11package controller
22
33import (
4+ "bytes"
45 v1 "cloudstackctl/apis/v1"
56 "cloudstackctl/db"
67 "cloudstackctl/pkg/handlers"
@@ -97,11 +98,60 @@ func (c *Controller) handleApply(w http.ResponseWriter, r *http.Request) {
9798 }
9899 applyErr = c .applyApplication (& app )
99100 case "Component" :
100- var comp v1.Component
101- if err := json .Unmarshal (body , & comp ); err != nil {
101+ // Accept two forms for Component.spec.virtualMachineSpec:
102+ // - a string referencing a named VirtualMachineSpec
103+ // - an inline object describing a VirtualMachineSpec
104+ type compSpecIn struct {
105+ VirtualMachineSpec json.RawMessage `json:"virtualMachineSpec"`
106+ Replicas int `json:"replicas"`
107+ Overrides v1.ComponentOverrides `json:"overrides"`
108+ HealthChecks []v1.HealthCheck `json:"healthChecks"`
109+ }
110+ type compIn struct {
111+ APIVersion string `json:"apiVersion"`
112+ Kind string `json:"kind"`
113+ Metadata v1.Metadata `json:"metadata"`
114+ Spec compSpecIn `json:"spec"`
115+ Status v1.Status `json:"status"`
116+ }
117+
118+ var ci compIn
119+ if err := json .Unmarshal (body , & ci ); err != nil {
102120 http .Error (w , "failed to parse Component" , http .StatusBadRequest )
103121 return
104122 }
123+
124+ comp := v1.Component {
125+ APIVersion : ci .APIVersion ,
126+ Kind : ci .Kind ,
127+ Metadata : ci .Metadata ,
128+ Spec : v1.ComponentSpec {
129+ Replicas : ci .Spec .Replicas ,
130+ Overrides : ci .Spec .Overrides ,
131+ HealthChecks : ci .Spec .HealthChecks ,
132+ },
133+ }
134+
135+ // Interpret VirtualMachineSpec field which may be a string or object
136+ if len (ci .Spec .VirtualMachineSpec ) > 0 {
137+ // If it starts with a quote it's a JSON string
138+ b := ci .Spec .VirtualMachineSpec
139+ // trim whitespace
140+ trimmed := bytes .TrimSpace (b )
141+ if len (trimmed ) > 0 && trimmed [0 ] == '"' {
142+ var ref string
143+ if err := json .Unmarshal (b , & ref ); err == nil {
144+ comp .Spec .VirtualMachineSpec = ref
145+ }
146+ } else {
147+ // Attempt to decode inline VirtualMachineSpec
148+ var vms v1.VirtualMachineSpec
149+ if err := json .Unmarshal (b , & vms ); err == nil {
150+ comp .EffectiveSpec = vms
151+ }
152+ }
153+ }
154+
105155 applyErr = c .applyComponent (& comp )
106156 case "VirtualMachine" :
107157 var vm v1.VirtualMachine
@@ -119,7 +169,7 @@ func (c *Controller) handleApply(w http.ResponseWriter, r *http.Request) {
119169
120170 if applyErr != nil {
121171 log .Printf ("apply error for kind=%s: %v" , kind , applyErr )
122- http .Error (w , "failed to apply resource" , http .StatusInternalServerError )
172+ http .Error (w , fmt . Sprintf ( "failed to apply resource: %v" , applyErr ) , http .StatusInternalServerError )
123173 return
124174 }
125175
@@ -618,11 +668,11 @@ func compareVMSpec(a, b v1.VirtualMachineSpec) bool {
618668 if a .Project != b .Project {
619669 return false
620670 }
621- if len (a .NetworkIDs ) != len (b .NetworkIDs ) {
671+ if len (a .Networks ) != len (b .Networks ) {
622672 return false
623673 }
624- for i := range a .NetworkIDs {
625- if a .NetworkIDs [i ] != b .NetworkIDs [i ] {
674+ for i := range a .Networks {
675+ if a .Networks [i ] != b .Networks [i ] {
626676 return false
627677 }
628678 }
0 commit comments