@@ -17,6 +17,7 @@ import (
17
17
apiEquality "k8s.io/apimachinery/pkg/api/equality"
18
18
19
19
vmopv1 "github.com/vmware-tanzu/vm-operator/api/v1alpha1"
20
+ "github.com/vmware-tanzu/vm-operator/pkg/conditions"
20
21
"github.com/vmware-tanzu/vm-operator/pkg/context"
21
22
"github.com/vmware-tanzu/vm-operator/pkg/lib"
22
23
"github.com/vmware-tanzu/vm-operator/pkg/util"
@@ -114,17 +115,27 @@ func GetCloudInitMetadata(vm *vmopv1.VirtualMachine,
114
115
return string (metadataBytes ), nil
115
116
}
116
117
118
+ // ErrWithReason encapsulates the error type as well as a human-readable reason that will be
119
+ // used to set the Reason field on the Condition set on the object.
120
+ type ErrWithReason struct {
121
+ error
122
+ conditionReason string
123
+ }
124
+
117
125
func GetCloudInitPrepCustSpec (
118
126
cloudInitMetadata string ,
119
- updateArgs VMUpdateArgs ) (* vimTypes.VirtualMachineConfigSpec , * vimTypes.CustomizationSpec , error ) {
127
+ updateArgs VMUpdateArgs ) (* vimTypes.VirtualMachineConfigSpec , * vimTypes.CustomizationSpec , * ErrWithReason ) {
120
128
121
129
userdata := updateArgs .VMMetadata .Data ["user-data" ]
122
130
123
131
if userdata != "" {
124
132
// Ensure the data is normalized first to plain-text.
125
133
plainText , err := util .TryToDecodeBase64Gzip ([]byte (userdata ))
126
134
if err != nil {
127
- return nil , nil , fmt .Errorf ("decoding cloud-init prep userdata failed %v" , err )
135
+ return nil , nil , & ErrWithReason {
136
+ error : fmt .Errorf ("decoding cloud-init prep userdata failed %v" , err ),
137
+ conditionReason : vmopv1 .VirtualMachineMetadataFormatInvalidReason ,
138
+ }
128
139
}
129
140
userdata = plainText
130
141
}
@@ -147,17 +158,27 @@ func GetCloudInitPrepCustSpec(
147
158
func GetCloudInitGuestInfoCustSpec (
148
159
cloudInitMetadata string ,
149
160
config * vimTypes.VirtualMachineConfigInfo ,
150
- updateArgs VMUpdateArgs ) (* vimTypes.VirtualMachineConfigSpec , error ) {
161
+ updateArgs VMUpdateArgs ) (* vimTypes.VirtualMachineConfigSpec , * ErrWithReason ) {
151
162
152
163
extraConfig := map [string ]string {}
153
164
154
165
encodedMetadata , err := EncodeGzipBase64 (cloudInitMetadata )
155
166
if err != nil {
156
- return nil , fmt .Errorf ("encoding cloud-init metadata failed %v" , err )
167
+ return nil , & ErrWithReason {
168
+ error : fmt .Errorf ("encoding cloud-init metadata failed %v" , err ),
169
+ conditionReason : vmopv1 .VirtualMachineMetadataFormatInvalidReason ,
170
+ }
157
171
}
158
172
extraConfig [constants .CloudInitGuestInfoMetadata ] = encodedMetadata
159
173
extraConfig [constants .CloudInitGuestInfoMetadataEncoding ] = "gzip+base64"
160
174
175
+ if len (encodedMetadata ) > int (constants .CloudInitGuestInfoMaxSize ) {
176
+ return nil , & ErrWithReason {
177
+ error : fmt .Errorf ("size of cloud-init guest info exceeds the maximum allowed size of %s" , constants .CloudInitGuestInfoMaxSize .String ()),
178
+ conditionReason : vmopv1 .VirtualMachineGuestInfoSizeExceededReason ,
179
+ }
180
+ }
181
+
161
182
var data string
162
183
// Check for the 'user-data' key as per official contract and API documentation.
163
184
// Additionally, To support the cluster bootstrap data supplied by CAPBK's secret,
@@ -173,16 +194,30 @@ func GetCloudInitGuestInfoCustSpec(
173
194
// Ensure the data is normalized first to plain-text.
174
195
plainText , err := util .TryToDecodeBase64Gzip ([]byte (data ))
175
196
if err != nil {
176
- return nil , fmt .Errorf ("decoding cloud-init userdata failed %v" , err )
197
+ return nil , & ErrWithReason {
198
+ error : fmt .Errorf ("decoding cloud-init userdata failed %v" , err ),
199
+ conditionReason : vmopv1 .VirtualMachineMetadataFormatInvalidReason ,
200
+ }
177
201
}
178
202
179
203
encodedUserdata , err := EncodeGzipBase64 (plainText )
180
204
if err != nil {
181
- return nil , fmt .Errorf ("encoding cloud-init userdata failed %v" , err )
205
+ return nil , & ErrWithReason {
206
+ error : fmt .Errorf ("encoding cloud-init userdata failed %v" , err ),
207
+ conditionReason : vmopv1 .VirtualMachineMetadataFormatInvalidReason ,
208
+ }
182
209
}
183
210
184
211
extraConfig [constants .CloudInitGuestInfoUserdata ] = encodedUserdata
185
212
extraConfig [constants .CloudInitGuestInfoUserdataEncoding ] = "gzip+base64"
213
+
214
+ if len (encodedUserdata ) > int (constants .CloudInitGuestInfoMaxSize ) ||
215
+ len (encodedUserdata )+ len (encodedMetadata ) > int (constants .CloudInitGuestInfoMaxSize ) {
216
+ return nil , & ErrWithReason {
217
+ error : fmt .Errorf ("size of cloud-init guest info exceeds the maximum allowed size of %s" , constants .CloudInitGuestInfoMaxSize .String ()),
218
+ conditionReason : vmopv1 .VirtualMachineGuestInfoSizeExceededReason ,
219
+ }
220
+ }
186
221
}
187
222
188
223
configSpec := & vimTypes.VirtualMachineConfigSpec {}
@@ -245,6 +280,11 @@ func customizeCloudInit(
245
280
246
281
cloudInitMetadata , err := GetCloudInitMetadata (vmCtx .VM , netplan , updateArgs .VMMetadata .Data )
247
282
if err != nil {
283
+ conditions .MarkFalse (vmCtx .VM ,
284
+ vmopv1 .VirtualMachineMetadataReadyCondition ,
285
+ vmopv1 .VirtualMachineMetadataFormatInvalidReason ,
286
+ vmopv1 .ConditionSeverityError ,
287
+ err .Error ())
248
288
return nil , nil , err
249
289
}
250
290
@@ -261,6 +301,12 @@ func customizeCloudInit(
261
301
}
262
302
263
303
if err != nil {
304
+ errWithReason := err .(ErrWithReason )
305
+ conditions .MarkFalse (vmCtx .VM ,
306
+ vmopv1 .VirtualMachineMetadataReadyCondition ,
307
+ errWithReason .conditionReason ,
308
+ vmopv1 .ConditionSeverityError ,
309
+ errWithReason .Error ())
264
310
return nil , nil , err
265
311
}
266
312
@@ -307,6 +353,7 @@ func (s *Session) customize(
307
353
if err != nil {
308
354
return err
309
355
}
356
+ conditions .MarkTrue (vmCtx .VM , vmopv1 .VirtualMachineMetadataReadyCondition )
310
357
311
358
if configSpec != nil {
312
359
defaultConfigSpec := & vimTypes.VirtualMachineConfigSpec {}
0 commit comments