diff --git a/hack/update-payload-crds.sh b/hack/update-payload-crds.sh index 37345ec072c..0b4454eeb28 100755 --- a/hack/update-payload-crds.sh +++ b/hack/update-payload-crds.sh @@ -24,7 +24,6 @@ crd_globs="\ operator/v1/zz_generated.crd-manifests/0000_50_openshift-controller-manager_02_openshiftcontrollermanagers*.crd.yaml machineconfiguration/v1/zz_generated.crd-manifests/*.crd.yaml machineconfiguration/v1alpha1/zz_generated.crd-manifests/0000_80_machine-config_01_internalreleaseimages*.crd.yaml - machineconfiguration/v1alpha1/zz_generated.crd-manifests/0000_80_machine-config_01_osimagestreams*.crd.yaml operator/v1/zz_generated.crd-manifests/0000_80_machine-config_01_machineconfigurations*.crd.yaml config/v1alpha1/zz_generated.crd-manifests/0000_10_config-operator_01_clustermonitoring*.crd.yaml config/v1alpha1/zz_generated.crd-manifests/0000_10_config-operator_01_criocredentialproviderconfigs*.crd.yaml diff --git a/machineconfiguration/v1/register.go b/machineconfiguration/v1/register.go index d0a88324f7f..d52f6480e87 100644 --- a/machineconfiguration/v1/register.go +++ b/machineconfiguration/v1/register.go @@ -38,6 +38,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &MachineOSConfigList{}, &MachineOSBuild{}, &MachineOSBuildList{}, + &OSImageStream{}, + &OSImageStreamList{}, &PinnedImageSet{}, &PinnedImageSetList{}, &MachineConfigNode{}, diff --git a/machineconfiguration/v1/tests/osimagestreams.machineconfiguration.openshift.io/OSStreams.yaml b/machineconfiguration/v1/tests/osimagestreams.machineconfiguration.openshift.io/OSStreams.yaml new file mode 100644 index 00000000000..6544684f237 --- /dev/null +++ b/machineconfiguration/v1/tests/osimagestreams.machineconfiguration.openshift.io/OSStreams.yaml @@ -0,0 +1,662 @@ +apiVersion: apiextensions.k8s.io/v1 # Hack because controller-gen complains if we don't have this +name: "[TechPreview] OSStreams" +crdName: osimagestreams.machineconfiguration.openshift.io +featureGates: + - OSStreams +tests: + onCreate: + - name: Should reject creation without spec.defaultStream + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: {} + expectedError: "spec.defaultStream: Required value" + + - name: Should be able to create a minimal OSImageStream + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + expected: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + + - name: Should reject a resource not named cluster + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: another-resource + spec: + defaultStream: rhel-coreos + expectedError: "Invalid value: \"object\": osimagestream is a singleton, .metadata.name must be 'cluster'" + + - name: Should reject spec.defaultStream with invalid characters + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: "invalid@stream!" + expectedError: "a RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character." + + - name: Should reject spec.defaultStream that is too long + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: "this-is-a-very-long-stream-name-that-exceeds-the-maximum-allowed-length-of-253-characters-for-rfc1123-subdomain-validation-which-is-used-to-ensure-compatibility-with-dns-and-kubernetes-naming-standards-and-this-string-needs-to-be-even-longer-to-properly-test-the-limit" + expectedError: "spec.defaultStream: Too long: may not be more than 253 bytes" + + onUpdate: + - name: Should be able to report a well formatted list of image streams + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + updated: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + status: + defaultStream: "rhel-coreos" + availableStreams: + - name: rhel-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + - name: rhel10-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e + expected: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + status: + defaultStream: "rhel-coreos" + availableStreams: + - name: rhel-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + - name: rhel10-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e + + - name: Should be able to update spec.defaultStream to a different valid value + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + updated: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel10-coreos + expected: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel10-coreos + + - name: Should reject updating spec.defaultStream to invalid characters + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + updated: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: "invalid@stream!" + expectedError: "a RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character." + + - name: Should reject image URL without digest + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + updated: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + status: + defaultStream: "rhel-coreos" + availableStreams: + - name: rhel-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev:latest + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + expectedStatusError: "the OCI Image reference must end with a valid '@sha256:' suffix" + + - name: Should reject image URL with invalid digest length + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + updated: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + status: + defaultStream: "rhel-coreos" + availableStreams: + - name: rhel-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:abc123 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + expectedStatusError: "the OCI Image reference must end with a valid '@sha256:' suffix, where '' is 64 characters long" + + - name: Should reject stream name with invalid characters + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + updated: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + status: + defaultStream: "rhel@coreos!" + availableStreams: + - name: "rhel@coreos!" + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + expectedStatusError: "a RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character." + + - name: Should reject stream name that is too long + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + updated: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + status: + defaultStream: "rhel-coreos" + availableStreams: + - name: "this-is-a-very-long-stream-name-that-exceeds-the-maximum-allowed-length-of-253-characters-for-rfc1123-subdomain-validation-which-is-used-to-ensure-compatibility-with-dns-and-kubernetes-naming-standards-and-this-string-needs-to-be-even-longer-to-properly-test-the-limit" + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + - name: "rhel-coreos" + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + expectedStatusError: "status.availableStreams[0].name: Too long: may not be more than 253 bytes" + + - name: Should reject image URL without proper host format + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + updated: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + status: + defaultStream: "rhel-coreos" + availableStreams: + - name: rhel-coreos + osImage: invalid_host/image@sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + expectedStatusError: "the OCI Image name should follow the host[:port][/namespace]/name format" + + - name: Should accept defaultStream that references an existing stream + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + updated: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + status: + defaultStream: rhel-coreos + availableStreams: + - name: rhel-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + - name: rhel10-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e + expected: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + status: + defaultStream: rhel-coreos + availableStreams: + - name: rhel-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + - name: rhel10-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e + + - name: Should reject updating spec.defaultStream to a stream not in status.availableStreams + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + status: + defaultStream: rhel-coreos + availableStreams: + - name: rhel-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + - name: rhel10-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e + updated: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: non-existent-stream + status: + defaultStream: rhel-coreos + availableStreams: + - name: rhel-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + - name: rhel10-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e + expectedError: "spec.defaultStream must reference an existing stream name from status.availableStreams" + + - name: Should accept status update removing a stream when spec is unchanged + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + status: + defaultStream: rhel-coreos + availableStreams: + - name: rhel-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + - name: rhel10-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e + updated: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + status: + defaultStream: rhel10-coreos + availableStreams: + - name: rhel10-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e + expected: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + status: + defaultStream: rhel10-coreos + availableStreams: + - name: rhel10-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e + + - name: Should reject an status update without defaultStream + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + updated: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + status: + availableStreams: + - name: rhel-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + expectedStatusError: "status.defaultStream: Required value" + + - name: Should reject an status update without availableStreams + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + updated: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + status: + defaultStream: rhel-coreos + expectedStatusError: "status.availableStreams: Required value" + + - name: Should reject an status update with empty availableStreams + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + updated: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + status: + defaultStream: rhel-coreos + availableStreams: [] + expectedStatusError: "status.availableStreams: Invalid value: 0: availableStreams in body should have at least 1 items" + + - name: Should reject defaultStream that does not reference an existing stream + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + updated: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + status: + defaultStream: non-existent-stream + availableStreams: + - name: rhel-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + expectedStatusError: "defaultStream must reference a stream name from availableStreams" + + - name: Should reject defaultStream with invalid characters + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + updated: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + status: + defaultStream: "invalid@stream!" + availableStreams: + - name: rhel-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + expectedStatusError: "a RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character." + + - name: Should reject defaultStream that is too long + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + updated: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + status: + defaultStream: "this-is-a-very-long-stream-name-that-exceeds-the-maximum-allowed-length-of-253-characters-for-rfc1123-subdomain-validation-which-is-used-to-ensure-compatibility-with-dns-and-kubernetes-naming-standards-and-this-string-needs-to-be-even-longer-to-properly-test-the-limit" + availableStreams: + - name: rhel-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + expectedStatusError: "status.defaultStream: Too long: may not be more than 253 bytes" + + - name: Should allow status update when spec.defaultStream is stale after forced upgrade + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: old-removed-stream + status: + defaultStream: rhel-coreos + availableStreams: + - name: rhel-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + - name: rhel10-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e + updated: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: old-removed-stream + status: + defaultStream: rhel10-coreos + availableStreams: + - name: rhel-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + - name: rhel10-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e + expected: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: old-removed-stream + status: + defaultStream: rhel10-coreos + availableStreams: + - name: rhel-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + - name: rhel10-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e + + - name: Should reject changing stale spec.defaultStream to another invalid value after forced upgrade + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: old-removed-stream + status: + defaultStream: rhel-coreos + availableStreams: + - name: rhel-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + - name: rhel10-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e + updated: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: another-invalid-stream + status: + defaultStream: rhel-coreos + availableStreams: + - name: rhel-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + - name: rhel10-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e + expectedError: "spec.defaultStream must reference an existing stream name from status.availableStreams" + + - name: Should reject removing spec.defaultStream once it has been set + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + updated: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: {} + expectedError: "spec.defaultStream: Required value" + + - name: Should allow updating stale spec.defaultStream to a valid stream after forced upgrade + initial: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: old-removed-stream + status: + defaultStream: rhel-coreos + availableStreams: + - name: rhel-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + - name: rhel10-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e + updated: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + status: + defaultStream: rhel-coreos + availableStreams: + - name: rhel-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + - name: rhel10-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e + expected: | + apiVersion: machineconfiguration.openshift.io/v1 + kind: OSImageStream + metadata: + name: cluster + spec: + defaultStream: rhel-coreos + status: + defaultStream: rhel-coreos + availableStreams: + - name: rhel-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8 + - name: rhel10-coreos + osImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b + osExtensionsImage: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e diff --git a/machineconfiguration/v1/types_osimagestream.go b/machineconfiguration/v1/types_osimagestream.go new file mode 100644 index 00000000000..162bd98aacd --- /dev/null +++ b/machineconfiguration/v1/types_osimagestream.go @@ -0,0 +1,162 @@ +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// OSImageStream describes a set of streams and associated images available +// for the MachineConfigPools to be used as base OS images. +// +// The resource is a singleton named "cluster". +// +// Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer). +// +openshift:compatibility-gen:level=1 +// +kubebuilder:object:root=true +// +kubebuilder:resource:path=osimagestreams,scope=Cluster +// +kubebuilder:subresource:status +// +openshift:api-approved.openshift.io=https://github.com/openshift/api/pull/2555 +// +openshift:file-pattern=cvoRunLevel=0000_80,operatorName=machine-config,operatorOrdering=01 +// +openshift:enable:FeatureGate=OSStreams +// +kubebuilder:metadata:labels=openshift.io/operator-managed= +// +kubebuilder:validation:XValidation:rule="self.metadata.name == 'cluster'",message="osimagestream is a singleton, .metadata.name must be 'cluster'" +// +kubebuilder:validation:XValidation:rule="self.spec == oldSelf.spec || !has(self.status) || self.spec.defaultStream in self.status.availableStreams.map(s, s.name)",message="spec.defaultStream must reference an existing stream name from status.availableStreams" +type OSImageStream struct { + metav1.TypeMeta `json:",inline"` + + // metadata is the standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + + // spec contains the desired OSImageStream config configuration. + // +required + Spec OSImageStreamSpec `json:"spec,omitzero,omitempty"` + + // status describes the last observed state of this OSImageStream. + // Populated by the MachineConfigOperator after reading release metadata. + // When not present, the controller has not yet reconciled this resource. + // +optional + Status OSImageStreamStatus `json:"status,omitempty,omitzero"` +} + +// OSImageStreamStatus describes the current state of a OSImageStream +// +kubebuilder:validation:XValidation:rule="self.defaultStream in self.availableStreams.map(s, s.name)",message="defaultStream must reference a stream name from availableStreams" +type OSImageStreamStatus struct { + + // availableStreams is a list of the available OS Image Streams that can be + // used as the base image for MachineConfigPools. + // availableStreams is required, must have at least one item, must not exceed + // 100 items, and must have unique entries keyed on the name field. + // + // +required + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=100 + // +listType=map + // +listMapKey=name + AvailableStreams []OSImageStreamSet `json:"availableStreams,omitempty"` + + // defaultStream is the name of the stream that should be used as the default + // when no specific stream is requested by a MachineConfigPool. + // + // It must be a valid RFC 1123 subdomain between 1 and 253 characters in length, + // consisting of lowercase alphanumeric characters, hyphens ('-'), and periods ('.'), + // and must reference the name of one of the streams in availableStreams. + // + // +required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:validation:XValidation:rule="!format.dns1123Subdomain().validate(self).hasValue()",message="a RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character." + DefaultStream string `json:"defaultStream,omitempty"` +} + +// OSImageStreamSpec defines the desired state of a OSImageStream. +type OSImageStreamSpec struct { + // defaultStream is the desired name of the stream that should be used as the + // default when no specific stream is requested by a MachineConfigPool. + // + // This field is set by the installer during installation. Users may need to + // update it if the currently selected stream is no longer available, for + // example when the stream has reached its End of Life. + // The MachineConfigOperator uses this value to determine which stream from + // status.availableStreams to apply as the default for MachineConfigPools + // that do not specify a stream override. + // + // When status.availableStreams has been populated by the operator, updating + // this field requires that the new value references the name of one of the + // streams in status.availableStreams. Status-only updates by the operator + // are not subject to this constraint, allowing the operator to update + // availableStreams independently of this field. + // During initial creation, before the operator has populated status, any + // valid value is accepted. + // + // For upgrade scenarios where the source OCP version doesn't have this CRD + // the MCO creates and populates the OSImageStream cluster singleton setting + // this field with the proper value based on the source OCP version. + // + // It must be a valid RFC 1123 subdomain between 1 and 253 characters in length, + // consisting of lowercase alphanumeric characters, hyphens ('-'), and periods ('.'). + // + // +required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:validation:XValidation:rule="!format.dns1123Subdomain().validate(self).hasValue()",message="a RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character." + DefaultStream string `json:"defaultStream,omitempty"` +} + +type OSImageStreamSet struct { + // name is the required identifier of the stream. + // + // name is determined by the operator based on the OCI label of the + // discovered OS or Extension Image. + // + // Must be a valid RFC 1123 subdomain between 1 and 253 characters in length, + // consisting of lowercase alphanumeric characters, hyphens ('-'), and periods ('.'). + // + // +required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:validation:XValidation:rule="!format.dns1123Subdomain().validate(self).hasValue()",message="a RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character." + Name string `json:"name,omitempty"` + + // osImage is a required OS Image referenced by digest. + // + // osImage contains the immutable, fundamental operating system components, including the kernel + // and base utilities, that define the core environment for the node's host operating system. + // + // The format of the image pull spec is: host[:port][/namespace]/name@sha256:, + // where the digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9. + // The length of the whole spec must be between 1 to 447 characters. + // +required + OSImage ImageDigestFormat `json:"osImage,omitempty"` + + // osExtensionsImage is a required OS Extensions Image referenced by digest. + // + // osExtensionsImage bundles the extra repositories used to enable extensions, augmenting + // the base operating system without modifying the underlying immutable osImage. + // + // The format of the image pull spec is: host[:port][/namespace]/name@sha256:, + // where the digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9. + // The length of the whole spec must be between 1 to 447 characters. + // +required + OSExtensionsImage ImageDigestFormat `json:"osExtensionsImage,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// OSImageStreamList is a list of OSImageStream resources +// +// Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer). +// +openshift:compatibility-gen:level=1 +type OSImageStreamList struct { + metav1.TypeMeta `json:",inline"` + + // metadata is the standard list's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + metav1.ListMeta `json:"metadata"` + + Items []OSImageStream `json:"items"` +} diff --git a/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_osimagestreams.crd.yaml b/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_osimagestreams.crd.yaml new file mode 100644 index 00000000000..ac5a1106766 --- /dev/null +++ b/machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_osimagestreams.crd.yaml @@ -0,0 +1,208 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.openshift.io: https://github.com/openshift/api/pull/2555 + api.openshift.io/merged-by-featuregates: "true" + include.release.openshift.io/ibm-cloud-managed: "true" + include.release.openshift.io/self-managed-high-availability: "true" + release.openshift.io/feature-set: CustomNoUpgrade,DevPreviewNoUpgrade,TechPreviewNoUpgrade + labels: + openshift.io/operator-managed: "" + name: osimagestreams.machineconfiguration.openshift.io +spec: + group: machineconfiguration.openshift.io + names: + kind: OSImageStream + listKind: OSImageStreamList + plural: osimagestreams + singular: osimagestream + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: |- + OSImageStream describes a set of streams and associated images available + for the MachineConfigPools to be used as base OS images. + + The resource is a singleton named "cluster". + + Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer). + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: spec contains the desired OSImageStream config configuration. + properties: + defaultStream: + description: |- + defaultStream is the desired name of the stream that should be used as the + default when no specific stream is requested by a MachineConfigPool. + + This field is set by the installer during installation. Users may need to + update it if the currently selected stream is no longer available, for + example when the stream has reached its End of Life. + The MachineConfigOperator uses this value to determine which stream from + status.availableStreams to apply as the default for MachineConfigPools + that do not specify a stream override. + + When status.availableStreams has been populated by the operator, updating + this field requires that the new value references the name of one of the + streams in status.availableStreams. Status-only updates by the operator + are not subject to this constraint, allowing the operator to update + availableStreams independently of this field. + During initial creation, before the operator has populated status, any + valid value is accepted. + + For upgrade scenarios where the source OCP version doesn't have this CRD + the MCO creates and populates the OSImageStream cluster singleton setting + this field with the proper value based on the source OCP version. + + It must be a valid RFC 1123 subdomain between 1 and 253 characters in length, + consisting of lowercase alphanumeric characters, hyphens ('-'), and periods ('.'). + maxLength: 253 + minLength: 1 + type: string + x-kubernetes-validations: + - message: a RFC 1123 subdomain must consist of lower case alphanumeric + characters, '-' or '.', and must start and end with an alphanumeric + character. + rule: '!format.dns1123Subdomain().validate(self).hasValue()' + required: + - defaultStream + type: object + status: + description: |- + status describes the last observed state of this OSImageStream. + Populated by the MachineConfigOperator after reading release metadata. + When not present, the controller has not yet reconciled this resource. + properties: + availableStreams: + description: |- + availableStreams is a list of the available OS Image Streams that can be + used as the base image for MachineConfigPools. + availableStreams is required, must have at least one item, must not exceed + 100 items, and must have unique entries keyed on the name field. + items: + properties: + name: + description: |- + name is the required identifier of the stream. + + name is determined by the operator based on the OCI label of the + discovered OS or Extension Image. + + Must be a valid RFC 1123 subdomain between 1 and 253 characters in length, + consisting of lowercase alphanumeric characters, hyphens ('-'), and periods ('.'). + maxLength: 253 + minLength: 1 + type: string + x-kubernetes-validations: + - message: a RFC 1123 subdomain must consist of lower case alphanumeric + characters, '-' or '.', and must start and end with an alphanumeric + character. + rule: '!format.dns1123Subdomain().validate(self).hasValue()' + osExtensionsImage: + description: |- + osExtensionsImage is a required OS Extensions Image referenced by digest. + + osExtensionsImage bundles the extra repositories used to enable extensions, augmenting + the base operating system without modifying the underlying immutable osImage. + + The format of the image pull spec is: host[:port][/namespace]/name@sha256:, + where the digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9. + The length of the whole spec must be between 1 to 447 characters. + maxLength: 447 + minLength: 1 + type: string + x-kubernetes-validations: + - message: the OCI Image reference must end with a valid '@sha256:' + suffix, where '' is 64 characters long + rule: (self.split('@').size() == 2 && self.split('@')[1].matches('^sha256:[a-f0-9]{64}$')) + - message: the OCI Image name should follow the host[:port][/namespace]/name + format, resembling a valid URL without the scheme + rule: (self.split('@')[0].matches('^([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9-]+(:[0-9]{2,5})?/([a-zA-Z0-9-_]{0,61}/)?[a-zA-Z0-9-_.]*?$')) + osImage: + description: |- + osImage is a required OS Image referenced by digest. + + osImage contains the immutable, fundamental operating system components, including the kernel + and base utilities, that define the core environment for the node's host operating system. + + The format of the image pull spec is: host[:port][/namespace]/name@sha256:, + where the digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9. + The length of the whole spec must be between 1 to 447 characters. + maxLength: 447 + minLength: 1 + type: string + x-kubernetes-validations: + - message: the OCI Image reference must end with a valid '@sha256:' + suffix, where '' is 64 characters long + rule: (self.split('@').size() == 2 && self.split('@')[1].matches('^sha256:[a-f0-9]{64}$')) + - message: the OCI Image name should follow the host[:port][/namespace]/name + format, resembling a valid URL without the scheme + rule: (self.split('@')[0].matches('^([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9-]+(:[0-9]{2,5})?/([a-zA-Z0-9-_]{0,61}/)?[a-zA-Z0-9-_.]*?$')) + required: + - name + - osExtensionsImage + - osImage + type: object + maxItems: 100 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + defaultStream: + description: |- + defaultStream is the name of the stream that should be used as the default + when no specific stream is requested by a MachineConfigPool. + + It must be a valid RFC 1123 subdomain between 1 and 253 characters in length, + consisting of lowercase alphanumeric characters, hyphens ('-'), and periods ('.'), + and must reference the name of one of the streams in availableStreams. + maxLength: 253 + minLength: 1 + type: string + x-kubernetes-validations: + - message: a RFC 1123 subdomain must consist of lower case alphanumeric + characters, '-' or '.', and must start and end with an alphanumeric + character. + rule: '!format.dns1123Subdomain().validate(self).hasValue()' + required: + - availableStreams + - defaultStream + type: object + x-kubernetes-validations: + - message: defaultStream must reference a stream name from availableStreams + rule: self.defaultStream in self.availableStreams.map(s, s.name) + required: + - spec + type: object + x-kubernetes-validations: + - message: osimagestream is a singleton, .metadata.name must be 'cluster' + rule: self.metadata.name == 'cluster' + - message: spec.defaultStream must reference an existing stream name from + status.availableStreams + rule: self.spec == oldSelf.spec || !has(self.status) || self.spec.defaultStream + in self.status.availableStreams.map(s, s.name) + served: true + storage: true + subresources: + status: {} diff --git a/machineconfiguration/v1/zz_generated.deepcopy.go b/machineconfiguration/v1/zz_generated.deepcopy.go index a42a2f36ed0..9b738f8622d 100644 --- a/machineconfiguration/v1/zz_generated.deepcopy.go +++ b/machineconfiguration/v1/zz_generated.deepcopy.go @@ -1553,6 +1553,67 @@ func (in *NetworkInfo) DeepCopy() *NetworkInfo { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OSImageStream) DeepCopyInto(out *OSImageStream) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSImageStream. +func (in *OSImageStream) DeepCopy() *OSImageStream { + if in == nil { + return nil + } + out := new(OSImageStream) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *OSImageStream) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OSImageStreamList) DeepCopyInto(out *OSImageStreamList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]OSImageStream, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSImageStreamList. +func (in *OSImageStreamList) DeepCopy() *OSImageStreamList { + if in == nil { + return nil + } + out := new(OSImageStreamList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *OSImageStreamList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OSImageStreamReference) DeepCopyInto(out *OSImageStreamReference) { *out = *in @@ -1569,6 +1630,59 @@ func (in *OSImageStreamReference) DeepCopy() *OSImageStreamReference { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OSImageStreamSet) DeepCopyInto(out *OSImageStreamSet) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSImageStreamSet. +func (in *OSImageStreamSet) DeepCopy() *OSImageStreamSet { + if in == nil { + return nil + } + out := new(OSImageStreamSet) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OSImageStreamSpec) DeepCopyInto(out *OSImageStreamSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSImageStreamSpec. +func (in *OSImageStreamSpec) DeepCopy() *OSImageStreamSpec { + if in == nil { + return nil + } + out := new(OSImageStreamSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OSImageStreamStatus) DeepCopyInto(out *OSImageStreamStatus) { + *out = *in + if in.AvailableStreams != nil { + in, out := &in.AvailableStreams, &out.AvailableStreams + *out = make([]OSImageStreamSet, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSImageStreamStatus. +func (in *OSImageStreamStatus) DeepCopy() *OSImageStreamStatus { + if in == nil { + return nil + } + out := new(OSImageStreamStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ObjectReference) DeepCopyInto(out *ObjectReference) { *out = *in diff --git a/machineconfiguration/v1/zz_generated.featuregated-crd-manifests.yaml b/machineconfiguration/v1/zz_generated.featuregated-crd-manifests.yaml index c5d566e19a6..632c77f3e35 100644 --- a/machineconfiguration/v1/zz_generated.featuregated-crd-manifests.yaml +++ b/machineconfiguration/v1/zz_generated.featuregated-crd-manifests.yaml @@ -317,6 +317,30 @@ machineosconfigs.machineconfiguration.openshift.io: TopLevelFeatureGates: [] Version: v1 +osimagestreams.machineconfiguration.openshift.io: + Annotations: {} + ApprovedPRNumber: https://github.com/openshift/api/pull/2555 + CRDName: osimagestreams.machineconfiguration.openshift.io + Capability: "" + Category: "" + FeatureGates: + - OSStreams + FilenameOperatorName: machine-config + FilenameOperatorOrdering: "01" + FilenameRunLevel: "0000_80" + GroupName: machineconfiguration.openshift.io + HasStatus: true + KindName: OSImageStream + Labels: + openshift.io/operator-managed: "" + PluralName: osimagestreams + PrinterColumns: [] + Scope: Cluster + ShortNames: null + TopLevelFeatureGates: + - OSStreams + Version: v1 + pinnedimagesets.machineconfiguration.openshift.io: Annotations: {} ApprovedPRNumber: https://github.com/openshift/api/pull/2198 diff --git a/machineconfiguration/v1/zz_generated.featuregated-crd-manifests/osimagestreams.machineconfiguration.openshift.io/OSStreams.yaml b/machineconfiguration/v1/zz_generated.featuregated-crd-manifests/osimagestreams.machineconfiguration.openshift.io/OSStreams.yaml new file mode 100644 index 00000000000..48648dd341b --- /dev/null +++ b/machineconfiguration/v1/zz_generated.featuregated-crd-manifests/osimagestreams.machineconfiguration.openshift.io/OSStreams.yaml @@ -0,0 +1,208 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.openshift.io: https://github.com/openshift/api/pull/2555 + api.openshift.io/filename-cvo-runlevel: "0000_80" + api.openshift.io/filename-operator: machine-config + api.openshift.io/filename-ordering: "01" + feature-gate.release.openshift.io/OSStreams: "true" + labels: + openshift.io/operator-managed: "" + name: osimagestreams.machineconfiguration.openshift.io +spec: + group: machineconfiguration.openshift.io + names: + kind: OSImageStream + listKind: OSImageStreamList + plural: osimagestreams + singular: osimagestream + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: |- + OSImageStream describes a set of streams and associated images available + for the MachineConfigPools to be used as base OS images. + + The resource is a singleton named "cluster". + + Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer). + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: spec contains the desired OSImageStream config configuration. + properties: + defaultStream: + description: |- + defaultStream is the desired name of the stream that should be used as the + default when no specific stream is requested by a MachineConfigPool. + + This field is set by the installer during installation. Users may need to + update it if the currently selected stream is no longer available, for + example when the stream has reached its End of Life. + The MachineConfigOperator uses this value to determine which stream from + status.availableStreams to apply as the default for MachineConfigPools + that do not specify a stream override. + + When status.availableStreams has been populated by the operator, updating + this field requires that the new value references the name of one of the + streams in status.availableStreams. Status-only updates by the operator + are not subject to this constraint, allowing the operator to update + availableStreams independently of this field. + During initial creation, before the operator has populated status, any + valid value is accepted. + + For upgrade scenarios where the source OCP version doesn't have this CRD + the MCO creates and populates the OSImageStream cluster singleton setting + this field with the proper value based on the source OCP version. + + It must be a valid RFC 1123 subdomain between 1 and 253 characters in length, + consisting of lowercase alphanumeric characters, hyphens ('-'), and periods ('.'). + maxLength: 253 + minLength: 1 + type: string + x-kubernetes-validations: + - message: a RFC 1123 subdomain must consist of lower case alphanumeric + characters, '-' or '.', and must start and end with an alphanumeric + character. + rule: '!format.dns1123Subdomain().validate(self).hasValue()' + required: + - defaultStream + type: object + status: + description: |- + status describes the last observed state of this OSImageStream. + Populated by the MachineConfigOperator after reading release metadata. + When not present, the controller has not yet reconciled this resource. + properties: + availableStreams: + description: |- + availableStreams is a list of the available OS Image Streams that can be + used as the base image for MachineConfigPools. + availableStreams is required, must have at least one item, must not exceed + 100 items, and must have unique entries keyed on the name field. + items: + properties: + name: + description: |- + name is the required identifier of the stream. + + name is determined by the operator based on the OCI label of the + discovered OS or Extension Image. + + Must be a valid RFC 1123 subdomain between 1 and 253 characters in length, + consisting of lowercase alphanumeric characters, hyphens ('-'), and periods ('.'). + maxLength: 253 + minLength: 1 + type: string + x-kubernetes-validations: + - message: a RFC 1123 subdomain must consist of lower case alphanumeric + characters, '-' or '.', and must start and end with an alphanumeric + character. + rule: '!format.dns1123Subdomain().validate(self).hasValue()' + osExtensionsImage: + description: |- + osExtensionsImage is a required OS Extensions Image referenced by digest. + + osExtensionsImage bundles the extra repositories used to enable extensions, augmenting + the base operating system without modifying the underlying immutable osImage. + + The format of the image pull spec is: host[:port][/namespace]/name@sha256:, + where the digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9. + The length of the whole spec must be between 1 to 447 characters. + maxLength: 447 + minLength: 1 + type: string + x-kubernetes-validations: + - message: the OCI Image reference must end with a valid '@sha256:' + suffix, where '' is 64 characters long + rule: (self.split('@').size() == 2 && self.split('@')[1].matches('^sha256:[a-f0-9]{64}$')) + - message: the OCI Image name should follow the host[:port][/namespace]/name + format, resembling a valid URL without the scheme + rule: (self.split('@')[0].matches('^([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9-]+(:[0-9]{2,5})?/([a-zA-Z0-9-_]{0,61}/)?[a-zA-Z0-9-_.]*?$')) + osImage: + description: |- + osImage is a required OS Image referenced by digest. + + osImage contains the immutable, fundamental operating system components, including the kernel + and base utilities, that define the core environment for the node's host operating system. + + The format of the image pull spec is: host[:port][/namespace]/name@sha256:, + where the digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9. + The length of the whole spec must be between 1 to 447 characters. + maxLength: 447 + minLength: 1 + type: string + x-kubernetes-validations: + - message: the OCI Image reference must end with a valid '@sha256:' + suffix, where '' is 64 characters long + rule: (self.split('@').size() == 2 && self.split('@')[1].matches('^sha256:[a-f0-9]{64}$')) + - message: the OCI Image name should follow the host[:port][/namespace]/name + format, resembling a valid URL without the scheme + rule: (self.split('@')[0].matches('^([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9-]+(:[0-9]{2,5})?/([a-zA-Z0-9-_]{0,61}/)?[a-zA-Z0-9-_.]*?$')) + required: + - name + - osExtensionsImage + - osImage + type: object + maxItems: 100 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + defaultStream: + description: |- + defaultStream is the name of the stream that should be used as the default + when no specific stream is requested by a MachineConfigPool. + + It must be a valid RFC 1123 subdomain between 1 and 253 characters in length, + consisting of lowercase alphanumeric characters, hyphens ('-'), and periods ('.'), + and must reference the name of one of the streams in availableStreams. + maxLength: 253 + minLength: 1 + type: string + x-kubernetes-validations: + - message: a RFC 1123 subdomain must consist of lower case alphanumeric + characters, '-' or '.', and must start and end with an alphanumeric + character. + rule: '!format.dns1123Subdomain().validate(self).hasValue()' + required: + - availableStreams + - defaultStream + type: object + x-kubernetes-validations: + - message: defaultStream must reference a stream name from availableStreams + rule: self.defaultStream in self.availableStreams.map(s, s.name) + required: + - spec + type: object + x-kubernetes-validations: + - message: osimagestream is a singleton, .metadata.name must be 'cluster' + rule: self.metadata.name == 'cluster' + - message: spec.defaultStream must reference an existing stream name from + status.availableStreams + rule: self.spec == oldSelf.spec || !has(self.status) || self.spec.defaultStream + in self.status.availableStreams.map(s, s.name) + served: true + storage: true + subresources: + status: {} diff --git a/machineconfiguration/v1/zz_generated.swagger_doc_generated.go b/machineconfiguration/v1/zz_generated.swagger_doc_generated.go index 0bf471c4797..7369c02db0c 100644 --- a/machineconfiguration/v1/zz_generated.swagger_doc_generated.go +++ b/machineconfiguration/v1/zz_generated.swagger_doc_generated.go @@ -717,6 +717,55 @@ func (MachineOSImageBuilder) SwaggerDoc() map[string]string { return map_MachineOSImageBuilder } +var map_OSImageStream = map[string]string{ + "": "OSImageStream describes a set of streams and associated images available for the MachineConfigPools to be used as base OS images.\n\nThe resource is a singleton named \"cluster\".\n\nCompatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).", + "metadata": "metadata is the standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", + "spec": "spec contains the desired OSImageStream config configuration.", + "status": "status describes the last observed state of this OSImageStream. Populated by the MachineConfigOperator after reading release metadata. When not present, the controller has not yet reconciled this resource.", +} + +func (OSImageStream) SwaggerDoc() map[string]string { + return map_OSImageStream +} + +var map_OSImageStreamList = map[string]string{ + "": "OSImageStreamList is a list of OSImageStream resources\n\nCompatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).", + "metadata": "metadata is the standard list's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", +} + +func (OSImageStreamList) SwaggerDoc() map[string]string { + return map_OSImageStreamList +} + +var map_OSImageStreamSet = map[string]string{ + "name": "name is the required identifier of the stream.\n\nname is determined by the operator based on the OCI label of the discovered OS or Extension Image.\n\nMust be a valid RFC 1123 subdomain between 1 and 253 characters in length, consisting of lowercase alphanumeric characters, hyphens ('-'), and periods ('.').", + "osImage": "osImage is a required OS Image referenced by digest.\n\nosImage contains the immutable, fundamental operating system components, including the kernel and base utilities, that define the core environment for the node's host operating system.\n\nThe format of the image pull spec is: host[:port][/namespace]/name@sha256:, where the digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9. The length of the whole spec must be between 1 to 447 characters.", + "osExtensionsImage": "osExtensionsImage is a required OS Extensions Image referenced by digest.\n\nosExtensionsImage bundles the extra repositories used to enable extensions, augmenting the base operating system without modifying the underlying immutable osImage.\n\nThe format of the image pull spec is: host[:port][/namespace]/name@sha256:, where the digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9. The length of the whole spec must be between 1 to 447 characters.", +} + +func (OSImageStreamSet) SwaggerDoc() map[string]string { + return map_OSImageStreamSet +} + +var map_OSImageStreamSpec = map[string]string{ + "": "OSImageStreamSpec defines the desired state of a OSImageStream.", + "defaultStream": "defaultStream is the desired name of the stream that should be used as the default when no specific stream is requested by a MachineConfigPool.\n\nThis field is set by the installer during installation. Users may need to update it if the currently selected stream is no longer available, for example when the stream has reached its End of Life. The MachineConfigOperator uses this value to determine which stream from status.availableStreams to apply as the default for MachineConfigPools that do not specify a stream override.\n\nWhen status.availableStreams has been populated by the operator, updating this field requires that the new value references the name of one of the streams in status.availableStreams. Status-only updates by the operator are not subject to this constraint, allowing the operator to update availableStreams independently of this field. During initial creation, before the operator has populated status, any valid value is accepted.\n\nFor upgrade scenarios where the source OCP version doesn't have this CRD the MCO creates and populates the OSImageStream cluster singleton setting this field with the proper value based on the source OCP version.\n\nIt must be a valid RFC 1123 subdomain between 1 and 253 characters in length, consisting of lowercase alphanumeric characters, hyphens ('-'), and periods ('.').", +} + +func (OSImageStreamSpec) SwaggerDoc() map[string]string { + return map_OSImageStreamSpec +} + +var map_OSImageStreamStatus = map[string]string{ + "": "OSImageStreamStatus describes the current state of a OSImageStream", + "availableStreams": "availableStreams is a list of the available OS Image Streams that can be used as the base image for MachineConfigPools. availableStreams is required, must have at least one item, must not exceed 100 items, and must have unique entries keyed on the name field.", + "defaultStream": "defaultStream is the name of the stream that should be used as the default when no specific stream is requested by a MachineConfigPool.\n\nIt must be a valid RFC 1123 subdomain between 1 and 253 characters in length, consisting of lowercase alphanumeric characters, hyphens ('-'), and periods ('.'), and must reference the name of one of the streams in availableStreams.", +} + +func (OSImageStreamStatus) SwaggerDoc() map[string]string { + return map_OSImageStreamStatus +} + var map_PinnedImageRef = map[string]string{ "": "PinnedImageRef represents a reference to an OCI image", "name": "name is an OCI Image referenced by digest. The format of the image pull spec is: host[:port][/namespace]/name@sha256:, where the digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9. The length of the whole spec must be between 1 to 447 characters.", diff --git a/payload-manifests/crds/0000_80_machine-config_01_osimagestreams.crd.yaml b/payload-manifests/crds/0000_80_machine-config_01_osimagestreams.crd.yaml index d18a1ecaa3e..ac5a1106766 100644 --- a/payload-manifests/crds/0000_80_machine-config_01_osimagestreams.crd.yaml +++ b/payload-manifests/crds/0000_80_machine-config_01_osimagestreams.crd.yaml @@ -19,7 +19,7 @@ spec: singular: osimagestream scope: Cluster versions: - - name: v1alpha1 + - name: v1 schema: openAPIV3Schema: description: |- @@ -28,7 +28,7 @@ spec: The resource is a singleton named "cluster". - Compatibility level 4: No compatibility is provided, the API can change at any point for any reason. These capabilities should not be used by applications needing long term support. + Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer). properties: apiVersion: description: |- @@ -70,8 +70,9 @@ spec: During initial creation, before the operator has populated status, any valid value is accepted. - When omitted, the operator determines the default stream automatically. - Once set, this field cannot be removed. + For upgrade scenarios where the source OCP version doesn't have this CRD + the MCO creates and populates the OSImageStream cluster singleton setting + this field with the proper value based on the source OCP version. It must be a valid RFC 1123 subdomain between 1 and 253 characters in length, consisting of lowercase alphanumeric characters, hyphens ('-'), and periods ('.'). @@ -83,10 +84,9 @@ spec: characters, '-' or '.', and must start and end with an alphanumeric character. rule: '!format.dns1123Subdomain().validate(self).hasValue()' + required: + - defaultStream type: object - x-kubernetes-validations: - - message: spec.defaultStream cannot be removed once set - rule: '!has(oldSelf.defaultStream) || has(self.defaultStream)' status: description: |- status describes the last observed state of this OSImageStream. @@ -200,8 +200,8 @@ spec: rule: self.metadata.name == 'cluster' - message: spec.defaultStream must reference an existing stream name from status.availableStreams - rule: self.spec == oldSelf.spec || !has(self.spec.defaultStream) || !has(self.status) - || self.spec.defaultStream in self.status.availableStreams.map(s, s.name) + rule: self.spec == oldSelf.spec || !has(self.status) || self.spec.defaultStream + in self.status.availableStreams.map(s, s.name) served: true storage: true subresources: