From 8f7329ef242975bb28fd93c096616097f91ead30 Mon Sep 17 00:00:00 2001 From: Matthew Booth Date: Tue, 4 Nov 2025 16:37:29 +0000 Subject: [PATCH] Add ClusterAPI config --- .../generated_openapi/zz_generated.openapi.go | 309 ++++++++++ openapi/openapi.json | 174 ++++++ operator/v1alpha1/register.go | 2 + .../ClusterAPIMachineManagement.yaml | 551 ++++++++++++++++++ operator/v1alpha1/types_clusterapi.go | 186 ++++++ ...pi_01_clusterapis-CustomNoUpgrade.crd.yaml | 239 ++++++++ ...1_clusterapis-DevPreviewNoUpgrade.crd.yaml | 239 ++++++++ ..._clusterapis-TechPreviewNoUpgrade.crd.yaml | 239 ++++++++ operator/v1alpha1/zz_generated.deepcopy.go | 168 ++++++ ..._generated.featuregated-crd-manifests.yaml | 23 + .../ClusterAPIMachineManagement.yaml | 239 ++++++++ .../zz_generated.swagger_doc_generated.go | 71 +++ 12 files changed, 2440 insertions(+) create mode 100644 operator/v1alpha1/tests/clusterapis.operator.openshift.io/ClusterAPIMachineManagement.yaml create mode 100644 operator/v1alpha1/types_clusterapi.go create mode 100644 operator/v1alpha1/zz_generated.crd-manifests/0000_30_cluster-api_01_clusterapis-CustomNoUpgrade.crd.yaml create mode 100644 operator/v1alpha1/zz_generated.crd-manifests/0000_30_cluster-api_01_clusterapis-DevPreviewNoUpgrade.crd.yaml create mode 100644 operator/v1alpha1/zz_generated.crd-manifests/0000_30_cluster-api_01_clusterapis-TechPreviewNoUpgrade.crd.yaml create mode 100644 operator/v1alpha1/zz_generated.featuregated-crd-manifests/clusterapis.operator.openshift.io/ClusterAPIMachineManagement.yaml diff --git a/openapi/generated_openapi/zz_generated.openapi.go b/openapi/generated_openapi/zz_generated.openapi.go index 4e9847373a2..2d7f2133d02 100644 --- a/openapi/generated_openapi/zz_generated.openapi.go +++ b/openapi/generated_openapi/zz_generated.openapi.go @@ -1191,6 +1191,13 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/openshift/api/operator/v1.UpstreamResolvers": schema_openshift_api_operator_v1_UpstreamResolvers(ref), "github.com/openshift/api/operator/v1.VSphereCSIDriverConfigSpec": schema_openshift_api_operator_v1_VSphereCSIDriverConfigSpec(ref), "github.com/openshift/api/operator/v1alpha1.BackupJobReference": schema_openshift_api_operator_v1alpha1_BackupJobReference(ref), + "github.com/openshift/api/operator/v1alpha1.ClusterAPI": schema_openshift_api_operator_v1alpha1_ClusterAPI(ref), + "github.com/openshift/api/operator/v1alpha1.ClusterAPIInstallerComponent": schema_openshift_api_operator_v1alpha1_ClusterAPIInstallerComponent(ref), + "github.com/openshift/api/operator/v1alpha1.ClusterAPIInstallerComponentImage": schema_openshift_api_operator_v1alpha1_ClusterAPIInstallerComponentImage(ref), + "github.com/openshift/api/operator/v1alpha1.ClusterAPIInstallerRevision": schema_openshift_api_operator_v1alpha1_ClusterAPIInstallerRevision(ref), + "github.com/openshift/api/operator/v1alpha1.ClusterAPIList": schema_openshift_api_operator_v1alpha1_ClusterAPIList(ref), + "github.com/openshift/api/operator/v1alpha1.ClusterAPISpec": schema_openshift_api_operator_v1alpha1_ClusterAPISpec(ref), + "github.com/openshift/api/operator/v1alpha1.ClusterAPIStatus": schema_openshift_api_operator_v1alpha1_ClusterAPIStatus(ref), "github.com/openshift/api/operator/v1alpha1.ClusterVersionOperator": schema_openshift_api_operator_v1alpha1_ClusterVersionOperator(ref), "github.com/openshift/api/operator/v1alpha1.ClusterVersionOperatorList": schema_openshift_api_operator_v1alpha1_ClusterVersionOperatorList(ref), "github.com/openshift/api/operator/v1alpha1.ClusterVersionOperatorSpec": schema_openshift_api_operator_v1alpha1_ClusterVersionOperatorSpec(ref), @@ -60690,6 +60697,308 @@ func schema_openshift_api_operator_v1alpha1_BackupJobReference(ref common.Refere } } +func schema_openshift_api_operator_v1alpha1_ClusterAPI(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ClusterAPI provides configuration for the capi-operator.\n\nCompatibility 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.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Description: "metadata is the standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), + }, + }, + "spec": { + SchemaProps: spec.SchemaProps{ + Description: "spec is the specification of the desired behavior of the capi-operator.", + Ref: ref("github.com/openshift/api/operator/v1alpha1.ClusterAPISpec"), + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Description: "status defines the observed status of the capi-operator.", + Default: map[string]interface{}{}, + Ref: ref("github.com/openshift/api/operator/v1alpha1.ClusterAPIStatus"), + }, + }, + }, + Required: []string{"metadata"}, + }, + }, + Dependencies: []string{ + "github.com/openshift/api/operator/v1alpha1.ClusterAPISpec", "github.com/openshift/api/operator/v1alpha1.ClusterAPIStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + } +} + +func schema_openshift_api_operator_v1alpha1_ClusterAPIInstallerComponent(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ClusterAPIInstallerComponent defines a component which will be installed by this revision.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "image": { + SchemaProps: spec.SchemaProps{ + Description: "image defines an image source for a component. The image must contain a /capi-operator-installer directory containing the component manifests.", + Default: map[string]interface{}{}, + Ref: ref("github.com/openshift/api/operator/v1alpha1.ClusterAPIInstallerComponentImage"), + }, + }, + }, + Required: []string{"image"}, + }, + }, + Dependencies: []string{ + "github.com/openshift/api/operator/v1alpha1.ClusterAPIInstallerComponentImage"}, + } +} + +func schema_openshift_api_operator_v1alpha1_ClusterAPIInstallerComponentImage(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ClusterAPIInstallerComponentImage defines an image source for a component.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "digest": { + SchemaProps: spec.SchemaProps{ + Description: "digest is an image reference to the image containing the component manifests. The reference must be a valid image digest reference in the format host[:port][/namespace]/name@sha256:. The digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9. The length of the field must be between 1 to 447 characters.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"digest"}, + }, + }, + } +} + +func schema_openshift_api_operator_v1alpha1_ClusterAPIInstallerRevision(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Description: "name is the name of a revision.", + Type: []string{"string"}, + Format: "", + }, + }, + "revision": { + SchemaProps: spec.SchemaProps{ + Description: "revision is a monotonically increasing number that is assigned to a revision.", + Type: []string{"integer"}, + Format: "int64", + }, + }, + "contentID": { + SchemaProps: spec.SchemaProps{ + Description: "contentID uniquely identifies the content of this revision. The contentID must be between 1 and 255 characters long.", + Type: []string{"string"}, + Format: "", + }, + }, + "unmanagedCustomResourceDefinitions": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "set", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "unmanagedCustomResourceDefinitions is a list of the names of ClusterResourceDefinition (CRD) objects which are included in this revision, but which should not be installed or updated. If not set, all CRDs in the revision will be managed by the CAPI operator.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "components": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "components is list of components which will be installed by this revision. Components will be installed in the order they are listed.\n\nThe maximum number of components is 32.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/openshift/api/operator/v1alpha1.ClusterAPIInstallerComponent"), + }, + }, + }, + }, + }, + }, + Required: []string{"name", "revision", "contentID", "components"}, + }, + }, + Dependencies: []string{ + "github.com/openshift/api/operator/v1alpha1.ClusterAPIInstallerComponent"}, + } +} + +func schema_openshift_api_operator_v1alpha1_ClusterAPIList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ClusterAPIList contains a list of ClusterAPI configurations\n\nCompatibility 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.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Description: "metadata is the standard list's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), + }, + }, + "items": { + SchemaProps: spec.SchemaProps{ + Description: "items contains the items", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/openshift/api/operator/v1alpha1.ClusterAPI"), + }, + }, + }, + }, + }, + }, + Required: []string{"metadata", "items"}, + }, + }, + Dependencies: []string{ + "github.com/openshift/api/operator/v1alpha1.ClusterAPI", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + } +} + +func schema_openshift_api_operator_v1alpha1_ClusterAPISpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ClusterAPISpec defines the desired configuration of the capi-operator.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "unmanagedCustomResourceDefinitions": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "set", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "unmanagedCustomResourceDefinitions is a list of ClusterResourceDefinition (CRD) names that should not be managed by the capi-operator installer controller. This allows external actors to own specific CRDs while capi-operator manages others.\n\nEach CRD name must be a valid DNS-1123 subdomain consisting of lowercase alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character, with a maximum length of 253 characters. Example: \"clusters.cluster.x-k8s.io\"\n\nItems cannot be removed from this list once added.\n\nThe maximum number of unmanagedCustomResourceDefinitions is 128.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func schema_openshift_api_operator_v1alpha1_ClusterAPIStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ClusterAPIStatus describes the current state of the capi-operator.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "currentRevision": { + SchemaProps: spec.SchemaProps{ + Description: "currentRevision is the name of the most recently fully applied revision. It is written by the installer controller. If it is absent, it indicates that no revision has been fully applied yet. If set, currentRevision must correspond to an entry in the revisions list.", + Type: []string{"string"}, + Format: "", + }, + }, + "desiredRevision": { + SchemaProps: spec.SchemaProps{ + Description: "desiredRevision is the name of the desired revision. It is written by the revision controller. It must be set to the name of the entry in the revisions list with the highest revision number.", + Type: []string{"string"}, + Format: "", + }, + }, + "revisions": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "atomic", + }, + }, + SchemaProps: spec.SchemaProps{ + Description: "revisions is a list of all currently active revisions. A revision is active until the installer controller updates currentRevision to a later revision. It is written by the revision controller.\n\nThe maximum number of revisions is 16. All revisions must have a unique name. All revisions must have a unique revision number. When adding a revision, the revision number must be greater than the highest revision number in the list. Revisions are immutable, although they can be deleted.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/openshift/api/operator/v1alpha1.ClusterAPIInstallerRevision"), + }, + }, + }, + }, + }, + }, + Required: []string{"desiredRevision", "revisions"}, + }, + }, + Dependencies: []string{ + "github.com/openshift/api/operator/v1alpha1.ClusterAPIInstallerRevision"}, + } +} + func schema_openshift_api_operator_v1alpha1_ClusterVersionOperator(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/openapi/openapi.json b/openapi/openapi.json index 4683af72761..e3fbe39b35a 100644 --- a/openapi/openapi.json +++ b/openapi/openapi.json @@ -35319,6 +35319,109 @@ } } }, + "com.github.openshift.api.operator.v1alpha1.ClusterAPI": { + "description": "ClusterAPI provides configuration for the capi-operator.\n\nCompatibility 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.", + "type": "object", + "required": [ + "metadata", + "spec" + ], + "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": { + "description": "metadata is the standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", + "default": {}, + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta" + }, + "spec": { + "description": "spec is the specification of the desired behavior of the capi-operator.", + "default": {}, + "$ref": "#/definitions/com.github.openshift.api.operator.v1alpha1.ClusterAPISpec" + }, + "status": { + "description": "status defines the observed status of the capi-operator.", + "default": {}, + "$ref": "#/definitions/com.github.openshift.api.operator.v1alpha1.ClusterAPIStatus" + } + } + }, + "com.github.openshift.api.operator.v1alpha1.ClusterAPIList": { + "description": "ClusterAPIList contains a list of ClusterAPI configurations\n\nCompatibility 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.", + "type": "object", + "required": [ + "metadata", + "items" + ], + "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" + }, + "items": { + "description": "items contains the items", + "type": "array", + "items": { + "default": {}, + "$ref": "#/definitions/com.github.openshift.api.operator.v1alpha1.ClusterAPI" + } + }, + "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": { + "description": "metadata is the standard list's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", + "default": {}, + "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ListMeta" + } + } + }, + "com.github.openshift.api.operator.v1alpha1.ClusterAPISpec": { + "description": "ClusterAPISpec defines the desired configuration of the capi-operator.", + "type": "object", + "properties": { + "unmanagedCustomResourceDefinitions": { + "description": "unmanagedCustomResourceDefinitions is a list of ClusterResourceDefinition (CRD) names that should not be managed by the capi-operator installer controller. This allows external actors to own specific CRDs while capi-operator manages others.\n\nEach CRD name must be a valid DNS-1123 subdomain consisting of lowercase alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character, with a maximum length of 253 characters. Example: \"clusters.cluster.x-k8s.io\"\n\nItems cannot be removed from this list once added.\n\nThe maximum number of unmanagedCustomResourceDefinitions is 128.", + "type": "array", + "items": { + "type": "string", + "default": "" + }, + "x-kubernetes-list-type": "set" + } + } + }, + "com.github.openshift.api.operator.v1alpha1.ClusterAPIStatus": { + "description": "ClusterAPIStatus describes the current state of the capi-operator.", + "type": "object", + "properties": { + "activeConfigMaps": { + "description": "activeConfigMaps is a list of ConfigMap names that the installer controller has successfully reconciled. This represents the currently deployed CAPI provider components.\n\nEach ConfigMap name must be a valid DNS-1123 label consisting of lowercase alphanumeric characters or hyphens, starting and ending with an alphanumeric character, with a maximum length of 63 characters.\n\nThis field is owned by the installer controller and is updated atomically after a successful reconciliation.\n\nThe maximum number of activeConfigMaps is 128.", + "type": "array", + "items": { + "type": "string", + "default": "" + }, + "x-kubernetes-list-type": "atomic" + }, + "targetConfigMaps": { + "description": "targetConfigMaps is a list of ConfigMap names that the staging controller has validated and approved for reconciliation. The installer controller will reconcile these ConfigMaps.\n\nEach ConfigMap name must be a valid DNS-1123 label consisting of lowercase alphanumeric characters or hyphens, starting and ending with an alphanumeric character, with a maximum length of 63 characters.\n\nThis field is owned by the staging controller and is updated atomically to a consistent set of transport ConfigMaps that have passed validation checks.\n\nThe maximum number of targetConfigMaps is 128.", + "type": "array", + "items": { + "type": "string", + "default": "" + }, + "x-kubernetes-list-type": "atomic" + } + } + }, "com.github.openshift.api.operator.v1alpha1.ClusterVersionOperator": { "description": "ClusterVersionOperator holds cluster-wide information about the Cluster Version Operator.\n\nCompatibility 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.", "type": "object", @@ -51516,6 +51619,77 @@ "description": "IntOrString is a type that can hold an int32 or a string. When used in JSON or YAML marshalling and unmarshalling, it produces or consumes the inner type. This allows you to have, for example, a JSON field that can accept a name or number.", "type": "string", "format": "int-or-string" + }, + "io.k8s.apimachinery.pkg.version.Info": { + "description": "Info contains versioning information. how we'll want to distribute that information.", + "type": "object", + "required": [ + "major", + "minor", + "gitVersion", + "gitCommit", + "gitTreeState", + "buildDate", + "goVersion", + "compiler", + "platform" + ], + "properties": { + "buildDate": { + "type": "string", + "default": "" + }, + "compiler": { + "type": "string", + "default": "" + }, + "emulationMajor": { + "description": "EmulationMajor is the major version of the emulation version", + "type": "string" + }, + "emulationMinor": { + "description": "EmulationMinor is the minor version of the emulation version", + "type": "string" + }, + "gitCommit": { + "type": "string", + "default": "" + }, + "gitTreeState": { + "type": "string", + "default": "" + }, + "gitVersion": { + "type": "string", + "default": "" + }, + "goVersion": { + "type": "string", + "default": "" + }, + "major": { + "description": "Major is the major version of the binary version", + "type": "string", + "default": "" + }, + "minCompatibilityMajor": { + "description": "MinCompatibilityMajor is the major version of the minimum compatibility version", + "type": "string" + }, + "minCompatibilityMinor": { + "description": "MinCompatibilityMinor is the minor version of the minimum compatibility version", + "type": "string" + }, + "minor": { + "description": "Minor is the minor version of the binary version", + "type": "string", + "default": "" + }, + "platform": { + "type": "string", + "default": "" + } + } } } } diff --git a/operator/v1alpha1/register.go b/operator/v1alpha1/register.go index 3e9b09ccede..ec19cba3a94 100644 --- a/operator/v1alpha1/register.go +++ b/operator/v1alpha1/register.go @@ -41,6 +41,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &EtcdBackupList{}, &ClusterVersionOperator{}, &ClusterVersionOperatorList{}, + &ClusterAPI{}, + &ClusterAPIList{}, ) return nil diff --git a/operator/v1alpha1/tests/clusterapis.operator.openshift.io/ClusterAPIMachineManagement.yaml b/operator/v1alpha1/tests/clusterapis.operator.openshift.io/ClusterAPIMachineManagement.yaml new file mode 100644 index 00000000000..365ac3ec19e --- /dev/null +++ b/operator/v1alpha1/tests/clusterapis.operator.openshift.io/ClusterAPIMachineManagement.yaml @@ -0,0 +1,551 @@ +apiVersion: apiextensions.k8s.io/v1 # Hack because controller-gen complains if we don't have this +name: "ClusterAPI" +crdName: clusterapis.operator.openshift.io +featureGate: ClusterAPIMachineManagement +tests: + onCreate: + - name: Should be able to create a minimal ClusterAPI + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + expected: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + + - name: Should be able to create ClusterAPI with unmanagedCustomResourceDefinitions + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + spec: + unmanagedCustomResourceDefinitions: + - clusters.cluster.x-k8s.io + - machines.cluster.x-k8s.io + expected: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + spec: + unmanagedCustomResourceDefinitions: + - clusters.cluster.x-k8s.io + - machines.cluster.x-k8s.io + + - name: Should reject empty string in unmanagedCustomResourceDefinitions + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + spec: + unmanagedCustomResourceDefinitions: + - "" + expectedError: "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters" + + - name: Should reject CRD name which is not a valid DNS-1123 subdomain in unmanagedCustomResourceDefinitions + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + spec: + unmanagedCustomResourceDefinitions: + - Clusters.cluster.x-k8s.io + expectedError: "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters" + + - name: Should accept valid CRD names with hyphens and dots in unmanagedCustomResourceDefinitions + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + spec: + unmanagedCustomResourceDefinitions: + - a.b.c.d + - name-with-hyphens.domain-with-hyphens.io + - valid-name.example.io + expected: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + spec: + unmanagedCustomResourceDefinitions: + - a.b.c.d + - name-with-hyphens.domain-with-hyphens.io + - valid-name.example.io + + onUpdate: + - name: Should not allow removing items from unmanagedCustomResourceDefinitions + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + spec: + unmanagedCustomResourceDefinitions: + - clusters.cluster.x-k8s.io + - machines.cluster.x-k8s.io + updated: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + spec: + unmanagedCustomResourceDefinitions: + - clusters.cluster.x-k8s.io + expectedError: "items cannot be removed from unmanagedCustomResourceDefinitions list" + + - name: Should not allow unsetting unmanagedCustomResourceDefinitions once set + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + spec: + unmanagedCustomResourceDefinitions: + - clusters.cluster.x-k8s.io + - machines.cluster.x-k8s.io + updated: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + expectedError: "unmanagedCustomResourceDefinitions cannot be unset once set" + + - name: Should allow adding items to unmanagedCustomResourceDefinitions + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + spec: + unmanagedCustomResourceDefinitions: + - clusters.cluster.x-k8s.io + updated: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + spec: + unmanagedCustomResourceDefinitions: + - clusters.cluster.x-k8s.io + - machinehealthchecks.cluster.x-k8s.io + - machines.cluster.x-k8s.io + expected: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + spec: + unmanagedCustomResourceDefinitions: + - clusters.cluster.x-k8s.io + - machinehealthchecks.cluster.x-k8s.io + - machines.cluster.x-k8s.io + + # Status subresource tests for revisions + + - name: Should reject status with revisions having duplicate names + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + updated: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + status: + desiredRevision: rev-2 + revisions: + - name: rev-1 + revision: 1 + contentID: content-1 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - name: rev-1 + revision: 2 + contentID: content-2 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + expectedStatusError: "each revision must have a unique name" + + - name: Should reject status with revisions having duplicate revision numbers + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + updated: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + status: + desiredRevision: rev-2 + revisions: + - name: rev-1 + revision: 1 + contentID: content-1 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - name: rev-2 + revision: 1 + contentID: content-2 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + expectedStatusError: "each revision must have a unique revision number" + + - name: Should reject desiredRevision not matching the revision with highest number + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + updated: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + status: + desiredRevision: rev-1 + revisions: + - name: rev-1 + revision: 1 + contentID: content-1 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - name: rev-2 + revision: 2 + contentID: content-2 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + expectedStatusError: "desiredRevision must be the name of the revision with the highest revision number" + + - name: Should accept desiredRevision matching the revision with highest number + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + updated: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + status: + desiredRevision: rev-2 + revisions: + - name: rev-1 + revision: 1 + contentID: content-1 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - name: rev-2 + revision: 2 + contentID: content-2 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + expected: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + status: + desiredRevision: rev-2 + revisions: + - name: rev-1 + revision: 1 + contentID: content-1 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - name: rev-2 + revision: 2 + contentID: content-2 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + + - name: Should reject currentRevision not corresponding to an entry in revisions list + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + updated: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + status: + currentRevision: nonexistent-rev + desiredRevision: rev-1 + revisions: + - name: rev-1 + revision: 1 + contentID: content-1 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + expectedStatusError: "currentRevision must correspond to an entry in the revisions list" + + - name: Should accept currentRevision corresponding to an entry in revisions list + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + updated: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + status: + currentRevision: rev-1 + desiredRevision: rev-1 + revisions: + - name: rev-1 + revision: 1 + contentID: content-1 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + expected: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + status: + currentRevision: rev-1 + desiredRevision: rev-1 + revisions: + - name: rev-1 + revision: 1 + contentID: content-1 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + - name: Should accept absent currentRevision + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + updated: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + status: + desiredRevision: rev-1 + revisions: + - name: rev-1 + revision: 1 + contentID: content-1 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + expected: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + status: + desiredRevision: rev-1 + revisions: + - name: rev-1 + revision: 1 + contentID: content-1 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + - name: Should reject modifying an existing revision + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + status: + desiredRevision: rev-1 + revisions: + - name: rev-1 + revision: 1 + contentID: content-1 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + updated: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + status: + desiredRevision: rev-1 + revisions: + - name: rev-1 + revision: 1 + contentID: modified-content + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + expectedStatusError: "revisions are immutable" + + - name: Should allow deleting a revision from the list + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + status: + desiredRevision: rev-2 + revisions: + - name: rev-1 + revision: 1 + contentID: content-1 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - name: rev-2 + revision: 2 + contentID: content-2 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + updated: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + status: + desiredRevision: rev-2 + revisions: + - name: rev-2 + revision: 2 + contentID: content-2 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + expected: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + status: + desiredRevision: rev-2 + revisions: + - name: rev-2 + revision: 2 + contentID: content-2 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + + - name: Should reject adding revision with number less than highest existing + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + status: + desiredRevision: rev-1 + revisions: + - name: rev-1 + revision: 5 + contentID: content-1 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + updated: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + status: + desiredRevision: rev-2 + revisions: + - name: rev-1 + revision: 5 + contentID: content-1 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - name: rev-2 + revision: 3 + contentID: content-2 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + expectedStatusError: "new revisions must have a revision number greater than all existing revisions" + + - name: Should accept adding revision with number greater than all existing + initial: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + status: + desiredRevision: rev-1 + revisions: + - name: rev-1 + revision: 1 + contentID: content-1 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + updated: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + status: + desiredRevision: rev-2 + revisions: + - name: rev-1 + revision: 1 + contentID: content-1 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - name: rev-2 + revision: 2 + contentID: content-2 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + expected: | + apiVersion: operator.openshift.io/v1alpha1 + kind: ClusterAPI + metadata: + name: cluster + status: + desiredRevision: rev-2 + revisions: + - name: rev-1 + revision: 1 + contentID: content-1 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - name: rev-2 + revision: 2 + contentID: content-2 + components: + - image: + digest: quay.io/openshift/cluster-api@sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb \ No newline at end of file diff --git a/operator/v1alpha1/types_clusterapi.go b/operator/v1alpha1/types_clusterapi.go new file mode 100644 index 00000000000..81da40bbd91 --- /dev/null +++ b/operator/v1alpha1/types_clusterapi.go @@ -0,0 +1,186 @@ +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + machineosconfigv1 "github.com/openshift/api/machineconfiguration/v1" +) + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:object:root=true +// +kubebuilder:resource:path=clusterapis,scope=Cluster +// +kubebuilder:subresource:status +// +openshift:api-approved.openshift.io=https://github.com/openshift/api/pull/2564 +// +openshift:file-pattern=cvoRunLevel=0000_30,operatorName=cluster-api,operatorOrdering=01 +// +openshift:enable:FeatureGate=ClusterAPIMachineManagement + +// ClusterAPI provides configuration for the capi-operator. +// +// 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. +// +openshift:compatibility-gen:level=4 +// +kubebuilder:validation:XValidation:rule="!has(oldSelf.spec) || !has(oldSelf.spec.unmanagedCustomResourceDefinitions) || has(self.spec.unmanagedCustomResourceDefinitions)",message="unmanagedCustomResourceDefinitions cannot be unset once set" +// +kubebuilder:validation:XValidation:rule="self.metadata.name == 'cluster'",message="clusterapi is a singleton, .metadata.name must be 'cluster'" +type ClusterAPI 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 + // +required + metav1.ObjectMeta `json:"metadata,omitempty"` + + // spec is the specification of the desired behavior of the capi-operator. + // +optional + Spec *ClusterAPISpec `json:"spec,omitempty"` + + // status defines the observed status of the capi-operator. + // +optional + Status ClusterAPIStatus `json:"status,omitzero"` +} + +// ClusterAPISpec defines the desired configuration of the capi-operator. +type ClusterAPISpec struct { + // unmanagedCustomResourceDefinitions is a list of ClusterResourceDefinition (CRD) + // names that should not be managed by the capi-operator installer + // controller. This allows external actors to own specific CRDs while + // capi-operator manages others. + // + // Each CRD name must be a valid DNS-1123 subdomain consisting of lowercase + // alphanumeric characters, '-' or '.', and must start and end with an + // alphanumeric character, with a maximum length of 253 characters. + // Example: "clusters.cluster.x-k8s.io" + // + // Items cannot be removed from this list once added. + // + // The maximum number of unmanagedCustomResourceDefinitions is 128. + // + // +optional + // +listType=set + // +kubebuilder:validation:MaxItems=128 + // +kubebuilder:validation:XValidation:rule="oldSelf.all(item, item in self)",message="items cannot be removed from unmanagedCustomResourceDefinitions list" + // +kubebuilder:validation:items:XValidation:rule="!format.dns1123Subdomain().validate(self).hasValue()",message="a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character." + // +kubebuilder:validation:items:MaxLength=253 + UnmanagedCustomResourceDefinitions []string `json:"unmanagedCustomResourceDefinitions,omitempty"` +} + +// RevisionName represents the name of a revision. The name must be between 1 +// and 255 characters long. +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=255 +type RevisionName string + +// ClusterAPIStatus describes the current state of the capi-operator. +// +kubebuilder:validation:MinProperties=1 +// +kubebuilder:validation:XValidation:rule="self.revisions.exists(r, r.name == self.desiredRevision && self.revisions.all(s, s.revision <= r.revision))",message="desiredRevision must be the name of the revision with the highest revision number" +// +kubebuilder:validation:XValidation:rule="!has(self.currentRevision) || self.revisions.exists(r, r.name == self.currentRevision)",message="currentRevision must correspond to an entry in the revisions list" +type ClusterAPIStatus struct { + // currentRevision is the name of the most recently fully applied revision. + // It is written by the installer controller. If it is absent, it indicates + // that no revision has been fully applied yet. + // If set, currentRevision must correspond to an entry in the revisions list. + // +optional + CurrentRevision RevisionName `json:"currentRevision,omitempty"` + + // desiredRevision is the name of the desired revision. It is written by the + // revision controller. It must be set to the name of the entry in the + // revisions list with the highest revision number. + // +required + DesiredRevision RevisionName `json:"desiredRevision,omitempty"` + + // revisions is a list of all currently active revisions. A revision is + // active until the installer controller updates currentRevision to a later + // revision. It is written by the revision controller. + // + // The maximum number of revisions is 16. + // All revisions must have a unique name. + // All revisions must have a unique revision number. + // When adding a revision, the revision number must be greater than the highest revision number in the list. + // Revisions are immutable, although they can be deleted. + // + // +required + // +listType=atomic + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=16 + // +kubebuilder:validation:XValidation:rule="self.all(x, self.exists_one(y, x.name == y.name))",message="each revision must have a unique name" + // +kubebuilder:validation:XValidation:rule="self.all(x, self.exists_one(y, x.revision == y.revision))",message="each revision must have a unique revision number" + // +kubebuilder:validation:XValidation:rule="self.all(new, oldSelf.exists(old, old.name == new.name) || oldSelf.all(old, new.revision > old.revision))",message="new revisions must have a revision number greater than all existing revisions" + // +kubebuilder:validation:XValidation:rule="oldSelf.all(old, !self.exists(new, new.name == old.name) || self.exists(new, new == old))",message="revisions are immutable" + Revisions []ClusterAPIInstallerRevision `json:"revisions,omitempty"` +} + +type ClusterAPIInstallerRevision struct { + // name is the name of a revision. + // +required + Name RevisionName `json:"name,omitempty"` + + // revision is a monotonically increasing number that is assigned to a revision. + // +required + // +kubebuilder:validation:Minimum=1 + Revision int64 `json:"revision,omitempty"` + + // contentID uniquely identifies the content of this revision. + // The contentID must be between 1 and 255 characters long. + // +required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=255 + ContentID string `json:"contentID,omitempty"` + + // unmanagedCustomResourceDefinitions is a list of the names of + // ClusterResourceDefinition (CRD) objects which are included in this + // revision, but which should not be installed or updated. If not set, all + // CRDs in the revision will be managed by the CAPI operator. + // +listType=set + // +kubebuilder:validation:items:XValidation:rule="!format.dns1123Subdomain().validate(self).hasValue()",message="a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character." + // +kubebuilder:validation:items:MaxLength=253 + // +kubebuilder:validation:MaxItems=128 + // +optional + UnmanagedCustomResourceDefinitions []string `json:"unmanagedCustomResourceDefinitions,omitempty"` + + // components is list of components which will be installed by this + // revision. Components will be installed in the order they are listed. + // + // The maximum number of components is 32. + // + // +required + // +listType=atomic + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=32 + Components []ClusterAPIInstallerComponent `json:"components,omitempty"` +} + +// ClusterAPIInstallerComponent defines a component which will be installed by this revision. +// +kubebuilder:validation:MaxProperties=1 +type ClusterAPIInstallerComponent struct { + // image defines an image source for a component. The image must contain a + // /capi-operator-installer directory containing the component manifests. + // +required + Image ClusterAPIInstallerComponentImage `json:"image,omitzero"` +} + +// ClusterAPIInstallerComponentImage defines an image source for a component. +type ClusterAPIInstallerComponentImage struct { + // digest is an image reference to the image containing the component manifests. The reference + // must be a valid image digest reference in the format host[:port][/namespace]/name@sha256:. + // The digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9. + // The length of the field must be between 1 to 447 characters. + // +required + Digest machineosconfigv1.ImageDigestFormat `json:"digest,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ClusterAPIList contains a list of ClusterAPI configurations +// +// 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. +// +openshift:compatibility-gen:level=4 +type ClusterAPIList 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 contains the items + Items []ClusterAPI `json:"items"` +} diff --git a/operator/v1alpha1/zz_generated.crd-manifests/0000_30_cluster-api_01_clusterapis-CustomNoUpgrade.crd.yaml b/operator/v1alpha1/zz_generated.crd-manifests/0000_30_cluster-api_01_clusterapis-CustomNoUpgrade.crd.yaml new file mode 100644 index 00000000000..091cb4727a8 --- /dev/null +++ b/operator/v1alpha1/zz_generated.crd-manifests/0000_30_cluster-api_01_clusterapis-CustomNoUpgrade.crd.yaml @@ -0,0 +1,239 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.openshift.io: https://github.com/openshift/api/pull/2564 + 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 + name: clusterapis.operator.openshift.io +spec: + group: operator.openshift.io + names: + kind: ClusterAPI + listKind: ClusterAPIList + plural: clusterapis + singular: clusterapi + scope: Cluster + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + ClusterAPI provides configuration for the capi-operator. + + 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. + 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 is the specification of the desired behavior of the + capi-operator. + properties: + unmanagedCustomResourceDefinitions: + description: |- + unmanagedCustomResourceDefinitions is a list of ClusterResourceDefinition (CRD) + names that should not be managed by the capi-operator installer + controller. This allows external actors to own specific CRDs while + capi-operator manages others. + + Each CRD name must be a valid DNS-1123 subdomain consisting of lowercase + alphanumeric characters, '-' or '.', and must start and end with an + alphanumeric character, with a maximum length of 253 characters. + Example: "clusters.cluster.x-k8s.io" + + Items cannot be removed from this list once added. + + The maximum number of unmanagedCustomResourceDefinitions is 128. + items: + maxLength: 253 + type: string + x-kubernetes-validations: + - message: a lowercase 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()' + maxItems: 128 + type: array + x-kubernetes-list-type: set + x-kubernetes-validations: + - message: items cannot be removed from unmanagedCustomResourceDefinitions + list + rule: oldSelf.all(item, item in self) + type: object + status: + description: status defines the observed status of the capi-operator. + minProperties: 1 + properties: + currentRevision: + description: |- + currentRevision is the name of the most recently fully applied revision. + It is written by the installer controller. If it is absent, it indicates + that no revision has been fully applied yet. + If set, currentRevision must correspond to an entry in the revisions list. + maxLength: 255 + minLength: 1 + type: string + desiredRevision: + description: |- + desiredRevision is the name of the desired revision. It is written by the + revision controller. It must be set to the name of the entry in the + revisions list with the highest revision number. + maxLength: 255 + minLength: 1 + type: string + revisions: + description: |- + revisions is a list of all currently active revisions. A revision is + active until the installer controller updates currentRevision to a later + revision. It is written by the revision controller. + + The maximum number of revisions is 16. + All revisions must have a unique name. + All revisions must have a unique revision number. + When adding a revision, the revision number must be greater than the highest revision number in the list. + Revisions are immutable, although they can be deleted. + items: + properties: + components: + description: |- + components is list of components which will be installed by this + revision. Components will be installed in the order they are listed. + + The maximum number of components is 32. + items: + description: ClusterAPIInstallerComponent defines a component + which will be installed by this revision. + maxProperties: 1 + properties: + image: + description: |- + image defines an image source for a component. The image must contain a + /capi-operator-installer directory containing the component manifests. + properties: + digest: + description: |- + digest is an image reference to the image containing the component manifests. The reference + must be a valid image digest reference in the format host[:port][/namespace]/name@sha256:. + The digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9. + The length of the field 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: + - digest + type: object + required: + - image + type: object + maxItems: 32 + minItems: 1 + type: array + x-kubernetes-list-type: atomic + contentID: + description: |- + contentID uniquely identifies the content of this revision. + The contentID must be between 1 and 255 characters long. + maxLength: 255 + minLength: 1 + type: string + name: + description: name is the name of a revision. + maxLength: 255 + minLength: 1 + type: string + revision: + description: revision is a monotonically increasing number that + is assigned to a revision. + format: int64 + minimum: 1 + type: integer + unmanagedCustomResourceDefinitions: + description: |- + unmanagedCustomResourceDefinitions is a list of the names of + ClusterResourceDefinition (CRD) objects which are included in this + revision, but which should not be installed or updated. If not set, all + CRDs in the revision will be managed by the CAPI operator. + items: + maxLength: 253 + type: string + x-kubernetes-validations: + - message: a lowercase 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()' + maxItems: 128 + type: array + x-kubernetes-list-type: set + required: + - components + - contentID + - name + - revision + type: object + maxItems: 16 + minItems: 1 + type: array + x-kubernetes-list-type: atomic + x-kubernetes-validations: + - message: each revision must have a unique name + rule: self.all(x, self.exists_one(y, x.name == y.name)) + - message: each revision must have a unique revision number + rule: self.all(x, self.exists_one(y, x.revision == y.revision)) + - message: new revisions must have a revision number greater than + all existing revisions + rule: self.all(new, oldSelf.exists(old, old.name == new.name) || + oldSelf.all(old, new.revision > old.revision)) + - message: revisions are immutable + rule: oldSelf.all(old, !self.exists(new, new.name == old.name) || + self.exists(new, new == old)) + required: + - desiredRevision + - revisions + type: object + x-kubernetes-validations: + - message: desiredRevision must be the name of the revision with the highest + revision number + rule: self.revisions.exists(r, r.name == self.desiredRevision && self.revisions.all(s, + s.revision <= r.revision)) + - message: currentRevision must correspond to an entry in the revisions + list + rule: '!has(self.currentRevision) || self.revisions.exists(r, r.name + == self.currentRevision)' + required: + - metadata + type: object + x-kubernetes-validations: + - message: unmanagedCustomResourceDefinitions cannot be unset once set + rule: '!has(oldSelf.spec) || !has(oldSelf.spec.unmanagedCustomResourceDefinitions) + || has(self.spec.unmanagedCustomResourceDefinitions)' + - message: clusterapi is a singleton, .metadata.name must be 'cluster' + rule: self.metadata.name == 'cluster' + served: true + storage: true + subresources: + status: {} diff --git a/operator/v1alpha1/zz_generated.crd-manifests/0000_30_cluster-api_01_clusterapis-DevPreviewNoUpgrade.crd.yaml b/operator/v1alpha1/zz_generated.crd-manifests/0000_30_cluster-api_01_clusterapis-DevPreviewNoUpgrade.crd.yaml new file mode 100644 index 00000000000..69321c3ed0a --- /dev/null +++ b/operator/v1alpha1/zz_generated.crd-manifests/0000_30_cluster-api_01_clusterapis-DevPreviewNoUpgrade.crd.yaml @@ -0,0 +1,239 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.openshift.io: https://github.com/openshift/api/pull/2564 + 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: DevPreviewNoUpgrade + name: clusterapis.operator.openshift.io +spec: + group: operator.openshift.io + names: + kind: ClusterAPI + listKind: ClusterAPIList + plural: clusterapis + singular: clusterapi + scope: Cluster + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + ClusterAPI provides configuration for the capi-operator. + + 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. + 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 is the specification of the desired behavior of the + capi-operator. + properties: + unmanagedCustomResourceDefinitions: + description: |- + unmanagedCustomResourceDefinitions is a list of ClusterResourceDefinition (CRD) + names that should not be managed by the capi-operator installer + controller. This allows external actors to own specific CRDs while + capi-operator manages others. + + Each CRD name must be a valid DNS-1123 subdomain consisting of lowercase + alphanumeric characters, '-' or '.', and must start and end with an + alphanumeric character, with a maximum length of 253 characters. + Example: "clusters.cluster.x-k8s.io" + + Items cannot be removed from this list once added. + + The maximum number of unmanagedCustomResourceDefinitions is 128. + items: + maxLength: 253 + type: string + x-kubernetes-validations: + - message: a lowercase 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()' + maxItems: 128 + type: array + x-kubernetes-list-type: set + x-kubernetes-validations: + - message: items cannot be removed from unmanagedCustomResourceDefinitions + list + rule: oldSelf.all(item, item in self) + type: object + status: + description: status defines the observed status of the capi-operator. + minProperties: 1 + properties: + currentRevision: + description: |- + currentRevision is the name of the most recently fully applied revision. + It is written by the installer controller. If it is absent, it indicates + that no revision has been fully applied yet. + If set, currentRevision must correspond to an entry in the revisions list. + maxLength: 255 + minLength: 1 + type: string + desiredRevision: + description: |- + desiredRevision is the name of the desired revision. It is written by the + revision controller. It must be set to the name of the entry in the + revisions list with the highest revision number. + maxLength: 255 + minLength: 1 + type: string + revisions: + description: |- + revisions is a list of all currently active revisions. A revision is + active until the installer controller updates currentRevision to a later + revision. It is written by the revision controller. + + The maximum number of revisions is 16. + All revisions must have a unique name. + All revisions must have a unique revision number. + When adding a revision, the revision number must be greater than the highest revision number in the list. + Revisions are immutable, although they can be deleted. + items: + properties: + components: + description: |- + components is list of components which will be installed by this + revision. Components will be installed in the order they are listed. + + The maximum number of components is 32. + items: + description: ClusterAPIInstallerComponent defines a component + which will be installed by this revision. + maxProperties: 1 + properties: + image: + description: |- + image defines an image source for a component. The image must contain a + /capi-operator-installer directory containing the component manifests. + properties: + digest: + description: |- + digest is an image reference to the image containing the component manifests. The reference + must be a valid image digest reference in the format host[:port][/namespace]/name@sha256:. + The digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9. + The length of the field 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: + - digest + type: object + required: + - image + type: object + maxItems: 32 + minItems: 1 + type: array + x-kubernetes-list-type: atomic + contentID: + description: |- + contentID uniquely identifies the content of this revision. + The contentID must be between 1 and 255 characters long. + maxLength: 255 + minLength: 1 + type: string + name: + description: name is the name of a revision. + maxLength: 255 + minLength: 1 + type: string + revision: + description: revision is a monotonically increasing number that + is assigned to a revision. + format: int64 + minimum: 1 + type: integer + unmanagedCustomResourceDefinitions: + description: |- + unmanagedCustomResourceDefinitions is a list of the names of + ClusterResourceDefinition (CRD) objects which are included in this + revision, but which should not be installed or updated. If not set, all + CRDs in the revision will be managed by the CAPI operator. + items: + maxLength: 253 + type: string + x-kubernetes-validations: + - message: a lowercase 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()' + maxItems: 128 + type: array + x-kubernetes-list-type: set + required: + - components + - contentID + - name + - revision + type: object + maxItems: 16 + minItems: 1 + type: array + x-kubernetes-list-type: atomic + x-kubernetes-validations: + - message: each revision must have a unique name + rule: self.all(x, self.exists_one(y, x.name == y.name)) + - message: each revision must have a unique revision number + rule: self.all(x, self.exists_one(y, x.revision == y.revision)) + - message: new revisions must have a revision number greater than + all existing revisions + rule: self.all(new, oldSelf.exists(old, old.name == new.name) || + oldSelf.all(old, new.revision > old.revision)) + - message: revisions are immutable + rule: oldSelf.all(old, !self.exists(new, new.name == old.name) || + self.exists(new, new == old)) + required: + - desiredRevision + - revisions + type: object + x-kubernetes-validations: + - message: desiredRevision must be the name of the revision with the highest + revision number + rule: self.revisions.exists(r, r.name == self.desiredRevision && self.revisions.all(s, + s.revision <= r.revision)) + - message: currentRevision must correspond to an entry in the revisions + list + rule: '!has(self.currentRevision) || self.revisions.exists(r, r.name + == self.currentRevision)' + required: + - metadata + type: object + x-kubernetes-validations: + - message: unmanagedCustomResourceDefinitions cannot be unset once set + rule: '!has(oldSelf.spec) || !has(oldSelf.spec.unmanagedCustomResourceDefinitions) + || has(self.spec.unmanagedCustomResourceDefinitions)' + - message: clusterapi is a singleton, .metadata.name must be 'cluster' + rule: self.metadata.name == 'cluster' + served: true + storage: true + subresources: + status: {} diff --git a/operator/v1alpha1/zz_generated.crd-manifests/0000_30_cluster-api_01_clusterapis-TechPreviewNoUpgrade.crd.yaml b/operator/v1alpha1/zz_generated.crd-manifests/0000_30_cluster-api_01_clusterapis-TechPreviewNoUpgrade.crd.yaml new file mode 100644 index 00000000000..bb096011f96 --- /dev/null +++ b/operator/v1alpha1/zz_generated.crd-manifests/0000_30_cluster-api_01_clusterapis-TechPreviewNoUpgrade.crd.yaml @@ -0,0 +1,239 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.openshift.io: https://github.com/openshift/api/pull/2564 + 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: TechPreviewNoUpgrade + name: clusterapis.operator.openshift.io +spec: + group: operator.openshift.io + names: + kind: ClusterAPI + listKind: ClusterAPIList + plural: clusterapis + singular: clusterapi + scope: Cluster + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + ClusterAPI provides configuration for the capi-operator. + + 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. + 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 is the specification of the desired behavior of the + capi-operator. + properties: + unmanagedCustomResourceDefinitions: + description: |- + unmanagedCustomResourceDefinitions is a list of ClusterResourceDefinition (CRD) + names that should not be managed by the capi-operator installer + controller. This allows external actors to own specific CRDs while + capi-operator manages others. + + Each CRD name must be a valid DNS-1123 subdomain consisting of lowercase + alphanumeric characters, '-' or '.', and must start and end with an + alphanumeric character, with a maximum length of 253 characters. + Example: "clusters.cluster.x-k8s.io" + + Items cannot be removed from this list once added. + + The maximum number of unmanagedCustomResourceDefinitions is 128. + items: + maxLength: 253 + type: string + x-kubernetes-validations: + - message: a lowercase 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()' + maxItems: 128 + type: array + x-kubernetes-list-type: set + x-kubernetes-validations: + - message: items cannot be removed from unmanagedCustomResourceDefinitions + list + rule: oldSelf.all(item, item in self) + type: object + status: + description: status defines the observed status of the capi-operator. + minProperties: 1 + properties: + currentRevision: + description: |- + currentRevision is the name of the most recently fully applied revision. + It is written by the installer controller. If it is absent, it indicates + that no revision has been fully applied yet. + If set, currentRevision must correspond to an entry in the revisions list. + maxLength: 255 + minLength: 1 + type: string + desiredRevision: + description: |- + desiredRevision is the name of the desired revision. It is written by the + revision controller. It must be set to the name of the entry in the + revisions list with the highest revision number. + maxLength: 255 + minLength: 1 + type: string + revisions: + description: |- + revisions is a list of all currently active revisions. A revision is + active until the installer controller updates currentRevision to a later + revision. It is written by the revision controller. + + The maximum number of revisions is 16. + All revisions must have a unique name. + All revisions must have a unique revision number. + When adding a revision, the revision number must be greater than the highest revision number in the list. + Revisions are immutable, although they can be deleted. + items: + properties: + components: + description: |- + components is list of components which will be installed by this + revision. Components will be installed in the order they are listed. + + The maximum number of components is 32. + items: + description: ClusterAPIInstallerComponent defines a component + which will be installed by this revision. + maxProperties: 1 + properties: + image: + description: |- + image defines an image source for a component. The image must contain a + /capi-operator-installer directory containing the component manifests. + properties: + digest: + description: |- + digest is an image reference to the image containing the component manifests. The reference + must be a valid image digest reference in the format host[:port][/namespace]/name@sha256:. + The digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9. + The length of the field 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: + - digest + type: object + required: + - image + type: object + maxItems: 32 + minItems: 1 + type: array + x-kubernetes-list-type: atomic + contentID: + description: |- + contentID uniquely identifies the content of this revision. + The contentID must be between 1 and 255 characters long. + maxLength: 255 + minLength: 1 + type: string + name: + description: name is the name of a revision. + maxLength: 255 + minLength: 1 + type: string + revision: + description: revision is a monotonically increasing number that + is assigned to a revision. + format: int64 + minimum: 1 + type: integer + unmanagedCustomResourceDefinitions: + description: |- + unmanagedCustomResourceDefinitions is a list of the names of + ClusterResourceDefinition (CRD) objects which are included in this + revision, but which should not be installed or updated. If not set, all + CRDs in the revision will be managed by the CAPI operator. + items: + maxLength: 253 + type: string + x-kubernetes-validations: + - message: a lowercase 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()' + maxItems: 128 + type: array + x-kubernetes-list-type: set + required: + - components + - contentID + - name + - revision + type: object + maxItems: 16 + minItems: 1 + type: array + x-kubernetes-list-type: atomic + x-kubernetes-validations: + - message: each revision must have a unique name + rule: self.all(x, self.exists_one(y, x.name == y.name)) + - message: each revision must have a unique revision number + rule: self.all(x, self.exists_one(y, x.revision == y.revision)) + - message: new revisions must have a revision number greater than + all existing revisions + rule: self.all(new, oldSelf.exists(old, old.name == new.name) || + oldSelf.all(old, new.revision > old.revision)) + - message: revisions are immutable + rule: oldSelf.all(old, !self.exists(new, new.name == old.name) || + self.exists(new, new == old)) + required: + - desiredRevision + - revisions + type: object + x-kubernetes-validations: + - message: desiredRevision must be the name of the revision with the highest + revision number + rule: self.revisions.exists(r, r.name == self.desiredRevision && self.revisions.all(s, + s.revision <= r.revision)) + - message: currentRevision must correspond to an entry in the revisions + list + rule: '!has(self.currentRevision) || self.revisions.exists(r, r.name + == self.currentRevision)' + required: + - metadata + type: object + x-kubernetes-validations: + - message: unmanagedCustomResourceDefinitions cannot be unset once set + rule: '!has(oldSelf.spec) || !has(oldSelf.spec.unmanagedCustomResourceDefinitions) + || has(self.spec.unmanagedCustomResourceDefinitions)' + - message: clusterapi is a singleton, .metadata.name must be 'cluster' + rule: self.metadata.name == 'cluster' + served: true + storage: true + subresources: + status: {} diff --git a/operator/v1alpha1/zz_generated.deepcopy.go b/operator/v1alpha1/zz_generated.deepcopy.go index de4c0712815..1f3fd281e15 100644 --- a/operator/v1alpha1/zz_generated.deepcopy.go +++ b/operator/v1alpha1/zz_generated.deepcopy.go @@ -26,6 +26,174 @@ func (in *BackupJobReference) DeepCopy() *BackupJobReference { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterAPI) DeepCopyInto(out *ClusterAPI) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.Spec != nil { + in, out := &in.Spec, &out.Spec + *out = new(ClusterAPISpec) + (*in).DeepCopyInto(*out) + } + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterAPI. +func (in *ClusterAPI) DeepCopy() *ClusterAPI { + if in == nil { + return nil + } + out := new(ClusterAPI) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterAPI) 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 *ClusterAPIInstallerComponent) DeepCopyInto(out *ClusterAPIInstallerComponent) { + *out = *in + out.Image = in.Image + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterAPIInstallerComponent. +func (in *ClusterAPIInstallerComponent) DeepCopy() *ClusterAPIInstallerComponent { + if in == nil { + return nil + } + out := new(ClusterAPIInstallerComponent) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterAPIInstallerComponentImage) DeepCopyInto(out *ClusterAPIInstallerComponentImage) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterAPIInstallerComponentImage. +func (in *ClusterAPIInstallerComponentImage) DeepCopy() *ClusterAPIInstallerComponentImage { + if in == nil { + return nil + } + out := new(ClusterAPIInstallerComponentImage) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterAPIInstallerRevision) DeepCopyInto(out *ClusterAPIInstallerRevision) { + *out = *in + if in.UnmanagedCustomResourceDefinitions != nil { + in, out := &in.UnmanagedCustomResourceDefinitions, &out.UnmanagedCustomResourceDefinitions + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Components != nil { + in, out := &in.Components, &out.Components + *out = make([]ClusterAPIInstallerComponent, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterAPIInstallerRevision. +func (in *ClusterAPIInstallerRevision) DeepCopy() *ClusterAPIInstallerRevision { + if in == nil { + return nil + } + out := new(ClusterAPIInstallerRevision) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterAPIList) DeepCopyInto(out *ClusterAPIList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ClusterAPI, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterAPIList. +func (in *ClusterAPIList) DeepCopy() *ClusterAPIList { + if in == nil { + return nil + } + out := new(ClusterAPIList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterAPIList) 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 *ClusterAPISpec) DeepCopyInto(out *ClusterAPISpec) { + *out = *in + if in.UnmanagedCustomResourceDefinitions != nil { + in, out := &in.UnmanagedCustomResourceDefinitions, &out.UnmanagedCustomResourceDefinitions + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterAPISpec. +func (in *ClusterAPISpec) DeepCopy() *ClusterAPISpec { + if in == nil { + return nil + } + out := new(ClusterAPISpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterAPIStatus) DeepCopyInto(out *ClusterAPIStatus) { + *out = *in + if in.Revisions != nil { + in, out := &in.Revisions, &out.Revisions + *out = make([]ClusterAPIInstallerRevision, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterAPIStatus. +func (in *ClusterAPIStatus) DeepCopy() *ClusterAPIStatus { + if in == nil { + return nil + } + out := new(ClusterAPIStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClusterVersionOperator) DeepCopyInto(out *ClusterVersionOperator) { *out = *in diff --git a/operator/v1alpha1/zz_generated.featuregated-crd-manifests.yaml b/operator/v1alpha1/zz_generated.featuregated-crd-manifests.yaml index 0d595be801b..2385e592dd7 100644 --- a/operator/v1alpha1/zz_generated.featuregated-crd-manifests.yaml +++ b/operator/v1alpha1/zz_generated.featuregated-crd-manifests.yaml @@ -1,3 +1,26 @@ +clusterapis.operator.openshift.io: + Annotations: {} + ApprovedPRNumber: https://github.com/openshift/api/pull/2564 + CRDName: clusterapis.operator.openshift.io + Capability: "" + Category: "" + FeatureGates: + - ClusterAPIMachineManagement + FilenameOperatorName: cluster-api + FilenameOperatorOrdering: "01" + FilenameRunLevel: "0000_30" + GroupName: operator.openshift.io + HasStatus: true + KindName: ClusterAPI + Labels: {} + PluralName: clusterapis + PrinterColumns: [] + Scope: Cluster + ShortNames: null + TopLevelFeatureGates: + - ClusterAPIMachineManagement + Version: v1alpha1 + clusterversionoperators.operator.openshift.io: Annotations: {} ApprovedPRNumber: https://github.com/openshift/api/pull/2044 diff --git a/operator/v1alpha1/zz_generated.featuregated-crd-manifests/clusterapis.operator.openshift.io/ClusterAPIMachineManagement.yaml b/operator/v1alpha1/zz_generated.featuregated-crd-manifests/clusterapis.operator.openshift.io/ClusterAPIMachineManagement.yaml new file mode 100644 index 00000000000..325b74e302b --- /dev/null +++ b/operator/v1alpha1/zz_generated.featuregated-crd-manifests/clusterapis.operator.openshift.io/ClusterAPIMachineManagement.yaml @@ -0,0 +1,239 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.openshift.io: https://github.com/openshift/api/pull/2564 + api.openshift.io/filename-cvo-runlevel: "0000_30" + api.openshift.io/filename-operator: cluster-api + api.openshift.io/filename-ordering: "01" + feature-gate.release.openshift.io/ClusterAPIMachineManagement: "true" + name: clusterapis.operator.openshift.io +spec: + group: operator.openshift.io + names: + kind: ClusterAPI + listKind: ClusterAPIList + plural: clusterapis + singular: clusterapi + scope: Cluster + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + ClusterAPI provides configuration for the capi-operator. + + 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. + 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 is the specification of the desired behavior of the + capi-operator. + properties: + unmanagedCustomResourceDefinitions: + description: |- + unmanagedCustomResourceDefinitions is a list of ClusterResourceDefinition (CRD) + names that should not be managed by the capi-operator installer + controller. This allows external actors to own specific CRDs while + capi-operator manages others. + + Each CRD name must be a valid DNS-1123 subdomain consisting of lowercase + alphanumeric characters, '-' or '.', and must start and end with an + alphanumeric character, with a maximum length of 253 characters. + Example: "clusters.cluster.x-k8s.io" + + Items cannot be removed from this list once added. + + The maximum number of unmanagedCustomResourceDefinitions is 128. + items: + maxLength: 253 + type: string + x-kubernetes-validations: + - message: a lowercase 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()' + maxItems: 128 + type: array + x-kubernetes-list-type: set + x-kubernetes-validations: + - message: items cannot be removed from unmanagedCustomResourceDefinitions + list + rule: oldSelf.all(item, item in self) + type: object + status: + description: status defines the observed status of the capi-operator. + minProperties: 1 + properties: + currentRevision: + description: |- + currentRevision is the name of the most recently fully applied revision. + It is written by the installer controller. If it is absent, it indicates + that no revision has been fully applied yet. + If set, currentRevision must correspond to an entry in the revisions list. + maxLength: 255 + minLength: 1 + type: string + desiredRevision: + description: |- + desiredRevision is the name of the desired revision. It is written by the + revision controller. It must be set to the name of the entry in the + revisions list with the highest revision number. + maxLength: 255 + minLength: 1 + type: string + revisions: + description: |- + revisions is a list of all currently active revisions. A revision is + active until the installer controller updates currentRevision to a later + revision. It is written by the revision controller. + + The maximum number of revisions is 16. + All revisions must have a unique name. + All revisions must have a unique revision number. + When adding a revision, the revision number must be greater than the highest revision number in the list. + Revisions are immutable, although they can be deleted. + items: + properties: + components: + description: |- + components is list of components which will be installed by this + revision. Components will be installed in the order they are listed. + + The maximum number of components is 32. + items: + description: ClusterAPIInstallerComponent defines a component + which will be installed by this revision. + maxProperties: 1 + properties: + image: + description: |- + image defines an image source for a component. The image must contain a + /capi-operator-installer directory containing the component manifests. + properties: + digest: + description: |- + digest is an image reference to the image containing the component manifests. The reference + must be a valid image digest reference in the format host[:port][/namespace]/name@sha256:. + The digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9. + The length of the field 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: + - digest + type: object + required: + - image + type: object + maxItems: 32 + minItems: 1 + type: array + x-kubernetes-list-type: atomic + contentID: + description: |- + contentID uniquely identifies the content of this revision. + The contentID must be between 1 and 255 characters long. + maxLength: 255 + minLength: 1 + type: string + name: + description: name is the name of a revision. + maxLength: 255 + minLength: 1 + type: string + revision: + description: revision is a monotonically increasing number that + is assigned to a revision. + format: int64 + minimum: 1 + type: integer + unmanagedCustomResourceDefinitions: + description: |- + unmanagedCustomResourceDefinitions is a list of the names of + ClusterResourceDefinition (CRD) objects which are included in this + revision, but which should not be installed or updated. If not set, all + CRDs in the revision will be managed by the CAPI operator. + items: + maxLength: 253 + type: string + x-kubernetes-validations: + - message: a lowercase 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()' + maxItems: 128 + type: array + x-kubernetes-list-type: set + required: + - components + - contentID + - name + - revision + type: object + maxItems: 16 + minItems: 1 + type: array + x-kubernetes-list-type: atomic + x-kubernetes-validations: + - message: each revision must have a unique name + rule: self.all(x, self.exists_one(y, x.name == y.name)) + - message: each revision must have a unique revision number + rule: self.all(x, self.exists_one(y, x.revision == y.revision)) + - message: new revisions must have a revision number greater than + all existing revisions + rule: self.all(new, oldSelf.exists(old, old.name == new.name) || + oldSelf.all(old, new.revision > old.revision)) + - message: revisions are immutable + rule: oldSelf.all(old, !self.exists(new, new.name == old.name) || + self.exists(new, new == old)) + required: + - desiredRevision + - revisions + type: object + x-kubernetes-validations: + - message: desiredRevision must be the name of the revision with the highest + revision number + rule: self.revisions.exists(r, r.name == self.desiredRevision && self.revisions.all(s, + s.revision <= r.revision)) + - message: currentRevision must correspond to an entry in the revisions + list + rule: '!has(self.currentRevision) || self.revisions.exists(r, r.name + == self.currentRevision)' + required: + - metadata + type: object + x-kubernetes-validations: + - message: unmanagedCustomResourceDefinitions cannot be unset once set + rule: '!has(oldSelf.spec) || !has(oldSelf.spec.unmanagedCustomResourceDefinitions) + || has(self.spec.unmanagedCustomResourceDefinitions)' + - message: clusterapi is a singleton, .metadata.name must be 'cluster' + rule: self.metadata.name == 'cluster' + served: true + storage: true + subresources: + status: {} diff --git a/operator/v1alpha1/zz_generated.swagger_doc_generated.go b/operator/v1alpha1/zz_generated.swagger_doc_generated.go index 9060bf99815..b5bb7279c2e 100644 --- a/operator/v1alpha1/zz_generated.swagger_doc_generated.go +++ b/operator/v1alpha1/zz_generated.swagger_doc_generated.go @@ -135,6 +135,77 @@ func (VersionAvailability) SwaggerDoc() map[string]string { return map_VersionAvailability } +var map_ClusterAPI = map[string]string{ + "": "ClusterAPI provides configuration for the capi-operator.\n\nCompatibility 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.", + "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 is the specification of the desired behavior of the capi-operator.", + "status": "status defines the observed status of the capi-operator.", +} + +func (ClusterAPI) SwaggerDoc() map[string]string { + return map_ClusterAPI +} + +var map_ClusterAPIInstallerComponent = map[string]string{ + "": "ClusterAPIInstallerComponent defines a component which will be installed by this revision.", + "image": "image defines an image source for a component. The image must contain a /capi-operator-installer directory containing the component manifests.", +} + +func (ClusterAPIInstallerComponent) SwaggerDoc() map[string]string { + return map_ClusterAPIInstallerComponent +} + +var map_ClusterAPIInstallerComponentImage = map[string]string{ + "": "ClusterAPIInstallerComponentImage defines an image source for a component.", + "digest": "digest is an image reference to the image containing the component manifests. The reference must be a valid image digest reference in the format host[:port][/namespace]/name@sha256:. The digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9. The length of the field must be between 1 to 447 characters.", +} + +func (ClusterAPIInstallerComponentImage) SwaggerDoc() map[string]string { + return map_ClusterAPIInstallerComponentImage +} + +var map_ClusterAPIInstallerRevision = map[string]string{ + "name": "name is the name of a revision.", + "revision": "revision is a monotonically increasing number that is assigned to a revision.", + "contentID": "contentID uniquely identifies the content of this revision. The contentID must be between 1 and 255 characters long.", + "unmanagedCustomResourceDefinitions": "unmanagedCustomResourceDefinitions is a list of the names of ClusterResourceDefinition (CRD) objects which are included in this revision, but which should not be installed or updated. If not set, all CRDs in the revision will be managed by the CAPI operator.", + "components": "components is list of components which will be installed by this revision. Components will be installed in the order they are listed.\n\nThe maximum number of components is 32.", +} + +func (ClusterAPIInstallerRevision) SwaggerDoc() map[string]string { + return map_ClusterAPIInstallerRevision +} + +var map_ClusterAPIList = map[string]string{ + "": "ClusterAPIList contains a list of ClusterAPI configurations\n\nCompatibility 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.", + "metadata": "metadata is the standard list's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", + "items": "items contains the items", +} + +func (ClusterAPIList) SwaggerDoc() map[string]string { + return map_ClusterAPIList +} + +var map_ClusterAPISpec = map[string]string{ + "": "ClusterAPISpec defines the desired configuration of the capi-operator.", + "unmanagedCustomResourceDefinitions": "unmanagedCustomResourceDefinitions is a list of ClusterResourceDefinition (CRD) names that should not be managed by the capi-operator installer controller. This allows external actors to own specific CRDs while capi-operator manages others.\n\nEach CRD name must be a valid DNS-1123 subdomain consisting of lowercase alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character, with a maximum length of 253 characters. Example: \"clusters.cluster.x-k8s.io\"\n\nItems cannot be removed from this list once added.\n\nThe maximum number of unmanagedCustomResourceDefinitions is 128.", +} + +func (ClusterAPISpec) SwaggerDoc() map[string]string { + return map_ClusterAPISpec +} + +var map_ClusterAPIStatus = map[string]string{ + "": "ClusterAPIStatus describes the current state of the capi-operator.", + "currentRevision": "currentRevision is the name of the most recently fully applied revision. It is written by the installer controller. If it is absent, it indicates that no revision has been fully applied yet. If set, currentRevision must correspond to an entry in the revisions list.", + "desiredRevision": "desiredRevision is the name of the desired revision. It is written by the revision controller. It must be set to the name of the entry in the revisions list with the highest revision number.", + "revisions": "revisions is a list of all currently active revisions. A revision is active until the installer controller updates currentRevision to a later revision. It is written by the revision controller.\n\nThe maximum number of revisions is 16. All revisions must have a unique name. All revisions must have a unique revision number. When adding a revision, the revision number must be greater than the highest revision number in the list. Revisions are immutable, although they can be deleted.", +} + +func (ClusterAPIStatus) SwaggerDoc() map[string]string { + return map_ClusterAPIStatus +} + var map_ClusterVersionOperator = map[string]string{ "": "ClusterVersionOperator holds cluster-wide information about the Cluster Version Operator.\n\nCompatibility 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.", "metadata": "metadata is the standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata",