Skip to content

Commit c66c21d

Browse files
committed
image: Fix various immutability validations
There were several instances in the image API where we were asserting immutability on an optional field, but failing to assert that the value cannot be set and unset.
1 parent 28cccb9 commit c66c21d

File tree

5 files changed

+199
-131
lines changed

5 files changed

+199
-131
lines changed

internal/controllers/image/reconcile.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,10 @@ func getGlanceImage(ctx context.Context, orcImage *orcv1alpha1.Image, imageClien
321321

322322
// getImageName returns the name of the glance image we should use.
323323
func getImageName(orcImage *orcv1alpha1.Image) string {
324-
return ptr.Deref(orcImage.Spec.Resource.Name, orcImage.Name)
324+
if orcImage.Spec.Resource.Name != "" {
325+
return orcImage.Spec.Resource.Name
326+
}
327+
return orcImage.Name
325328
}
326329

327330
func listOptsFromImportFilter(filter *orcv1alpha1.ImageFilter) images.ListOptsBuilder {

orc/api/v1alpha1/image_types.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -218,21 +218,18 @@ type ImageContent struct {
218218
// ContainerFormat is the format of the image container.
219219
// qcow2 and raw images do not usually have a container. This is specified as "bare", which is also the default.
220220
// Permitted values are ami, ari, aki, bare, ovf, ova, and docker.
221-
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="containerFormat is immutable"
222221
// +kubebuilder:default:=bare
223222
// +optional
224223
ContainerFormat ImageContainerFormat `json:"containerFormat,omitempty"`
225224

226225
// DiskFormat is the format of the disk image.
227226
// Normal values are "qcow2", or "raw". Glance may be configured to support others.
228-
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="diskFormat is immutable"
229227
// +kubebuilder:validation:Required
230228
DiskFormat ImageDiskFormat `json:"diskFormat"`
231229

232230
// Download describes how to obtain image data by downloading it from a URL.
233231
// Must be set when creating a managed image.
234-
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="download is immutable"
235-
// +unionMember
232+
// +kubebuilder:validation:Required
236233
Download *ImageContentSourceDownload `json:"download,omitempty"`
237234
}
238235

@@ -273,21 +270,25 @@ type ImageHash struct {
273270
}
274271

275272
// ImageResourceSpec contains the desired state of a Glance image
273+
// +kubebuilder:validation:XValidation:rule="has(self.name) ? self.name == oldSelf.name : !has(oldSelf.name)",message="name is immutable"
274+
// +kubebuilder:validation:XValidation:rule="has(self.protected) ? self.protected == oldSelf.protected : !has(oldSelf.protected)",message="name is immutable"
275+
// +kubebuilder:validation:XValidation:rule="has(self.tags) ? self.tags == oldSelf.tags : !has(oldSelf.tags)",message="tags is immutable"
276+
// +kubebuilder:validation:XValidation:rule="has(self.visibility) ? self.visibility == oldSelf.visibility : !has(oldSelf.visibility)",message="visibility is immutable"
277+
// +kubebuilder:validation:XValidation:rule="has(self.properties) ? self.properties == oldSelf.properties : !has(oldSelf.properties)",message="properties is immutable"
276278
type ImageResourceSpec struct {
277279
// Name will be the name of the created Glance image. If not specified, the
278280
// name of the Image object will be used.
279-
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="imageName is immutable"
281+
// +kubebuilder:validation:MinLength:=1
282+
// +kubebuilder:validation:MaxLength:=1000
280283
// +optional
281-
Name *string `json:"name,omitempty"`
284+
Name string `json:"name,omitempty"`
282285

283286
// Protected specifies that the image is protected from deletion.
284287
// If not specified, the default is false.
285-
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="protected is immutable"
286288
// +optional
287289
Protected *bool `json:"protected,omitempty"`
288290

289291
// Tags is a list of tags which will be applied to the image. A tag has a maximum length of 255 characters.
290-
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="tags is immutable"
291292
// +listType=set
292293
// +optional
293294
Tags []ImageTag `json:"tags,omitempty"`
@@ -298,7 +299,6 @@ type ImageResourceSpec struct {
298299
Visibility *ImageVisibility `json:"visibility,omitempty"`
299300

300301
// Properties is metadata available to consumers of the image
301-
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="properties is immutable"
302302
// +optional
303303
Properties *ImageProperties `json:"properties,omitempty"`
304304

orc/api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 0 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

orc/config/crd/bases/openstack.k-orc.cloud_images.yaml

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,6 @@ spec:
163163
- ova
164164
- docker
165165
type: string
166-
x-kubernetes-validations:
167-
- message: containerFormat is immutable
168-
rule: self == oldSelf
169166
diskFormat:
170167
description: |-
171168
DiskFormat is the format of the disk image.
@@ -183,9 +180,6 @@ spec:
183180
- ploop
184181
- iso
185182
type: string
186-
x-kubernetes-validations:
187-
- message: diskFormat is immutable
188-
rule: self == oldSelf
189183
download:
190184
description: |-
191185
Download describes how to obtain image data by downloading it from a URL.
@@ -241,11 +235,9 @@ spec:
241235
required:
242236
- url
243237
type: object
244-
x-kubernetes-validations:
245-
- message: download is immutable
246-
rule: self == oldSelf
247238
required:
248239
- diskFormat
240+
- download
249241
type: object
250242
x-kubernetes-validations:
251243
- message: content is immutable
@@ -254,10 +246,9 @@ spec:
254246
description: |-
255247
Name will be the name of the created Glance image. If not specified, the
256248
name of the Image object will be used.
249+
maxLength: 1000
250+
minLength: 1
257251
type: string
258-
x-kubernetes-validations:
259-
- message: imageName is immutable
260-
rule: self == oldSelf
261252
properties:
262253
description: Properties is metadata available to consumers of
263254
the image
@@ -402,17 +393,11 @@ spec:
402393
minimum: 1
403394
type: integer
404395
type: object
405-
x-kubernetes-validations:
406-
- message: properties is immutable
407-
rule: self == oldSelf
408396
protected:
409397
description: |-
410398
Protected specifies that the image is protected from deletion.
411399
If not specified, the default is false.
412400
type: boolean
413-
x-kubernetes-validations:
414-
- message: protected is immutable
415-
rule: self == oldSelf
416401
tags:
417402
description: Tags is a list of tags which will be applied to the
418403
image. A tag has a maximum length of 255 characters.
@@ -422,9 +407,6 @@ spec:
422407
type: string
423408
type: array
424409
x-kubernetes-list-type: set
425-
x-kubernetes-validations:
426-
- message: tags is immutable
427-
rule: self == oldSelf
428410
visibility:
429411
description: Visibility of the image
430412
enum:
@@ -437,6 +419,20 @@ spec:
437419
- message: visibility is immutable
438420
rule: self == oldSelf
439421
type: object
422+
x-kubernetes-validations:
423+
- message: name is immutable
424+
rule: 'has(self.name) ? self.name == oldSelf.name : !has(oldSelf.name)'
425+
- message: name is immutable
426+
rule: 'has(self.protected) ? self.protected == oldSelf.protected
427+
: !has(oldSelf.protected)'
428+
- message: tags is immutable
429+
rule: 'has(self.tags) ? self.tags == oldSelf.tags : !has(oldSelf.tags)'
430+
- message: visibility is immutable
431+
rule: 'has(self.visibility) ? self.visibility == oldSelf.visibility
432+
: !has(oldSelf.visibility)'
433+
- message: properties is immutable
434+
rule: 'has(self.properties) ? self.properties == oldSelf.properties
435+
: !has(oldSelf.properties)'
440436
required:
441437
- cloudCredentialsRef
442438
type: object

0 commit comments

Comments
 (0)