77 "fmt"
88 "log"
99 "net/url"
10+ "strings"
1011
1112 cs "github.com/apache/cloudstack-go/v2/cloudstack"
1213
@@ -20,87 +21,111 @@ var getCmd = &cobra.Command{
2021 Long : `List resources managed by cloudstackctl (Application/Component/VirtualMachine/Network/Volume/etc.)` ,
2122 Run : func (cmd * cobra.Command , args []string ) {
2223 if len (args ) < 1 {
23- log .Fatal ("Usage: cloudstackctl get <resource-type> [name]" )
24+ log .Fatal ("Usage: cloudstackctl get <resource-type>[,...] [name]" )
25+ }
26+
27+ // Support comma-separated resource types: e.g. "apps,comps,vms"
28+ rawKinds := strings .Split (args [0 ], "," )
29+ kinds := make ([]string , 0 , len (rawKinds ))
30+ for _ , k := range rawKinds {
31+ kinds = append (kinds , normalizeResourceType (k ))
2432 }
2533
26- resourceType := normalizeResourceType (args [0 ])
2734 name := ""
2835 if len (args ) > 1 {
2936 name = args [1 ]
3037 }
3138
32- // Standalone: call local handler wrapper
39+ // Standalone: call local handler wrapper. If any requested kind is
40+ // managed by the controller, fail in standalone mode.
3341 if standalone {
34- if resourceType == "Application" || resourceType == "Component" || resourceType == "VirtualMachineSpec" {
35- log .Fatalf ("'%s' is not supported in standalone mode" , resourceType )
36- }
37-
38- payload := map [string ]string {"kind" : resourceType }
39- if name != "" {
40- payload ["name" ] = name
42+ for _ , resourceType := range kinds {
43+ if resourceType == "Application" || resourceType == "Component" || resourceType == "VirtualMachineSpec" {
44+ log .Fatalf ("'%s' is not supported in standalone mode" , resourceType )
45+ }
4146 }
42- raw , _ := json .Marshal (payload )
43- if resp , err := handlers .GetCloudStackResource (raw ); err != nil {
44- log .Fatalf ("Local get failed: %v" , err )
45- } else {
46- handlers .PrintCloudStackResource (resourceType , resp )
47+ for i , resourceType := range kinds {
48+ payload := map [string ]string {"kind" : resourceType }
49+ if name != "" {
50+ payload ["name" ] = name
51+ }
52+ raw , _ := json .Marshal (payload )
53+ if resp , err := handlers .GetCloudStackResource (raw ); err != nil {
54+ log .Fatalf ("Local get failed: %v" , err )
55+ } else {
56+ if i > 0 {
57+ fmt .Printf ("\n " )
58+ }
59+ handlers .PrintCloudStackResource (resourceType , resp )
60+ }
4761 }
4862 return
4963 }
5064
51- // Cluster mode: forward to controller HTTP API (/list)
52- var endpoint = "/list"
53- q := url.Values {}
54- if getAll && resourceType == "VirtualMachine" {
55- q .Set ("all" , "true" )
56- }
57- q .Set ("kind" , resourceType )
58- if name != "" {
59- q .Set ("name" , name )
60- }
61- path := endpoint + "?" + q .Encode ()
62- body , err := ControllerRequest ("GET" , path , nil )
63- if err != nil {
64- log .Fatalf ("Failed to query controller: %v" , err )
65- }
65+ // Controller mode: query controller for each requested kind and print
66+ // results sequentially with simple headers.
67+ for i , resourceType := range kinds {
68+ var endpoint = "/list"
69+ q := url.Values {}
70+ if getAll && resourceType == "VirtualMachine" {
71+ q .Set ("all" , "true" )
72+ }
73+ q .Set ("kind" , resourceType )
74+ if name != "" {
75+ q .Set ("name" , name )
76+ }
77+ path := endpoint + "?" + q .Encode ()
78+ body , err := ControllerRequest ("GET" , path , nil )
79+ if err != nil {
80+ log .Fatalf ("Failed to query controller for %s: %v" , resourceType , err )
81+ }
6682
67- // If controller returned VM objects from DB, pretty-print them
68- if resourceType == "VirtualMachine" && ! getAll {
69- var vms []v1.VirtualMachine
70- if err := json .Unmarshal (body , & vms ); err == nil {
71- handlers .PrintVMsFromController (vms )
72- return
83+ if i > 0 {
84+ fmt .Printf ("\n " )
7385 }
74- }
7586
76- if tryDecodeAndPrint (resourceType , body ) {
77- return
78- }
87+ // If controller returned VM objects from DB, pretty-print them
88+ if resourceType == "VirtualMachine" && ! getAll {
89+ var vms []v1.VirtualMachine
90+ if err := json .Unmarshal (body , & vms ); err == nil {
91+ handlers .PrintVMsFromController (vms )
92+ continue
93+ }
94+ }
7995
80- // Controller may return DB-backed resources; print them in-table when possible
81- switch resourceType {
82- case "Component" :
83- var comps []v1.Component
84- if err := json .Unmarshal (body , & comps ); err == nil {
85- handlers .PrintComponents (comps )
86- return
96+ if tryDecodeAndPrint (resourceType , body ) {
97+ continue
8798 }
88- case "VirtualMachineSpec" :
89- var specs []v1.VirtualMachineSpecResource
90- if err := json .Unmarshal (body , & specs ); err == nil {
91- handlers .PrintVMSpecs (specs )
92- return
99+
100+ // Controller may return DB-backed resources; print them in-table when possible
101+ handled := false
102+ switch resourceType {
103+ case "Component" :
104+ var comps []v1.Component
105+ if err := json .Unmarshal (body , & comps ); err == nil {
106+ handlers .PrintComponents (comps )
107+ handled = true
108+ }
109+ case "VirtualMachineSpec" :
110+ var specs []v1.VirtualMachineSpecResource
111+ if err := json .Unmarshal (body , & specs ); err == nil {
112+ handlers .PrintVMSpecs (specs )
113+ handled = true
114+ }
115+ case "Application" :
116+ var apps []v1.Application
117+ if err := json .Unmarshal (body , & apps ); err == nil {
118+ handlers .PrintApplications (apps )
119+ handled = true
120+ }
93121 }
94- case "Application" :
95- var apps []v1.Application
96- if err := json .Unmarshal (body , & apps ); err == nil {
97- handlers .PrintApplications (apps )
98- return
122+ if handled {
123+ continue
99124 }
100- }
101125
102- // Fallback: print raw body
103- fmt .Println (string (body ))
126+ // Fallback: print raw body
127+ fmt .Println (string (body ))
128+ }
104129 },
105130}
106131
0 commit comments