diff --git a/Makefile b/Makefile index 827d3ac7e..4e233bd5c 100644 --- a/Makefile +++ b/Makefile @@ -76,7 +76,7 @@ $(call build-image,placement,$(PLACEMENT_IMAGE),./build/Dockerfile.placement,.) $(call build-image,registration-operator,$(OPERATOR_IMAGE_NAME),./build/Dockerfile.registration-operator,.) $(call build-image,addon-manager,$(ADDON_MANAGER_IMAGE),./build/Dockerfile.addon,.) -copy-crd: +copy-crd: ensure-yaml-patch bash -x hack/copy-crds.sh $(YAML_PATCH) update: copy-crd update-csv @@ -86,7 +86,7 @@ test-unit: ensure-kubebuilder-tools update-csv: ensure-operator-sdk ensure-helm bash -x hack/update-csv.sh -verify-crds: +verify-crds: ensure-yaml-patch bash -x hack/verify-crds.sh $(YAML_PATCH) verify-gocilint: ensure-golangci-lint diff --git a/cmd/addon/main.go b/cmd/addon/main.go index 4acfad5b7..65a44772c 100644 --- a/cmd/addon/main.go +++ b/cmd/addon/main.go @@ -11,6 +11,7 @@ import ( "k8s.io/component-base/logs" "open-cluster-management.io/ocm/pkg/cmd/hub" + "open-cluster-management.io/ocm/pkg/cmd/webhook" "open-cluster-management.io/ocm/pkg/version" ) @@ -46,5 +47,6 @@ func newAddonCommand() *cobra.Command { } cmd.AddCommand(hub.NewAddonManager()) + cmd.AddCommand(webhook.NewAddonWebhook()) return cmd } diff --git a/deploy/cluster-manager/chart/cluster-manager/templates/cluster_role.yaml b/deploy/cluster-manager/chart/cluster-manager/templates/cluster_role.yaml index eee16427b..a72388e81 100644 --- a/deploy/cluster-manager/chart/cluster-manager/templates/cluster_role.yaml +++ b/deploy/cluster-manager/chart/cluster-manager/templates/cluster_role.yaml @@ -22,12 +22,14 @@ rules: - "signer-secret" - "registration-webhook-serving-cert" - "work-webhook-serving-cert" + - "addon-webhook-serving-cert" - "registration-controller-sa-kubeconfig" - "registration-webhook-sa-kubeconfig" - "work-webhook-sa-kubeconfig" - "placement-controller-sa-kubeconfig" - "work-controller-sa-kubeconfig" - "addon-manager-controller-sa-kubeconfig" + - "addon-webhook-sa-kubeconfig" - "external-hub-kubeconfig" - "work-driver-config" - "open-cluster-management-image-pull-credentials" diff --git a/deploy/cluster-manager/config/rbac/cluster_role.yaml b/deploy/cluster-manager/config/rbac/cluster_role.yaml index 258747440..728d9a67f 100644 --- a/deploy/cluster-manager/config/rbac/cluster_role.yaml +++ b/deploy/cluster-manager/config/rbac/cluster_role.yaml @@ -24,12 +24,14 @@ rules: - "signer-secret" - "registration-webhook-serving-cert" - "work-webhook-serving-cert" + - "addon-webhook-serving-cert" - "registration-controller-sa-kubeconfig" - "registration-webhook-sa-kubeconfig" - "work-webhook-sa-kubeconfig" - "placement-controller-sa-kubeconfig" - "work-controller-sa-kubeconfig" - "addon-manager-controller-sa-kubeconfig" + - "addon-webhook-sa-kubeconfig" - "external-hub-kubeconfig" - "work-driver-config" - "open-cluster-management-image-pull-credentials" diff --git a/deploy/cluster-manager/olm-catalog/latest/manifests/cluster-manager.clusterserviceversion.yaml b/deploy/cluster-manager/olm-catalog/latest/manifests/cluster-manager.clusterserviceversion.yaml index 51a6f067a..c2b9428ad 100644 --- a/deploy/cluster-manager/olm-catalog/latest/manifests/cluster-manager.clusterserviceversion.yaml +++ b/deploy/cluster-manager/olm-catalog/latest/manifests/cluster-manager.clusterserviceversion.yaml @@ -59,7 +59,7 @@ metadata: categories: Integration & Delivery,OpenShift Optional certified: "false" containerImage: quay.io/open-cluster-management/registration-operator:latest - createdAt: "2025-12-16T09:07:02Z" + createdAt: "2025-12-17T06:07:52Z" description: Manages the installation and upgrade of the ClusterManager. operators.operatorframework.io/builder: operator-sdk-v1.32.0 operators.operatorframework.io/project_layout: go.kubebuilder.io/v3 @@ -148,12 +148,14 @@ spec: - signer-secret - registration-webhook-serving-cert - work-webhook-serving-cert + - addon-webhook-serving-cert - registration-controller-sa-kubeconfig - registration-webhook-sa-kubeconfig - work-webhook-sa-kubeconfig - placement-controller-sa-kubeconfig - work-controller-sa-kubeconfig - addon-manager-controller-sa-kubeconfig + - addon-webhook-sa-kubeconfig - external-hub-kubeconfig - work-driver-config - open-cluster-management-image-pull-credentials diff --git a/deploy/klusterlet/olm-catalog/latest/manifests/klusterlet.clusterserviceversion.yaml b/deploy/klusterlet/olm-catalog/latest/manifests/klusterlet.clusterserviceversion.yaml index c9ecbd779..b98f82389 100644 --- a/deploy/klusterlet/olm-catalog/latest/manifests/klusterlet.clusterserviceversion.yaml +++ b/deploy/klusterlet/olm-catalog/latest/manifests/klusterlet.clusterserviceversion.yaml @@ -31,7 +31,7 @@ metadata: categories: Integration & Delivery,OpenShift Optional certified: "false" containerImage: quay.io/open-cluster-management/registration-operator:latest - createdAt: "2025-12-16T09:07:02Z" + createdAt: "2025-12-17T06:07:53Z" description: Manages the installation and upgrade of the Klusterlet. operators.operatorframework.io/builder: operator-sdk-v1.32.0 operators.operatorframework.io/project_layout: go.kubebuilder.io/v3 diff --git a/go.mod b/go.mod index 820062176..4411c89f3 100644 --- a/go.mod +++ b/go.mod @@ -39,8 +39,8 @@ require ( k8s.io/kube-aggregator v0.34.3 k8s.io/kubectl v0.34.3 k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 - open-cluster-management.io/addon-framework v1.1.1-0.20251216020304-d6b232cac146 - open-cluster-management.io/api v1.1.1-0.20251216020302-b4274bb2f05a + open-cluster-management.io/addon-framework v1.1.1-0.20251222073158-b5846d76add9 + open-cluster-management.io/api v1.1.1-0.20251222023835-510285203ee6 open-cluster-management.io/sdk-go v1.1.1-0.20251218093423-de3e6c682fd0 sigs.k8s.io/about-api v0.0.0-20250131010323-518069c31c03 sigs.k8s.io/cluster-inventory-api v0.0.0-20240730014211-ef0154379848 diff --git a/go.sum b/go.sum index 58bd32919..7f1687dcd 100644 --- a/go.sum +++ b/go.sum @@ -588,10 +588,10 @@ k8s.io/kubectl v0.34.3 h1:vpM6//153gh5gvsYHXWHVJ4l4xmN5QFwTSmlfd8icm8= k8s.io/kubectl v0.34.3/go.mod h1:zZQHtIZoUqTP1bAnPzq/3W1jfc0NeOeunFgcswrfg1c= k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -open-cluster-management.io/addon-framework v1.1.1-0.20251216020304-d6b232cac146 h1:9xiXnY0PHi8bWaxUqxML7BUvHmcLEBaAMIHagrhckj8= -open-cluster-management.io/addon-framework v1.1.1-0.20251216020304-d6b232cac146/go.mod h1:RB8Dni4wwJ3Kvpd083/Qfd/whbf4CZFqB9LPYGeF9Uc= -open-cluster-management.io/api v1.1.1-0.20251216020302-b4274bb2f05a h1:A8CSY1atudEbmjdEhdYUUQcN/Gdywo786WPPt0mFWgE= -open-cluster-management.io/api v1.1.1-0.20251216020302-b4274bb2f05a/go.mod h1:YcmA6SpGEekIMxdoeVIIyOaBhMA6ImWRLXP4g8n8T+4= +open-cluster-management.io/addon-framework v1.1.1-0.20251222073158-b5846d76add9 h1:Ll4rTS7hlg9PvEZwVjfpRqvG+Vywclcw1B08Vnf0w3E= +open-cluster-management.io/addon-framework v1.1.1-0.20251222073158-b5846d76add9/go.mod h1:St9LTEuZ5ADLY9cVXSp+rVE/ZbPJ+hzNQ7/YcsiQVd8= +open-cluster-management.io/api v1.1.1-0.20251222023835-510285203ee6 h1:mfcUKaSOYVDLzuontUOcasesbU9whNnvgrA0qf9trKs= +open-cluster-management.io/api v1.1.1-0.20251222023835-510285203ee6/go.mod h1:YcmA6SpGEekIMxdoeVIIyOaBhMA6ImWRLXP4g8n8T+4= open-cluster-management.io/sdk-go v1.1.1-0.20251218093423-de3e6c682fd0 h1:nup1pOFCuBgjisq2F5Bda9NQPyhCR/GRAfdHFdS1aJE= open-cluster-management.io/sdk-go v1.1.1-0.20251218093423-de3e6c682fd0/go.mod h1:3xQf3gISaZ3377vFnwjH3QH8EF2UNaf8D9igLPUBChk= sigs.k8s.io/about-api v0.0.0-20250131010323-518069c31c03 h1:1ShFiMjGQOR/8jTBkmZrk1gORxnvMwm1nOy2/DbHg4U= diff --git a/hack/0000_00_addon.open-cluster-management.io_clustermanagementaddons.crd.yaml.yaml-patch b/hack/0000_00_addon.open-cluster-management.io_clustermanagementaddons.crd.yaml.yaml-patch new file mode 100644 index 000000000..3fd9ad480 --- /dev/null +++ b/hack/0000_00_addon.open-cluster-management.io_clustermanagementaddons.crd.yaml.yaml-patch @@ -0,0 +1,15 @@ +- op: add + path: /spec/conversion + value: + strategy: Webhook + webhook: + clientConfig: + caBundle: {{ .AddonAPIServiceCABundle }} + service: + name: cluster-manager-addon-webhook + namespace: {{ .ClusterManagerNamespace }} + path: /convert + port: 9443 + conversionReviewVersions: + - v1 + - v1beta1 diff --git a/hack/0000_01_addon.open-cluster-management.io_managedclusteraddons.crd.yaml.yaml-patch b/hack/0000_01_addon.open-cluster-management.io_managedclusteraddons.crd.yaml.yaml-patch new file mode 100644 index 000000000..3fd9ad480 --- /dev/null +++ b/hack/0000_01_addon.open-cluster-management.io_managedclusteraddons.crd.yaml.yaml-patch @@ -0,0 +1,15 @@ +- op: add + path: /spec/conversion + value: + strategy: Webhook + webhook: + clientConfig: + caBundle: {{ .AddonAPIServiceCABundle }} + service: + name: cluster-manager-addon-webhook + namespace: {{ .ClusterManagerNamespace }} + path: /convert + port: 9443 + conversionReviewVersions: + - v1 + - v1beta1 diff --git a/hack/init.sh b/hack/init.sh index 89f932696..0d7e96a2e 100644 --- a/hack/init.sh +++ b/hack/init.sh @@ -5,7 +5,9 @@ set -o nounset set -o pipefail HUB_CRD_FILES="./vendor/open-cluster-management.io/api/cluster/v1/*.crd.yaml -./vendor/open-cluster-management.io/api/addon/v1alpha1/*.crd.yaml +./vendor/open-cluster-management.io/api/addon/v1alpha1/0000_02_addon.open-cluster-management.io_addondeploymentconfigs.crd.yaml +./vendor/open-cluster-management.io/api/addon/v1alpha1/0000_03_addon.open-cluster-management.io_addontemplates.crd.yaml +./vendor/open-cluster-management.io/api/addon/v1beta1/*.crd.yaml ./vendor/open-cluster-management.io/api/cluster/v1beta2/0000_01_clusters.open-cluster-management.io_managedclustersetbindings.crd.yaml ./vendor/open-cluster-management.io/api/cluster/v1beta2/0000_00_clusters.open-cluster-management.io_managedclustersets.crd.yaml ./vendor/open-cluster-management.io/api/cluster/v1beta1/0000_02_clusters.open-cluster-management.io_placements.crd.yaml diff --git a/manifests/cluster-manager/hub/addon-manager/webhook-service.yaml b/manifests/cluster-manager/hub/addon-manager/webhook-service.yaml new file mode 100644 index 000000000..4f7053877 --- /dev/null +++ b/manifests/cluster-manager/hub/addon-manager/webhook-service.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + name: cluster-manager-addon-webhook + namespace: {{ .ClusterManagerNamespace }} + labels: + {{ if gt (len .Labels) 0 }} + {{ range $key, $value := .Labels }} + "{{ $key }}": "{{ $value }}" + {{ end }} + {{ end }} +spec: + selector: + app: {{ .ClusterManagerName }}-addon-webhook + ports: + - name: webhook + port: 9443 + targetPort: 9443 diff --git a/manifests/cluster-manager/hub/addon-manager/webhook-serviceaccount.yaml b/manifests/cluster-manager/hub/addon-manager/webhook-serviceaccount.yaml new file mode 100644 index 000000000..039fe576e --- /dev/null +++ b/manifests/cluster-manager/hub/addon-manager/webhook-serviceaccount.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: addon-webhook-sa + namespace: {{ .ClusterManagerNamespace }} diff --git a/manifests/cluster-manager/hub/crds/0000_00_addon.open-cluster-management.io_clustermanagementaddons.crd.yaml b/manifests/cluster-manager/hub/crds/0000_00_addon.open-cluster-management.io_clustermanagementaddons.crd.yaml index e7fc80745..c71a370e3 100644 --- a/manifests/cluster-manager/hub/crds/0000_00_addon.open-cluster-management.io_clustermanagementaddons.crd.yaml +++ b/manifests/cluster-manager/hub/crds/0000_00_addon.open-cluster-management.io_clustermanagementaddons.crd.yaml @@ -3,6 +3,19 @@ kind: CustomResourceDefinition metadata: name: clustermanagementaddons.addon.open-cluster-management.io spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + caBundle: {{ .AddonAPIServiceCABundle }} + service: + name: cluster-manager-addon-webhook + namespace: {{ .ClusterManagerNamespace }} + path: /convert + port: 9443 + conversionReviewVersions: + - v1 + - v1beta1 group: addon.open-cluster-management.io names: kind: ClusterManagementAddOn @@ -627,6 +640,580 @@ spec: storage: true subresources: status: {} + - additionalPrinterColumns: + - jsonPath: .spec.addOnMeta.displayName + name: DISPLAY NAME + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: |- + ClusterManagementAddOn represents the registration of an add-on to the cluster manager. + This resource allows you to discover which add-ons are available for the cluster manager + and provides metadata information about the add-ons. The ClusterManagementAddOn name is used + for the namespace-scoped ManagedClusterAddOn resource. + ClusterManagementAddOn is a cluster-scoped resource. + 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 represents a desired configuration for the agent on + the cluster management add-on. + properties: + addOnMeta: + description: addOnMeta is a reference to the metadata information + for the add-on. + properties: + description: + description: description represents the detailed description of + the add-on. + type: string + displayName: + description: displayName represents the name of add-on that will + be displayed. + type: string + type: object + defaultConfigs: + description: defaultConfigs is a list of default configuration types + supported by add-on. + items: + properties: + group: + default: "" + description: group of the add-on configuration. + type: string + name: + description: name of the add-on configuration. + minLength: 1 + type: string + namespace: + description: |- + namespace of the add-on configuration. + If this field is not set, the configuration is in the cluster scope. + type: string + resource: + description: resource of the add-on configuration. + minLength: 1 + type: string + required: + - name + - resource + type: object + type: array + x-kubernetes-list-map-keys: + - group + - resource + x-kubernetes-list-type: map + installStrategy: + default: + type: Manual + description: |- + installStrategy represents that related ManagedClusterAddOns should be installed + on certain clusters. + properties: + placements: + description: |- + placements is a list of placement references honored when install strategy type is + Placements. All clusters selected by these placements will install the addon + If one cluster belongs to multiple placements, it will only apply the strategy defined + later in the order. That is to say, The latter strategy overrides the previous one. + items: + properties: + configs: + description: |- + configs is the configuration of managedClusterAddon during installation. + User can override the configuration by updating the managedClusterAddon directly. + items: + properties: + group: + default: "" + description: group of the add-on configuration. + type: string + name: + description: name of the add-on configuration. + minLength: 1 + type: string + namespace: + description: |- + namespace of the add-on configuration. + If this field is not set, the configuration is in the cluster scope. + type: string + resource: + description: resource of the add-on configuration. + minLength: 1 + type: string + required: + - name + - resource + type: object + type: array + name: + description: name is the name of the placement + minLength: 1 + type: string + namespace: + description: namespace is the namespace of the placement + minLength: 1 + type: string + rolloutStrategy: + default: + type: All + description: |- + rolloutStrategy is the strategy to apply addon configurations change. + The rollout strategy only watches the addon configurations defined in ClusterManagementAddOn. + properties: + all: + description: all defines required fields for RolloutStrategy + type All + properties: + maxFailures: + anyOf: + - type: integer + - type: string + default: 0 + description: |- + MaxFailures is a percentage or number of clusters in the current rollout that can fail before + proceeding to the next rollout. Fail means the cluster has a failed status or timeout status + (does not reach successful status after ProgressDeadline). + Once the MaxFailures is breached, the rollout will stop. + MaxFailures is only considered for rollout types Progressive and ProgressivePerGroup. For + Progressive, this is considered over the total number of clusters. For ProgressivePerGroup, + this is considered according to the size of the current group. For both Progressive and + ProgressivePerGroup, the MaxFailures does not apply for MandatoryDecisionGroups, which tolerate + no failures. + Default is that no failures are tolerated. + pattern: ^((100|[0-9]{1,2})%|[0-9]+)$ + x-kubernetes-int-or-string: true + minSuccessTime: + default: "0" + description: |- + MinSuccessTime is a "soak" time. In other words, the minimum amount of time the workload + applier controller will wait from the start of each rollout before proceeding (assuming a + successful state has been reached and MaxFailures wasn't breached). + MinSuccessTime is only considered for rollout types Progressive and ProgressivePerGroup. + The default value is 0 meaning the workload applier proceeds immediately after a successful + state is reached. + MinSuccessTime must be defined in [0-9h]|[0-9m]|[0-9s] format examples; 2h , 90m , 360s + type: string + progressDeadline: + default: None + description: |- + ProgressDeadline defines how long workload applier controller will wait for the workload to + reach a successful state in the cluster. + If the workload does not reach a successful state after ProgressDeadline, will stop waiting + and workload will be treated as "timeout" and be counted into MaxFailures. Once the MaxFailures + is breached, the rollout will stop. + ProgressDeadline default value is "None", meaning the workload applier will wait for a + successful state indefinitely. + ProgressDeadline must be defined in [0-9h]|[0-9m]|[0-9s] format examples; 2h , 90m , 360s + pattern: ^(([0-9])+[h|m|s])|None$ + type: string + type: object + progressive: + description: progressive defines required fields for + RolloutStrategy type Progressive + properties: + mandatoryDecisionGroups: + description: |- + List of the decision groups names or indexes to apply the workload first and fail if workload + did not reach successful state. + GroupName or GroupIndex must match with the decisionGroups defined in the placement's + decisionStrategy + items: + description: |- + MandatoryDecisionGroup set the decision group name or group index. + GroupName is considered first to select the decisionGroups then GroupIndex. + properties: + groupIndex: + description: |- + groupIndex of the decision group should match the placementDecisions label value with label key + cluster.open-cluster-management.io/decision-group-index + format: int32 + type: integer + groupName: + description: |- + groupName of the decision group should match the placementDecisions label value with label key + cluster.open-cluster-management.io/decision-group-name + type: string + type: object + type: array + maxConcurrency: + anyOf: + - type: integer + - type: string + description: |- + maxConcurrency is the max number of clusters to deploy workload concurrently. The default value + for MaxConcurrency is determined from the clustersPerDecisionGroup defined in the + placement->DecisionStrategy. + pattern: ^((100|[0-9]{1,2})%|[0-9]+)$ + x-kubernetes-int-or-string: true + maxFailures: + anyOf: + - type: integer + - type: string + default: 0 + description: |- + MaxFailures is a percentage or number of clusters in the current rollout that can fail before + proceeding to the next rollout. Fail means the cluster has a failed status or timeout status + (does not reach successful status after ProgressDeadline). + Once the MaxFailures is breached, the rollout will stop. + MaxFailures is only considered for rollout types Progressive and ProgressivePerGroup. For + Progressive, this is considered over the total number of clusters. For ProgressivePerGroup, + this is considered according to the size of the current group. For both Progressive and + ProgressivePerGroup, the MaxFailures does not apply for MandatoryDecisionGroups, which tolerate + no failures. + Default is that no failures are tolerated. + pattern: ^((100|[0-9]{1,2})%|[0-9]+)$ + x-kubernetes-int-or-string: true + minSuccessTime: + default: "0" + description: |- + MinSuccessTime is a "soak" time. In other words, the minimum amount of time the workload + applier controller will wait from the start of each rollout before proceeding (assuming a + successful state has been reached and MaxFailures wasn't breached). + MinSuccessTime is only considered for rollout types Progressive and ProgressivePerGroup. + The default value is 0 meaning the workload applier proceeds immediately after a successful + state is reached. + MinSuccessTime must be defined in [0-9h]|[0-9m]|[0-9s] format examples; 2h , 90m , 360s + type: string + progressDeadline: + default: None + description: |- + ProgressDeadline defines how long workload applier controller will wait for the workload to + reach a successful state in the cluster. + If the workload does not reach a successful state after ProgressDeadline, will stop waiting + and workload will be treated as "timeout" and be counted into MaxFailures. Once the MaxFailures + is breached, the rollout will stop. + ProgressDeadline default value is "None", meaning the workload applier will wait for a + successful state indefinitely. + ProgressDeadline must be defined in [0-9h]|[0-9m]|[0-9s] format examples; 2h , 90m , 360s + pattern: ^(([0-9])+[h|m|s])|None$ + type: string + type: object + progressivePerGroup: + description: progressivePerGroup defines required fields + for RolloutStrategy type ProgressivePerGroup + properties: + mandatoryDecisionGroups: + description: |- + List of the decision groups names or indexes to apply the workload first and fail if workload + did not reach successful state. + GroupName or GroupIndex must match with the decisionGroups defined in the placement's + decisionStrategy + items: + description: |- + MandatoryDecisionGroup set the decision group name or group index. + GroupName is considered first to select the decisionGroups then GroupIndex. + properties: + groupIndex: + description: |- + groupIndex of the decision group should match the placementDecisions label value with label key + cluster.open-cluster-management.io/decision-group-index + format: int32 + type: integer + groupName: + description: |- + groupName of the decision group should match the placementDecisions label value with label key + cluster.open-cluster-management.io/decision-group-name + type: string + type: object + type: array + maxFailures: + anyOf: + - type: integer + - type: string + default: 0 + description: |- + MaxFailures is a percentage or number of clusters in the current rollout that can fail before + proceeding to the next rollout. Fail means the cluster has a failed status or timeout status + (does not reach successful status after ProgressDeadline). + Once the MaxFailures is breached, the rollout will stop. + MaxFailures is only considered for rollout types Progressive and ProgressivePerGroup. For + Progressive, this is considered over the total number of clusters. For ProgressivePerGroup, + this is considered according to the size of the current group. For both Progressive and + ProgressivePerGroup, the MaxFailures does not apply for MandatoryDecisionGroups, which tolerate + no failures. + Default is that no failures are tolerated. + pattern: ^((100|[0-9]{1,2})%|[0-9]+)$ + x-kubernetes-int-or-string: true + minSuccessTime: + default: "0" + description: |- + MinSuccessTime is a "soak" time. In other words, the minimum amount of time the workload + applier controller will wait from the start of each rollout before proceeding (assuming a + successful state has been reached and MaxFailures wasn't breached). + MinSuccessTime is only considered for rollout types Progressive and ProgressivePerGroup. + The default value is 0 meaning the workload applier proceeds immediately after a successful + state is reached. + MinSuccessTime must be defined in [0-9h]|[0-9m]|[0-9s] format examples; 2h , 90m , 360s + type: string + progressDeadline: + default: None + description: |- + ProgressDeadline defines how long workload applier controller will wait for the workload to + reach a successful state in the cluster. + If the workload does not reach a successful state after ProgressDeadline, will stop waiting + and workload will be treated as "timeout" and be counted into MaxFailures. Once the MaxFailures + is breached, the rollout will stop. + ProgressDeadline default value is "None", meaning the workload applier will wait for a + successful state indefinitely. + ProgressDeadline must be defined in [0-9h]|[0-9m]|[0-9s] format examples; 2h , 90m , 360s + pattern: ^(([0-9])+[h|m|s])|None$ + type: string + type: object + type: + default: All + enum: + - All + - Progressive + - ProgressivePerGroup + type: string + type: object + required: + - name + - namespace + type: object + type: array + x-kubernetes-list-map-keys: + - namespace + - name + x-kubernetes-list-type: map + type: + default: Manual + description: |- + type is the type of the install strategy, it can be: + - Manual: no automatic install + - Placements: install to clusters selected by placements. + enum: + - Manual + - Placements + type: string + type: object + type: object + status: + description: status represents the current status of cluster management + add-on. + properties: + defaultConfigReferences: + description: defaultConfigReferences is a list of current add-on default + configuration references. + items: + description: |- + DefaultConfigReference is a reference to the current add-on configuration. + This resource is used to record the configuration resource for the current add-on. + properties: + desiredConfig: + description: desiredConfig record the desired config spec hash. + properties: + name: + description: name of the add-on configuration. + minLength: 1 + type: string + namespace: + description: |- + namespace of the add-on configuration. + If this field is not set, the configuration is in the cluster scope. + type: string + specHash: + description: spec hash for an add-on configuration. + type: string + required: + - name + type: object + group: + default: "" + description: group of the add-on configuration. + type: string + resource: + description: resource of the add-on configuration. + minLength: 1 + type: string + required: + - resource + type: object + type: array + installProgressions: + description: installProgressions is a list of current add-on configuration + references per placement. + items: + properties: + conditions: + description: conditions describe the state of the managed and + monitored components for the operator. + items: + description: Condition contains details for one aspect of + the current state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + configReferences: + description: configReferences is a list of current add-on configuration + references. + items: + description: |- + InstallConfigReference is a reference to the current add-on configuration. + This resource is used to record the configuration resource for the current add-on. + properties: + desiredConfig: + description: desiredConfig record the desired config name + and spec hash. + properties: + name: + description: name of the add-on configuration. + minLength: 1 + type: string + namespace: + description: |- + namespace of the add-on configuration. + If this field is not set, the configuration is in the cluster scope. + type: string + specHash: + description: spec hash for an add-on configuration. + type: string + required: + - name + type: object + group: + default: "" + description: group of the add-on configuration. + type: string + lastAppliedConfig: + description: |- + lastAppliedConfig records the config spec hash when the all the corresponding + ManagedClusterAddOn are applied successfully. + properties: + name: + description: name of the add-on configuration. + minLength: 1 + type: string + namespace: + description: |- + namespace of the add-on configuration. + If this field is not set, the configuration is in the cluster scope. + type: string + specHash: + description: spec hash for an add-on configuration. + type: string + required: + - name + type: object + lastKnownGoodConfig: + description: |- + lastKnownGoodConfig records the last known good config spec hash. + For fresh install or rollout with type UpdateAll or RollingUpdate, the + lastKnownGoodConfig is the same as lastAppliedConfig. + For rollout with type RollingUpdateWithCanary, the lastKnownGoodConfig + is the last successfully applied config spec hash of the canary placement. + properties: + name: + description: name of the add-on configuration. + minLength: 1 + type: string + namespace: + description: |- + namespace of the add-on configuration. + If this field is not set, the configuration is in the cluster scope. + type: string + specHash: + description: spec hash for an add-on configuration. + type: string + required: + - name + type: object + resource: + description: resource of the add-on configuration. + minLength: 1 + type: string + required: + - resource + type: object + type: array + name: + description: name is the name of the placement + minLength: 1 + type: string + namespace: + description: namespace is the namespace of the placement + minLength: 1 + type: string + required: + - name + - namespace + type: object + type: array + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} status: acceptedNames: kind: "" diff --git a/manifests/cluster-manager/hub/crds/0000_01_addon.open-cluster-management.io_managedclusteraddons.crd.yaml b/manifests/cluster-manager/hub/crds/0000_01_addon.open-cluster-management.io_managedclusteraddons.crd.yaml index c6a676298..7c179bd6c 100644 --- a/manifests/cluster-manager/hub/crds/0000_01_addon.open-cluster-management.io_managedclusteraddons.crd.yaml +++ b/manifests/cluster-manager/hub/crds/0000_01_addon.open-cluster-management.io_managedclusteraddons.crd.yaml @@ -3,6 +3,19 @@ kind: CustomResourceDefinition metadata: name: managedclusteraddons.addon.open-cluster-management.io spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + caBundle: {{ .AddonAPIServiceCABundle }} + service: + name: cluster-manager-addon-webhook + namespace: {{ .ClusterManagerNamespace }} + path: /convert + port: 9443 + conversionReviewVersions: + - v1 + - v1beta1 group: addon.open-cluster-management.io names: kind: ManagedClusterAddOn @@ -399,6 +412,374 @@ spec: storage: true subresources: status: {} + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Available")].status + name: Available + type: string + - jsonPath: .status.conditions[?(@.type=="Degraded")].status + name: Degraded + type: string + - jsonPath: .status.conditions[?(@.type=="Progressing")].status + name: Progressing + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: |- + ManagedClusterAddOn is the Custom Resource object which holds the current state + of an add-on. This object is used by add-on operators to convey their state. + This resource should be created in the ManagedCluster namespace. + 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 holds configuration that could apply to any operator. + properties: + configs: + description: |- + configs is a list of add-on configurations. + In scenario where the current add-on has its own configurations. + An empty list means there are no default configurations for add-on. + The default is an empty list + items: + properties: + group: + default: "" + description: group of the add-on configuration. + type: string + name: + description: name of the add-on configuration. + minLength: 1 + type: string + namespace: + description: |- + namespace of the add-on configuration. + If this field is not set, the configuration is in the cluster scope. + type: string + resource: + description: resource of the add-on configuration. + minLength: 1 + type: string + required: + - name + - resource + type: object + type: array + type: object + status: + description: |- + status holds the information about the state of an operator. It is consistent with status information across + the Kubernetes ecosystem. + properties: + addOnMeta: + description: |- + addOnMeta is a reference to the metadata information for the add-on. + This should be same as the addOnMeta for the corresponding ClusterManagementAddOn resource. + properties: + description: + description: description represents the detailed description of + the add-on. + type: string + displayName: + description: displayName represents the name of add-on that will + be displayed. + type: string + type: object + conditions: + description: conditions describe the state of the managed and monitored + components for the operator. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + configReferences: + description: |- + configReferences is a list of current add-on configuration references. + This will be overridden by the clustermanagementaddon configuration references. + items: + description: |- + ConfigReference is a reference to the current add-on configuration. + This resource is used to locate the configuration resource for the current add-on. + properties: + desiredConfig: + description: desiredConfig record the desired config spec hash. + properties: + name: + description: name of the add-on configuration. + minLength: 1 + type: string + namespace: + description: |- + namespace of the add-on configuration. + If this field is not set, the configuration is in the cluster scope. + type: string + specHash: + description: spec hash for an add-on configuration. + type: string + required: + - name + type: object + group: + default: "" + description: group of the add-on configuration. + type: string + lastAppliedConfig: + description: lastAppliedConfig record the config spec hash when + the corresponding ManifestWork is applied successfully. + properties: + name: + description: name of the add-on configuration. + minLength: 1 + type: string + namespace: + description: |- + namespace of the add-on configuration. + If this field is not set, the configuration is in the cluster scope. + type: string + specHash: + description: spec hash for an add-on configuration. + type: string + required: + - name + type: object + lastObservedGeneration: + description: lastObservedGeneration is the observed generation + of the add-on configuration. + format: int64 + type: integer + resource: + description: resource of the add-on configuration. + minLength: 1 + type: string + required: + - resource + type: object + type: array + healthCheck: + description: |- + healthCheck indicates how to check the healthiness status of the current addon. It should be + set by each addon implementation, by default, the lease mode will be used. + properties: + mode: + default: Lease + description: mode indicates which mode will be used to check the + healthiness status of the addon. + enum: + - Lease + - Customized + type: string + type: object + namespace: + description: |- + namespace is the namespace on the managedcluster to put registration secret or lease for the addon. It is + required when registration is set or healthcheck mode is Lease. + type: string + registrations: + description: |- + registrations is the configurations for the addon agent to register to hub. It should be set by each addon controller + on hub to define how the addon agent on managedcluster is registered. With the registration defined, + The addon agent can access to kube apiserver with kube style API or other endpoints on hub cluster with client + certificate authentication. A csr will be created per registration configuration. If more than one + registrationConfig is defined, a csr will be created for each registration configuration. It is not allowed that + multiple registrationConfigs have the same signer name. After the csr is approved on the hub cluster, the klusterlet + agent will create a secret in the installNamespace for the registrationConfig. If the signerName is + "kubernetes.io/kube-apiserver-client", the secret name will be "{addon name}-hub-kubeconfig" whose contents includes + key/cert and kubeconfig. Otherwise, the secret name will be "{addon name}-{signer name}-client-cert" whose contents includes key/cert. + items: + description: RegistrationConfig defines the configuration for the + addon agent to register to the hub cluster. + properties: + csr: + description: |- + csr holds the configuration for csr type registration. + It should be set when type is "csr". + properties: + signerName: + description: signerName is the name of signer that addon + agent will use to create csr. + maxLength: 571 + minLength: 5 + pattern: ^([a-z0-9][a-z0-9-]*[a-z0-9]\.)+[a-z]+\/[a-z0-9-\.]+$ + type: string + subject: + description: subject is the user subject of the addon agent + to be registered to the hub. + properties: + groups: + description: groups is the user group of the addon agent. + items: + type: string + type: array + organizationUnits: + description: organizationUnits is the ou of the addon + agent + items: + type: string + type: array + user: + description: user is the user name of the addon agent. + type: string + type: object + required: + - signerName + type: object + kubeClient: + description: |- + kubeClient holds the configuration for kubeClient type registration. + It should be set when type is "kubeClient". + properties: + subject: + description: subject is the user subject of the addon agent + to be registered to the hub. + properties: + groups: + description: groups is the user group of the addon agent. + items: + type: string + type: array + user: + description: user is the user name of the addon agent. + type: string + type: object + type: object + type: + description: type specifies the type of registration configuration. + enum: + - kubeClient + - csr + type: string + required: + - type + type: object + type: array + relatedObjects: + description: |- + relatedObjects is a list of objects that are "interesting" or related to this operator. Common uses are: + 1. the detailed resource driving the operator + 2. operator namespaces + 3. operand namespaces + 4. related ClusterManagementAddon resource + items: + description: ObjectReference contains enough information to let + you inspect or modify the referred object. + properties: + group: + description: group of the referent. + type: string + name: + description: name of the referent. + type: string + namespace: + description: namespace of the referent. + type: string + resource: + description: resource of the referent. + type: string + required: + - group + - name + - resource + type: object + type: array + supportedConfigs: + description: |- + supportedConfigs is a list of configuration types that are allowed to override the add-on configurations defined + in ClusterManagementAddOn spec. + The default is an empty list, which means the add-on configurations can not be overridden. + items: + description: ConfigGroupResource represents the GroupResource of + the add-on configuration + properties: + group: + default: "" + description: group of the add-on configuration. + type: string + resource: + description: resource of the add-on configuration. + minLength: 1 + type: string + required: + - resource + type: object + type: array + x-kubernetes-list-map-keys: + - group + - resource + x-kubernetes-list-type: map + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} status: acceptedNames: kind: "" diff --git a/manifests/cluster-manager/management/addon-manager/webhook-deployment.yaml b/manifests/cluster-manager/management/addon-manager/webhook-deployment.yaml new file mode 100644 index 000000000..6bfe8a2d8 --- /dev/null +++ b/manifests/cluster-manager/management/addon-manager/webhook-deployment.yaml @@ -0,0 +1,107 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .ClusterManagerName }}-addon-webhook + namespace: {{ .ClusterManagerNamespace }} + labels: + app: {{ .ClusterManagerName }}-addon-webhook + {{ if gt (len .Labels) 0 }} + {{ range $key, $value := .Labels }} + "{{ $key }}": "{{ $value }}" + {{ end }} + {{ end }} +spec: + replicas: {{ .Replica }} + selector: + matchLabels: + app: {{ .ClusterManagerName }}-addon-webhook + template: + metadata: + labels: + app: {{ .ClusterManagerName }}-addon-webhook + {{ if gt (len .Labels) 0 }} + {{ range $key, $value := .Labels }} + "{{ $key }}": "{{ $value }}" + {{ end }} + {{ end }} + spec: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 70 + podAffinityTerm: + topologyKey: failure-domain.beta.kubernetes.io/zone + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - {{ .ClusterManagerName }}-addon-webhook + - weight: 30 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - {{ .ClusterManagerName }}-addon-webhook + {{- if .ImagePullSecret }} + imagePullSecrets: + - name: {{ .ImagePullSecret }} + {{- end }} + {{ if not .HostedMode }} + serviceAccountName: addon-webhook-sa + {{ end }} + containers: + - name: {{ .ClusterManagerName }}-addon-webhook + image: {{ .AddOnManagerImage }} + args: + - /addon + - "webhook-server" + - "--port=9443" + {{- if or (eq .ResourceRequirementResourceType "Default") (eq .ResourceRequirementResourceType "") }} + resources: + requests: + cpu: 2m + memory: 16Mi + {{- end }} + {{- if eq .ResourceRequirementResourceType "BestEffort" }} + resources: {} + {{- end }} + {{- if eq .ResourceRequirementResourceType "ResourceRequirement" }} + resources: + {{ .ResourceRequirements | indent 10 }} + {{- end }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + runAsNonRoot: true + readOnlyRootFilesystem: true + livenessProbe: + httpGet: + path: /healthz + scheme: HTTP + port: 8000 + initialDelaySeconds: 2 + periodSeconds: 10 + readinessProbe: + httpGet: + path: /readyz + scheme: HTTP + port: 8000 + initialDelaySeconds: 2 + ports: + - containerPort: 9443 + protocol: TCP + volumeMounts: + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: webhook-secret + readOnly: true + volumes: + - name: webhook-secret + secret: + secretName: addon-webhook-serving-cert \ No newline at end of file diff --git a/manifests/config.go b/manifests/config.go index f27ae227e..b51bc8a6b 100644 --- a/manifests/config.go +++ b/manifests/config.go @@ -11,10 +11,12 @@ type HubConfig struct { WorkImage string WorkAPIServiceCABundle string PlacementImage string + AddonAPIServiceCABundle string Replica int32 HostedMode bool RegistrationWebhook Webhook WorkWebhook Webhook + AddonWebhook Webhook RegistrationFeatureGates []string WorkFeatureGates []string AddOnManagerImage string diff --git a/pkg/addon/controllers/addonmanagement/addon_install_reconciler.go b/pkg/addon/controllers/addonmanagement/addon_install_reconciler.go index f815de521..4cde670b5 100644 --- a/pkg/addon/controllers/addonmanagement/addon_install_reconciler.go +++ b/pkg/addon/controllers/addonmanagement/addon_install_reconciler.go @@ -6,6 +6,7 @@ import ( "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime/schema" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/client-go/tools/cache" @@ -58,7 +59,11 @@ func (d *managedClusterAddonInstallReconciler) reconcile( return cma, reconcileContinue, err } - owner := metav1.NewControllerRef(cma, addonv1alpha1.GroupVersion.WithKind("ClusterManagementAddOn")) + owner := metav1.NewControllerRef(cma, schema.GroupVersionKind{ + Group: addonv1alpha1.GroupName, + Version: addonv1alpha1.GroupVersion.Version, + Kind: "ClusterManagementAddOn", + }) toAdd := requiredDeployed.Difference(existingDeployed) toRemove := existingDeployed.Difference(requiredDeployed) diff --git a/pkg/addon/controllers/addonowner/controller.go b/pkg/addon/controllers/addonowner/controller.go index 2b6dc9495..10022a04b 100644 --- a/pkg/addon/controllers/addonowner/controller.go +++ b/pkg/addon/controllers/addonowner/controller.go @@ -5,6 +5,7 @@ import ( "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/tools/cache" "k8s.io/klog/v2" @@ -94,7 +95,11 @@ func (c *addonOwnerController) sync(ctx context.Context, syncCtx factory.SyncCon return nil } - owner := metav1.NewControllerRef(clusterManagementAddon, addonapiv1alpha1.GroupVersion.WithKind("ClusterManagementAddOn")) + owner := metav1.NewControllerRef(clusterManagementAddon, schema.GroupVersionKind{ + Group: addonapiv1alpha1.GroupName, + Version: addonapiv1alpha1.GroupVersion.Version, + Kind: "ClusterManagementAddOn", + }) modified = utils.MergeOwnerRefs(&addonCopy.OwnerReferences, *owner, false) if modified { _, err = c.addonClient.AddonV1alpha1().ManagedClusterAddOns(namespace).Update(ctx, addonCopy, metav1.UpdateOptions{}) diff --git a/pkg/addon/controllers/addonowner/controller_test.go b/pkg/addon/controllers/addonowner/controller_test.go index 09466534c..e04b8bda8 100644 --- a/pkg/addon/controllers/addonowner/controller_test.go +++ b/pkg/addon/controllers/addonowner/controller_test.go @@ -7,6 +7,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" clienttesting "k8s.io/client-go/testing" "open-cluster-management.io/addon-framework/pkg/addonmanager/addontesting" @@ -20,7 +21,11 @@ import ( func newClusterManagementOwner(name string) metav1.OwnerReference { clusterManagementAddon := addontesting.NewClusterManagementAddon(name, "testcrd", "testcr").Build() - return *metav1.NewControllerRef(clusterManagementAddon, addonapiv1alpha1.GroupVersion.WithKind("ClusterManagementAddOn")) + return *metav1.NewControllerRef(clusterManagementAddon, schema.GroupVersionKind{ + Group: addonapiv1alpha1.GroupName, + Version: addonapiv1alpha1.GroupVersion.Version, + Kind: "ClusterManagementAddOn", + }) } func TestReconcile(t *testing.T) { diff --git a/pkg/addon/webhook/doc.go b/pkg/addon/webhook/doc.go new file mode 100644 index 000000000..466ff35df --- /dev/null +++ b/pkg/addon/webhook/doc.go @@ -0,0 +1,4 @@ +// Copyright Contributors to the Open Cluster Management project + +// Package webhook implements the webhook server for addon APIs +package webhook diff --git a/pkg/addon/webhook/start.go b/pkg/addon/webhook/start.go new file mode 100644 index 000000000..970aeba0e --- /dev/null +++ b/pkg/addon/webhook/start.go @@ -0,0 +1,37 @@ +// Copyright Contributors to the Open Cluster Management project + +package webhook + +import ( + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + + addonv1alpha1 "open-cluster-management.io/ocm/pkg/addon/webhook/v1alpha1" + addonv1beta1 "open-cluster-management.io/ocm/pkg/addon/webhook/v1beta1" + commonoptions "open-cluster-management.io/ocm/pkg/common/options" +) + +// SetupWebhookServer sets up the webhook server with addon API schemes and conversion webhooks +func SetupWebhookServer(opts *commonoptions.WebhookOptions) error { + // Install schemes + if err := opts.InstallScheme( + clientgoscheme.AddToScheme, + addonv1alpha1.Install, + addonv1beta1.Install, + ); err != nil { + return err + } + + // Register ManagedClusterAddOn conversion webhooks (v1alpha1 is Hub) + opts.InstallWebhook( + &addonv1alpha1.ManagedClusterAddOnWebhook{}, + &addonv1beta1.ManagedClusterAddOnWebhook{}, + ) + + // Register ClusterManagementAddOn conversion webhooks (v1alpha1 is Hub) + opts.InstallWebhook( + &addonv1alpha1.ClusterManagementAddOnWebhook{}, + &addonv1beta1.ClusterManagementAddOnWebhook{}, + ) + + return nil +} diff --git a/pkg/addon/webhook/v1alpha1/clustermanagementaddon_conversion.go b/pkg/addon/webhook/v1alpha1/clustermanagementaddon_conversion.go new file mode 100644 index 000000000..6593c8bf6 --- /dev/null +++ b/pkg/addon/webhook/v1alpha1/clustermanagementaddon_conversion.go @@ -0,0 +1,6 @@ +// Copyright Contributors to the Open Cluster Management project + +package v1alpha1 + +// Hub marks ClusterManagementAddOn as the conversion hub version +func (r *ClusterManagementAddOn) Hub() {} diff --git a/pkg/addon/webhook/v1alpha1/managedclusteraddon_conversion.go b/pkg/addon/webhook/v1alpha1/managedclusteraddon_conversion.go new file mode 100644 index 000000000..f6d5d9aa4 --- /dev/null +++ b/pkg/addon/webhook/v1alpha1/managedclusteraddon_conversion.go @@ -0,0 +1,6 @@ +// Copyright Contributors to the Open Cluster Management project + +package v1alpha1 + +// Hub marks ManagedClusterAddOn as the conversion hub version +func (r *ManagedClusterAddOn) Hub() {} diff --git a/pkg/addon/webhook/v1alpha1/webhook.go b/pkg/addon/webhook/v1alpha1/webhook.go new file mode 100644 index 000000000..a8a4b76f9 --- /dev/null +++ b/pkg/addon/webhook/v1alpha1/webhook.go @@ -0,0 +1,113 @@ +// Copyright Contributors to the Open Cluster Management project + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + ctrl "sigs.k8s.io/controller-runtime" + + addonv1alpha1 "open-cluster-management.io/api/addon/v1alpha1" +) + +var ( + schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + // Install is a function which adds this version to a scheme + Install = schemeBuilder.AddToScheme +) + +// Adds the list of known types to api.Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + gv := schema.GroupVersion{Group: addonv1alpha1.GroupName, Version: addonv1alpha1.GroupVersion.Version} + scheme.AddKnownTypes(gv, + &ManagedClusterAddOn{}, + &ClusterManagementAddOn{}, + ) + metav1.AddToGroupVersion(scheme, gv) + return nil +} + +// ManagedClusterAddOn wraps the v1alpha1 API type for conversion webhook +type ManagedClusterAddOn struct { + addonv1alpha1.ManagedClusterAddOn +} + +// DeepCopyObject returns a deep copy of the ManagedClusterAddOn wrapper +func (in *ManagedClusterAddOn) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopy returns a deep copy of the ManagedClusterAddOn wrapper +func (in *ManagedClusterAddOn) DeepCopy() *ManagedClusterAddOn { + if in == nil { + return nil + } + out := new(ManagedClusterAddOn) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto deep copies the receiver into out +func (in *ManagedClusterAddOn) DeepCopyInto(out *ManagedClusterAddOn) { + in.ManagedClusterAddOn.DeepCopyInto(&out.ManagedClusterAddOn) +} + +// ClusterManagementAddOn wraps the v1alpha1 API type for conversion webhook +type ClusterManagementAddOn struct { + addonv1alpha1.ClusterManagementAddOn +} + +// DeepCopyObject returns a deep copy of the ClusterManagementAddOn wrapper +func (in *ClusterManagementAddOn) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopy returns a deep copy of the ClusterManagementAddOn wrapper +func (in *ClusterManagementAddOn) DeepCopy() *ClusterManagementAddOn { + if in == nil { + return nil + } + out := new(ClusterManagementAddOn) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto deep copies the receiver into out +func (in *ClusterManagementAddOn) DeepCopyInto(out *ClusterManagementAddOn) { + in.ClusterManagementAddOn.DeepCopyInto(&out.ClusterManagementAddOn) +} + +// ManagedClusterAddOnWebhook implements the webhook for ManagedClusterAddOn v1alpha1 (Hub version) +type ManagedClusterAddOnWebhook struct{} + +func (w *ManagedClusterAddOnWebhook) Init(mgr ctrl.Manager) error { + return (&ManagedClusterAddOn{}).SetupWebhookWithManager(mgr) +} + +// SetupWebhookWithManager sets up the webhook with manager for ManagedClusterAddOn +func (r *ManagedClusterAddOn) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +// ClusterManagementAddOnWebhook implements the webhook for ClusterManagementAddOn v1alpha1 (Hub version) +type ClusterManagementAddOnWebhook struct{} + +func (w *ClusterManagementAddOnWebhook) Init(mgr ctrl.Manager) error { + return (&ClusterManagementAddOn{}).SetupWebhookWithManager(mgr) +} + +// SetupWebhookWithManager sets up the webhook with manager for ClusterManagementAddOn +func (r *ClusterManagementAddOn) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} diff --git a/pkg/addon/webhook/v1beta1/clustermanagementaddon_conversion.go b/pkg/addon/webhook/v1beta1/clustermanagementaddon_conversion.go new file mode 100644 index 000000000..5176bf3e5 --- /dev/null +++ b/pkg/addon/webhook/v1beta1/clustermanagementaddon_conversion.go @@ -0,0 +1,72 @@ +// Copyright Contributors to the Open Cluster Management project + +package v1beta1 + +import ( + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/klog/v2" + "sigs.k8s.io/controller-runtime/pkg/conversion" + + addonv1alpha1 "open-cluster-management.io/api/addon/v1alpha1" + addonv1beta1 "open-cluster-management.io/api/addon/v1beta1" + + internalv1alpha1 "open-cluster-management.io/ocm/pkg/addon/webhook/v1alpha1" +) + +// ConvertTo converts this ClusterManagementAddOn (v1beta1) to the Hub version (v1alpha1) +func (src *ClusterManagementAddOn) ConvertTo(dstRaw conversion.Hub) error { + dst, ok := dstRaw.(*internalv1alpha1.ClusterManagementAddOn) + if !ok { + return fmt.Errorf("expected *internalv1alpha1.ClusterManagementAddOn but got %T", dstRaw) + } + klog.V(4).Infof("Converting ClusterManagementAddOn %s from v1beta1 to v1alpha1 (Hub)", src.Name) + + // Convert the embedded v1beta1 type to v1alpha1 using the native conversion + var v1alpha1Obj addonv1alpha1.ClusterManagementAddOn + if err := addonv1beta1.Convert_v1beta1_ClusterManagementAddOn_To_v1alpha1_ClusterManagementAddOn( + &src.ClusterManagementAddOn, &v1alpha1Obj, nil); err != nil { + return fmt.Errorf("failed to convert ClusterManagementAddOn: %w", err) + } + + // Set TypeMeta for the target version - the native conversion doesn't copy these fields + // We must set the hub version (v1alpha1) here, not preserve the source version + v1alpha1Obj.TypeMeta = metav1.TypeMeta{ + Kind: "ClusterManagementAddOn", + APIVersion: addonv1alpha1.GroupVersion.String(), + } + + // Copy to the internal wrapper type + dst.ClusterManagementAddOn = v1alpha1Obj + + return nil +} + +// ConvertFrom converts from the Hub version (v1alpha1) to this version (v1beta1) +func (dst *ClusterManagementAddOn) ConvertFrom(srcRaw conversion.Hub) error { + src, ok := srcRaw.(*internalv1alpha1.ClusterManagementAddOn) + if !ok { + return fmt.Errorf("expected *internalv1alpha1.ClusterManagementAddOn but got %T", srcRaw) + } + klog.V(4).Infof("Converting ClusterManagementAddOn %s from v1alpha1 (Hub) to v1beta1", src.Name) + + // Convert the embedded v1alpha1 type to v1beta1 using the native conversion + var v1beta1Obj addonv1beta1.ClusterManagementAddOn + if err := addonv1beta1.Convert_v1alpha1_ClusterManagementAddOn_To_v1beta1_ClusterManagementAddOn( + &src.ClusterManagementAddOn, &v1beta1Obj, nil); err != nil { + return fmt.Errorf("failed to convert ClusterManagementAddOn: %w", err) + } + + // Set TypeMeta for the target version - the native conversion doesn't copy these fields + // We must set the target version (v1beta1) here, not preserve the source version + v1beta1Obj.TypeMeta = metav1.TypeMeta{ + Kind: "ClusterManagementAddOn", + APIVersion: addonv1beta1.GroupVersion.String(), + } + + // Copy to the internal wrapper type + dst.ClusterManagementAddOn = v1beta1Obj + + return nil +} diff --git a/pkg/addon/webhook/v1beta1/clustermanagementaddon_conversion_test.go b/pkg/addon/webhook/v1beta1/clustermanagementaddon_conversion_test.go new file mode 100644 index 000000000..e2f3f2d88 --- /dev/null +++ b/pkg/addon/webhook/v1beta1/clustermanagementaddon_conversion_test.go @@ -0,0 +1,438 @@ +// Copyright Contributors to the Open Cluster Management project + +package v1beta1 + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + addonv1alpha1 "open-cluster-management.io/api/addon/v1alpha1" + addonv1beta1 "open-cluster-management.io/api/addon/v1beta1" + clusterv1alpha1 "open-cluster-management.io/api/cluster/v1alpha1" + + internalv1alpha1 "open-cluster-management.io/ocm/pkg/addon/webhook/v1alpha1" +) + +func TestClusterManagementAddOnConvertTo(t *testing.T) { + cases := []struct { + name string + src *ClusterManagementAddOn + expected *internalv1alpha1.ClusterManagementAddOn + }{ + { + name: "complete conversion with all fields", + src: &ClusterManagementAddOn{ + ClusterManagementAddOn: addonv1beta1.ClusterManagementAddOn{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-addon", + }, + Spec: addonv1beta1.ClusterManagementAddOnSpec{ + AddOnMeta: addonv1beta1.AddOnMeta{ + DisplayName: "Test AddOn", + Description: "Test description", + }, + DefaultConfigs: []addonv1beta1.AddOnConfig{ + { + ConfigGroupResource: addonv1beta1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + ConfigReferent: addonv1beta1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + }, + }, + InstallStrategy: addonv1beta1.InstallStrategy{ + Type: addonv1beta1.AddonInstallStrategyPlacements, + Placements: []addonv1beta1.PlacementStrategy{ + { + PlacementRef: addonv1beta1.PlacementRef{ + Name: "placement1", + Namespace: "default", + }, + Configs: []addonv1beta1.AddOnConfig{ + { + ConfigGroupResource: addonv1beta1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + ConfigReferent: addonv1beta1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + }, + }, + RolloutStrategy: clusterv1alpha1.RolloutStrategy{ + Type: clusterv1alpha1.All, + }, + }, + }, + }, + }, + Status: addonv1beta1.ClusterManagementAddOnStatus{ + DefaultConfigReferences: []addonv1beta1.DefaultConfigReference{ + { + ConfigGroupResource: addonv1beta1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + DesiredConfig: &addonv1beta1.ConfigSpecHash{ + ConfigReferent: addonv1beta1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + SpecHash: "hash123", + }, + }, + }, + InstallProgressions: []addonv1beta1.InstallProgression{ + { + PlacementRef: addonv1beta1.PlacementRef{ + Name: "placement1", + Namespace: "default", + }, + ConfigReferences: []addonv1beta1.InstallConfigReference{ + { + ConfigGroupResource: addonv1beta1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + DesiredConfig: &addonv1beta1.ConfigSpecHash{ + ConfigReferent: addonv1beta1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + SpecHash: "hash123", + }, + }, + }, + }, + }, + }, + }, + }, + expected: &internalv1alpha1.ClusterManagementAddOn{ + ClusterManagementAddOn: addonv1alpha1.ClusterManagementAddOn{ + TypeMeta: metav1.TypeMeta{ + Kind: "ClusterManagementAddOn", + APIVersion: "addon.open-cluster-management.io/v1alpha1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-addon", + }, + Spec: addonv1alpha1.ClusterManagementAddOnSpec{ + AddOnMeta: addonv1alpha1.AddOnMeta{ + DisplayName: "Test AddOn", + Description: "Test description", + }, + SupportedConfigs: []addonv1alpha1.ConfigMeta{ + { + ConfigGroupResource: addonv1alpha1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + DefaultConfig: &addonv1alpha1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + }, + }, + InstallStrategy: addonv1alpha1.InstallStrategy{ + Type: addonv1alpha1.AddonInstallStrategyPlacements, + Placements: []addonv1alpha1.PlacementStrategy{ + { + PlacementRef: addonv1alpha1.PlacementRef{ + Name: "placement1", + Namespace: "default", + }, + Configs: []addonv1alpha1.AddOnConfig{ + { + ConfigGroupResource: addonv1alpha1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + ConfigReferent: addonv1alpha1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + }, + }, + RolloutStrategy: clusterv1alpha1.RolloutStrategy{ + Type: clusterv1alpha1.All, + }, + }, + }, + }, + }, + Status: addonv1alpha1.ClusterManagementAddOnStatus{ + DefaultConfigReferences: []addonv1alpha1.DefaultConfigReference{ + { + ConfigGroupResource: addonv1alpha1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + DesiredConfig: &addonv1alpha1.ConfigSpecHash{ + ConfigReferent: addonv1alpha1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + SpecHash: "hash123", + }, + }, + }, + InstallProgressions: []addonv1alpha1.InstallProgression{ + { + PlacementRef: addonv1alpha1.PlacementRef{ + Name: "placement1", + Namespace: "default", + }, + ConfigReferences: []addonv1alpha1.InstallConfigReference{ + { + ConfigGroupResource: addonv1alpha1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + DesiredConfig: &addonv1alpha1.ConfigSpecHash{ + ConfigReferent: addonv1alpha1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + SpecHash: "hash123", + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + dst := &internalv1alpha1.ClusterManagementAddOn{} + if err := tc.src.ConvertTo(dst); err != nil { + t.Fatalf("ConvertTo() failed: %v", err) + } + + if diff := cmp.Diff(tc.expected, dst); diff != "" { + t.Errorf("ConvertTo() mismatch (-want +got):\n%s", diff) + } + }) + } +} + +func TestClusterManagementAddOnConvertFrom(t *testing.T) { + cases := []struct { + name string + src *internalv1alpha1.ClusterManagementAddOn + expected *ClusterManagementAddOn + }{ + { + name: "complete conversion with all fields", + src: &internalv1alpha1.ClusterManagementAddOn{ + ClusterManagementAddOn: addonv1alpha1.ClusterManagementAddOn{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-addon", + }, + Spec: addonv1alpha1.ClusterManagementAddOnSpec{ + AddOnMeta: addonv1alpha1.AddOnMeta{ + DisplayName: "Test AddOn", + Description: "Test description", + }, + SupportedConfigs: []addonv1alpha1.ConfigMeta{ + { + ConfigGroupResource: addonv1alpha1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + DefaultConfig: &addonv1alpha1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + }, + }, + InstallStrategy: addonv1alpha1.InstallStrategy{ + Type: addonv1alpha1.AddonInstallStrategyPlacements, + Placements: []addonv1alpha1.PlacementStrategy{ + { + PlacementRef: addonv1alpha1.PlacementRef{ + Name: "placement1", + Namespace: "default", + }, + Configs: []addonv1alpha1.AddOnConfig{ + { + ConfigGroupResource: addonv1alpha1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + ConfigReferent: addonv1alpha1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + }, + }, + RolloutStrategy: clusterv1alpha1.RolloutStrategy{ + Type: clusterv1alpha1.All, + }, + }, + }, + }, + }, + Status: addonv1alpha1.ClusterManagementAddOnStatus{ + DefaultConfigReferences: []addonv1alpha1.DefaultConfigReference{ + { + ConfigGroupResource: addonv1alpha1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + DesiredConfig: &addonv1alpha1.ConfigSpecHash{ + ConfigReferent: addonv1alpha1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + SpecHash: "hash123", + }, + }, + }, + InstallProgressions: []addonv1alpha1.InstallProgression{ + { + PlacementRef: addonv1alpha1.PlacementRef{ + Name: "placement1", + Namespace: "default", + }, + ConfigReferences: []addonv1alpha1.InstallConfigReference{ + { + ConfigGroupResource: addonv1alpha1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + DesiredConfig: &addonv1alpha1.ConfigSpecHash{ + ConfigReferent: addonv1alpha1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + SpecHash: "hash123", + }, + }, + }, + }, + }, + }, + }, + }, + expected: &ClusterManagementAddOn{ + ClusterManagementAddOn: addonv1beta1.ClusterManagementAddOn{ + TypeMeta: metav1.TypeMeta{ + Kind: "ClusterManagementAddOn", + APIVersion: "addon.open-cluster-management.io/v1beta1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-addon", + }, + Spec: addonv1beta1.ClusterManagementAddOnSpec{ + AddOnMeta: addonv1beta1.AddOnMeta{ + DisplayName: "Test AddOn", + Description: "Test description", + }, + DefaultConfigs: []addonv1beta1.AddOnConfig{ + { + ConfigGroupResource: addonv1beta1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + ConfigReferent: addonv1beta1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + }, + }, + InstallStrategy: addonv1beta1.InstallStrategy{ + Type: addonv1beta1.AddonInstallStrategyPlacements, + Placements: []addonv1beta1.PlacementStrategy{ + { + PlacementRef: addonv1beta1.PlacementRef{ + Name: "placement1", + Namespace: "default", + }, + Configs: []addonv1beta1.AddOnConfig{ + { + ConfigGroupResource: addonv1beta1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + ConfigReferent: addonv1beta1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + }, + }, + RolloutStrategy: clusterv1alpha1.RolloutStrategy{ + Type: clusterv1alpha1.All, + }, + }, + }, + }, + }, + Status: addonv1beta1.ClusterManagementAddOnStatus{ + DefaultConfigReferences: []addonv1beta1.DefaultConfigReference{ + { + ConfigGroupResource: addonv1beta1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + DesiredConfig: &addonv1beta1.ConfigSpecHash{ + ConfigReferent: addonv1beta1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + SpecHash: "hash123", + }, + }, + }, + InstallProgressions: []addonv1beta1.InstallProgression{ + { + PlacementRef: addonv1beta1.PlacementRef{ + Name: "placement1", + Namespace: "default", + }, + ConfigReferences: []addonv1beta1.InstallConfigReference{ + { + ConfigGroupResource: addonv1beta1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + DesiredConfig: &addonv1beta1.ConfigSpecHash{ + ConfigReferent: addonv1beta1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + SpecHash: "hash123", + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + dst := &ClusterManagementAddOn{} + if err := dst.ConvertFrom(tc.src); err != nil { + t.Fatalf("ConvertFrom() failed: %v", err) + } + + if diff := cmp.Diff(tc.expected, dst); diff != "" { + t.Errorf("ConvertFrom() mismatch (-want +got):\n%s", diff) + } + }) + } +} diff --git a/pkg/addon/webhook/v1beta1/managedclusteraddon_conversion.go b/pkg/addon/webhook/v1beta1/managedclusteraddon_conversion.go new file mode 100644 index 000000000..b5c1553fd --- /dev/null +++ b/pkg/addon/webhook/v1beta1/managedclusteraddon_conversion.go @@ -0,0 +1,104 @@ +// Copyright Contributors to the Open Cluster Management project + +package v1beta1 + +import ( + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/klog/v2" + "sigs.k8s.io/controller-runtime/pkg/conversion" + + addonv1alpha1 "open-cluster-management.io/api/addon/v1alpha1" + addonv1beta1 "open-cluster-management.io/api/addon/v1beta1" + + internalv1alpha1 "open-cluster-management.io/ocm/pkg/addon/webhook/v1alpha1" +) + +const ( + // InstallNamespaceAnnotation is the annotation key for storing installNamespace + // This is used because installNamespace field was removed in v1beta1 + InstallNamespaceAnnotation = "addon.open-cluster-management.io/v1alpha1-install-namespace" +) + +// ConvertTo converts this ManagedClusterAddOn (v1beta1) to the Hub version (v1alpha1) +func (src *ManagedClusterAddOn) ConvertTo(dstRaw conversion.Hub) error { + dst, ok := dstRaw.(*internalv1alpha1.ManagedClusterAddOn) + if !ok { + return fmt.Errorf("expected *internalv1alpha1.ManagedClusterAddOn but got %T", dstRaw) + } + klog.V(4).Infof("Converting ManagedClusterAddOn %s/%s from v1beta1 to v1alpha1 (Hub)", + src.Namespace, src.Name) + + // Convert the embedded v1beta1 type to v1alpha1 using the native conversion + var v1alpha1Obj addonv1alpha1.ManagedClusterAddOn + if err := addonv1beta1.Convert_v1beta1_ManagedClusterAddOn_To_v1alpha1_ManagedClusterAddOn( + &src.ManagedClusterAddOn, &v1alpha1Obj, nil); err != nil { + return fmt.Errorf("failed to convert ManagedClusterAddOn: %w", err) + } + + // Set TypeMeta for the target version - the native conversion doesn't copy these fields + // We must set the hub version (v1alpha1) here, not preserve the source version + v1alpha1Obj.TypeMeta = metav1.TypeMeta{ + Kind: "ManagedClusterAddOn", + APIVersion: addonv1alpha1.GroupVersion.String(), + } + + // Restore installNamespace from annotation + // This field was removed in v1beta1, so we store it in annotation + if installNs, ok := src.Annotations[InstallNamespaceAnnotation]; ok { + v1alpha1Obj.Spec.InstallNamespace = installNs + } + + // Manually populate deprecated ConfigReferent field in ConfigReferences + // The native conversion doesn't handle this deprecated field from v1alpha1.ConfigReference + // We need to copy from DesiredConfig.ConfigReferent if DesiredConfig exists + for i := range v1alpha1Obj.Status.ConfigReferences { + if v1alpha1Obj.Status.ConfigReferences[i].DesiredConfig != nil { + v1alpha1Obj.Status.ConfigReferences[i].ConfigReferent = v1alpha1Obj.Status.ConfigReferences[i].DesiredConfig.ConfigReferent + } + } + + // Copy to the internal wrapper type + dst.ManagedClusterAddOn = v1alpha1Obj + + return nil +} + +// ConvertFrom converts from the Hub version (v1alpha1) to this version (v1beta1) +func (dst *ManagedClusterAddOn) ConvertFrom(srcRaw conversion.Hub) error { + src, ok := srcRaw.(*internalv1alpha1.ManagedClusterAddOn) + if !ok { + return fmt.Errorf("expected *internalv1alpha1.ManagedClusterAddOn but got %T", srcRaw) + } + klog.V(4).Infof("Converting ManagedClusterAddOn %s/%s from v1alpha1 (Hub) to v1beta1", + src.Namespace, src.Name) + + // Convert the embedded v1alpha1 type to v1beta1 using the native conversion + var v1beta1Obj addonv1beta1.ManagedClusterAddOn + if err := addonv1beta1.Convert_v1alpha1_ManagedClusterAddOn_To_v1beta1_ManagedClusterAddOn( + &src.ManagedClusterAddOn, &v1beta1Obj, nil); err != nil { + return fmt.Errorf("failed to convert ManagedClusterAddOn: %w", err) + } + + // Set TypeMeta for the target version - the native conversion doesn't copy these fields + // We must set the target version (v1beta1) here, not preserve the source version + v1beta1Obj.TypeMeta = metav1.TypeMeta{ + Kind: "ManagedClusterAddOn", + APIVersion: addonv1beta1.GroupVersion.String(), + } + + // Copy to the wrapper type + dst.ManagedClusterAddOn = v1beta1Obj + + // Save installNamespace to annotation (removed in v1beta1) + // This field exists in v1alpha1 but not in v1beta1, so we preserve it in annotations + if src.Spec.InstallNamespace != "" { + if dst.ManagedClusterAddOn.Annotations == nil { + dst.ManagedClusterAddOn.Annotations = make(map[string]string) + } + dst.ManagedClusterAddOn.Annotations[InstallNamespaceAnnotation] = src.Spec.InstallNamespace + } + + return nil +} diff --git a/pkg/addon/webhook/v1beta1/managedclusteraddon_conversion_test.go b/pkg/addon/webhook/v1beta1/managedclusteraddon_conversion_test.go new file mode 100644 index 000000000..c0faa87a9 --- /dev/null +++ b/pkg/addon/webhook/v1beta1/managedclusteraddon_conversion_test.go @@ -0,0 +1,372 @@ +// Copyright Contributors to the Open Cluster Management project + +package v1beta1 + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + addonv1alpha1 "open-cluster-management.io/api/addon/v1alpha1" + addonv1beta1 "open-cluster-management.io/api/addon/v1beta1" + + internalv1alpha1 "open-cluster-management.io/ocm/pkg/addon/webhook/v1alpha1" +) + +func TestManagedClusterAddOnConvertTo(t *testing.T) { + cases := []struct { + name string + src *ManagedClusterAddOn + expected *internalv1alpha1.ManagedClusterAddOn + }{ + { + name: "complete conversion with all fields", + src: &ManagedClusterAddOn{ + ManagedClusterAddOn: addonv1beta1.ManagedClusterAddOn{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-addon", + Namespace: "cluster1", + Annotations: map[string]string{ + "addon.open-cluster-management.io/v1alpha1-install-namespace": "test-namespace", + }, + }, + Spec: addonv1beta1.ManagedClusterAddOnSpec{ + Configs: []addonv1beta1.AddOnConfig{ + { + ConfigGroupResource: addonv1beta1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + ConfigReferent: addonv1beta1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + }, + }, + }, + Status: addonv1beta1.ManagedClusterAddOnStatus{ + Namespace: "open-cluster-management-agent-addon", + Registrations: []addonv1beta1.RegistrationConfig{ + { + Type: addonv1beta1.KubeClient, + KubeClient: &addonv1beta1.KubeClientConfig{ + Subject: addonv1beta1.KubeClientSubject{ + BaseSubject: addonv1beta1.BaseSubject{ + User: "system:addon:test", + }, + }, + }, + }, + }, + ConfigReferences: []addonv1beta1.ConfigReference{ + { + ConfigGroupResource: addonv1beta1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + DesiredConfig: &addonv1beta1.ConfigSpecHash{ + ConfigReferent: addonv1beta1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + SpecHash: "hash123", + }, + }, + }, + SupportedConfigs: []addonv1beta1.ConfigGroupResource{ + { + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + }, + RelatedObjects: []addonv1beta1.ObjectReference{ + { + Group: "apps", + Resource: "deployments", + Name: "test-deployment", + }, + }, + AddOnMeta: addonv1beta1.AddOnMeta{ + DisplayName: "Test AddOn", + Description: "Test description", + }, + HealthCheck: addonv1beta1.HealthCheck{ + Mode: addonv1beta1.HealthCheckModeCustomized, + }, + }, + }, + }, + expected: &internalv1alpha1.ManagedClusterAddOn{ + ManagedClusterAddOn: addonv1alpha1.ManagedClusterAddOn{ + TypeMeta: metav1.TypeMeta{ + Kind: "ManagedClusterAddOn", + APIVersion: "addon.open-cluster-management.io/v1alpha1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-addon", + Namespace: "cluster1", + Annotations: map[string]string{ + "addon.open-cluster-management.io/v1alpha1-install-namespace": "test-namespace", + }, + }, + Spec: addonv1alpha1.ManagedClusterAddOnSpec{ + InstallNamespace: "test-namespace", + Configs: []addonv1alpha1.AddOnConfig{ + { + ConfigGroupResource: addonv1alpha1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + ConfigReferent: addonv1alpha1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + }, + }, + }, + Status: addonv1alpha1.ManagedClusterAddOnStatus{ + Namespace: "open-cluster-management-agent-addon", + Registrations: []addonv1alpha1.RegistrationConfig{ + { + SignerName: "kubernetes.io/kube-apiserver-client", + Subject: addonv1alpha1.Subject{ + User: "system:addon:test", + }, + }, + }, + ConfigReferences: []addonv1alpha1.ConfigReference{ + { + ConfigGroupResource: addonv1alpha1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + ConfigReferent: addonv1alpha1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + DesiredConfig: &addonv1alpha1.ConfigSpecHash{ + ConfigReferent: addonv1alpha1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + SpecHash: "hash123", + }, + }, + }, + SupportedConfigs: []addonv1alpha1.ConfigGroupResource{ + { + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + }, + RelatedObjects: []addonv1alpha1.ObjectReference{ + { + Group: "apps", + Resource: "deployments", + Name: "test-deployment", + }, + }, + AddOnMeta: addonv1alpha1.AddOnMeta{ + DisplayName: "Test AddOn", + Description: "Test description", + }, + HealthCheck: addonv1alpha1.HealthCheck{ + Mode: addonv1alpha1.HealthCheckModeCustomized, + }, + }, + }, + }, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + dst := &internalv1alpha1.ManagedClusterAddOn{} + if err := tc.src.ConvertTo(dst); err != nil { + t.Fatalf("ConvertTo() failed: %v", err) + } + + if diff := cmp.Diff(tc.expected, dst); diff != "" { + t.Errorf("ConvertTo() mismatch (-want +got):\n%s", diff) + } + }) + } +} + +func TestManagedClusterAddOnConvertFrom(t *testing.T) { + cases := []struct { + name string + src *internalv1alpha1.ManagedClusterAddOn + expected *ManagedClusterAddOn + }{ + { + name: "complete conversion with all fields", + src: &internalv1alpha1.ManagedClusterAddOn{ + ManagedClusterAddOn: addonv1alpha1.ManagedClusterAddOn{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-addon", + Namespace: "cluster1", + }, + Spec: addonv1alpha1.ManagedClusterAddOnSpec{ + InstallNamespace: "test-namespace", + Configs: []addonv1alpha1.AddOnConfig{ + { + ConfigGroupResource: addonv1alpha1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + ConfigReferent: addonv1alpha1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + }, + }, + }, + Status: addonv1alpha1.ManagedClusterAddOnStatus{ + Namespace: "open-cluster-management-agent-addon", + Registrations: []addonv1alpha1.RegistrationConfig{ + { + SignerName: "kubernetes.io/kube-apiserver-client", + Subject: addonv1alpha1.Subject{ + User: "system:addon:test", + }, + }, + }, + ConfigReferences: []addonv1alpha1.ConfigReference{ + { + ConfigGroupResource: addonv1alpha1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + ConfigReferent: addonv1alpha1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + DesiredConfig: &addonv1alpha1.ConfigSpecHash{ + ConfigReferent: addonv1alpha1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + SpecHash: "hash123", + }, + }, + }, + SupportedConfigs: []addonv1alpha1.ConfigGroupResource{ + { + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + }, + RelatedObjects: []addonv1alpha1.ObjectReference{ + { + Group: "apps", + Resource: "deployments", + Name: "test-deployment", + }, + }, + AddOnMeta: addonv1alpha1.AddOnMeta{ + DisplayName: "Test AddOn", + Description: "Test description", + }, + HealthCheck: addonv1alpha1.HealthCheck{ + Mode: addonv1alpha1.HealthCheckModeCustomized, + }, + }, + }, + }, + expected: &ManagedClusterAddOn{ + ManagedClusterAddOn: addonv1beta1.ManagedClusterAddOn{ + TypeMeta: metav1.TypeMeta{ + Kind: "ManagedClusterAddOn", + APIVersion: "addon.open-cluster-management.io/v1beta1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-addon", + Namespace: "cluster1", + Annotations: map[string]string{ + "addon.open-cluster-management.io/v1alpha1-install-namespace": "test-namespace", + }, + }, + Spec: addonv1beta1.ManagedClusterAddOnSpec{ + Configs: []addonv1beta1.AddOnConfig{ + { + ConfigGroupResource: addonv1beta1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + ConfigReferent: addonv1beta1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + }, + }, + }, + Status: addonv1beta1.ManagedClusterAddOnStatus{ + Namespace: "open-cluster-management-agent-addon", + Registrations: []addonv1beta1.RegistrationConfig{ + { + Type: addonv1beta1.KubeClient, + KubeClient: &addonv1beta1.KubeClientConfig{ + Subject: addonv1beta1.KubeClientSubject{ + BaseSubject: addonv1beta1.BaseSubject{ + User: "system:addon:test", + }, + }, + }, + }, + }, + ConfigReferences: []addonv1beta1.ConfigReference{ + { + ConfigGroupResource: addonv1beta1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + DesiredConfig: &addonv1beta1.ConfigSpecHash{ + ConfigReferent: addonv1beta1.ConfigReferent{ + Name: "config1", + Namespace: "default", + }, + SpecHash: "hash123", + }, + }, + }, + SupportedConfigs: []addonv1beta1.ConfigGroupResource{ + { + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + }, + RelatedObjects: []addonv1beta1.ObjectReference{ + { + Group: "apps", + Resource: "deployments", + Name: "test-deployment", + }, + }, + AddOnMeta: addonv1beta1.AddOnMeta{ + DisplayName: "Test AddOn", + Description: "Test description", + }, + HealthCheck: addonv1beta1.HealthCheck{ + Mode: addonv1beta1.HealthCheckModeCustomized, + }, + }, + }, + }, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + dst := &ManagedClusterAddOn{} + if err := dst.ConvertFrom(tc.src); err != nil { + t.Fatalf("ConvertFrom() failed: %v", err) + } + + if diff := cmp.Diff(tc.expected, dst); diff != "" { + t.Errorf("ConvertFrom() mismatch (-want +got):\n%s", diff) + } + }) + } +} diff --git a/pkg/addon/webhook/v1beta1/webhook.go b/pkg/addon/webhook/v1beta1/webhook.go new file mode 100644 index 000000000..f6f36f8b0 --- /dev/null +++ b/pkg/addon/webhook/v1beta1/webhook.go @@ -0,0 +1,113 @@ +// Copyright Contributors to the Open Cluster Management project + +package v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + ctrl "sigs.k8s.io/controller-runtime" + + addonv1beta1 "open-cluster-management.io/api/addon/v1beta1" +) + +var ( + schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + // Install is a function which adds this version to a scheme + Install = schemeBuilder.AddToScheme +) + +// Adds the list of known types to api.Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + gv := schema.GroupVersion{Group: addonv1beta1.GroupName, Version: addonv1beta1.GroupVersion.Version} + scheme.AddKnownTypes(gv, + &ManagedClusterAddOn{}, + &ClusterManagementAddOn{}, + ) + metav1.AddToGroupVersion(scheme, gv) + return nil +} + +// ManagedClusterAddOn wraps the v1beta1 API type for conversion webhook +type ManagedClusterAddOn struct { + addonv1beta1.ManagedClusterAddOn +} + +// DeepCopyObject returns a deep copy of the ManagedClusterAddOn wrapper +func (in *ManagedClusterAddOn) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopy returns a deep copy of the ManagedClusterAddOn wrapper +func (in *ManagedClusterAddOn) DeepCopy() *ManagedClusterAddOn { + if in == nil { + return nil + } + out := new(ManagedClusterAddOn) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto deep copies the receiver into out +func (in *ManagedClusterAddOn) DeepCopyInto(out *ManagedClusterAddOn) { + in.ManagedClusterAddOn.DeepCopyInto(&out.ManagedClusterAddOn) +} + +// ClusterManagementAddOn wraps the v1beta1 API type for conversion webhook +type ClusterManagementAddOn struct { + addonv1beta1.ClusterManagementAddOn +} + +// DeepCopyObject returns a deep copy of the ClusterManagementAddOn wrapper +func (in *ClusterManagementAddOn) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopy returns a deep copy of the ClusterManagementAddOn wrapper +func (in *ClusterManagementAddOn) DeepCopy() *ClusterManagementAddOn { + if in == nil { + return nil + } + out := new(ClusterManagementAddOn) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto deep copies the receiver into out +func (in *ClusterManagementAddOn) DeepCopyInto(out *ClusterManagementAddOn) { + in.ClusterManagementAddOn.DeepCopyInto(&out.ClusterManagementAddOn) +} + +// ManagedClusterAddOnWebhook implements the webhook for ManagedClusterAddOn v1beta1 +type ManagedClusterAddOnWebhook struct{} + +func (w *ManagedClusterAddOnWebhook) Init(mgr ctrl.Manager) error { + return (&ManagedClusterAddOn{}).SetupWebhookWithManager(mgr) +} + +// SetupWebhookWithManager sets up the webhook with manager for ManagedClusterAddOn +func (src *ManagedClusterAddOn) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(src). + Complete() +} + +// ClusterManagementAddOnWebhook implements the webhook for ClusterManagementAddOn v1beta1 +type ClusterManagementAddOnWebhook struct{} + +func (w *ClusterManagementAddOnWebhook) Init(mgr ctrl.Manager) error { + return (&ClusterManagementAddOn{}).SetupWebhookWithManager(mgr) +} + +// SetupWebhookWithManager sets up the webhook with manager for ClusterManagementAddOn +func (src *ClusterManagementAddOn) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(src). + Complete() +} diff --git a/pkg/cmd/webhook/addon.go b/pkg/cmd/webhook/addon.go new file mode 100644 index 000000000..f362e2e32 --- /dev/null +++ b/pkg/cmd/webhook/addon.go @@ -0,0 +1,31 @@ +// Copyright Contributors to the Open Cluster Management project + +package webhook + +import ( + "github.com/spf13/cobra" + ctrl "sigs.k8s.io/controller-runtime" + + "open-cluster-management.io/ocm/pkg/addon/webhook" + commonoptions "open-cluster-management.io/ocm/pkg/common/options" +) + +// NewAddonWebhook creates a new addon webhook server command +func NewAddonWebhook() *cobra.Command { + webhookOptions := commonoptions.NewWebhookOptions() + cmd := &cobra.Command{ + Use: "webhook-server", + Short: "Start the addon conversion webhook server", + RunE: func(c *cobra.Command, args []string) error { + if err := webhook.SetupWebhookServer(webhookOptions); err != nil { + return err + } + return webhookOptions.RunWebhookServer(ctrl.SetupSignalHandler()) + }, + } + + flags := cmd.Flags() + webhookOptions.AddFlags(flags) + + return cmd +} diff --git a/pkg/cmd/webhook/addon_test.go b/pkg/cmd/webhook/addon_test.go new file mode 100644 index 000000000..b3f694ffc --- /dev/null +++ b/pkg/cmd/webhook/addon_test.go @@ -0,0 +1,18 @@ +package webhook + +import ( + "testing" +) + +func TestNewAddonWebhook(t *testing.T) { + cmd := NewAddonWebhook() + if cmd == nil { + t.Errorf("NewAddonWebhook() should not return nil") + } + if cmd.Use != "webhook-server" { + t.Errorf("expected webhook-server, but got %s", cmd.Use) + } + if cmd.Short != "Start the addon conversion webhook server" { + t.Errorf("expected 'Start the addon conversion webhook server', but got %s", cmd.Short) + } +} diff --git a/pkg/operator/helpers/queuekey.go b/pkg/operator/helpers/queuekey.go index fec5b1845..86e112319 100644 --- a/pkg/operator/helpers/queuekey.go +++ b/pkg/operator/helpers/queuekey.go @@ -41,6 +41,8 @@ const ( RegistrationWebhookService = "cluster-manager-registration-webhook" WorkWebhookSecret = "work-webhook-serving-cert" // #nosec G101 WorkWebhookService = "cluster-manager-work-webhook" + AddonWebhookSecret = "addon-webhook-serving-cert" // #nosec G101 + AddonWebhookService = "cluster-manager-addon-webhook" SignerSecret = "signer-secret" CaBundleConfigmap = "ca-bundle-configmap" @@ -118,6 +120,7 @@ func ClusterManagerDeploymentQueueKeyFunc(clusterManagerLister operatorlister.Cl strings.HasSuffix(name, "registration-webhook") || strings.HasSuffix(name, "work-webhook") || strings.HasSuffix(name, "addon-manager-controller") || + strings.HasSuffix(name, "addon-webhook") || strings.HasSuffix(name, "work-controller") || strings.HasSuffix(name, "placement-controller") { interestedObjectFound = true diff --git a/pkg/operator/operators/clustermanager/controllers/certrotationcontroller/certrotation_controller.go b/pkg/operator/operators/clustermanager/controllers/certrotationcontroller/certrotation_controller.go index e08cc4f42..aa5e40527 100644 --- a/pkg/operator/operators/clustermanager/controllers/certrotationcontroller/certrotation_controller.go +++ b/pkg/operator/operators/clustermanager/controllers/certrotationcontroller/certrotation_controller.go @@ -81,6 +81,7 @@ func NewCertRotationController( secretInformers[helpers.SignerSecret].Informer(), secretInformers[helpers.RegistrationWebhookSecret].Informer(), secretInformers[helpers.WorkWebhookSecret].Informer(), + secretInformers[helpers.AddonWebhookSecret].Informer(), secretInformers[helpers.GRPCServerSecret].Informer()). ToController("CertRotationController") } @@ -165,6 +166,12 @@ func (c certRotationController) syncOne(ctx context.Context, clustermanager *ope return fmt.Errorf("clean up deleted cluster-manager, deleting work webhook secret failed, err:%s", err.Error()) } + // delete addon webhook secret + err = c.kubeClient.CoreV1().Secrets(clustermanagerNamespace).Delete(ctx, helpers.AddonWebhookSecret, metav1.DeleteOptions{}) + if err != nil && !errors.IsNotFound(err) { + return fmt.Errorf("clean up deleted cluster-manager, deleting addon webhook secret failed, err:%s", err.Error()) + } + // delete grpc server secret err = c.kubeClient.CoreV1().Secrets(clustermanagerNamespace).Delete(ctx, helpers.GRPCServerSecret, metav1.DeleteOptions{}) if err != nil && !errors.IsNotFound(err) { @@ -229,6 +236,14 @@ func (c certRotationController) syncOne(ctx context.Context, clustermanager *ope Lister: c.secretInformers[helpers.WorkWebhookSecret].Lister(), Client: c.kubeClient.CoreV1(), }, + helpers.AddonWebhookSecret: { + Namespace: clustermanagerNamespace, + Name: helpers.AddonWebhookSecret, + Validity: TargetCertValidity, + HostNames: []string{fmt.Sprintf("%s.%s.svc", helpers.AddonWebhookService, clustermanagerNamespace)}, + Lister: c.secretInformers[helpers.AddonWebhookSecret].Lister(), + Client: c.kubeClient.CoreV1(), + }, } c.rotationMap[clustermanagerName] = rotations{ diff --git a/pkg/operator/operators/clustermanager/controllers/certrotationcontroller/certrotation_controller_test.go b/pkg/operator/operators/clustermanager/controllers/certrotationcontroller/certrotation_controller_test.go index c45a363b1..23e5402eb 100644 --- a/pkg/operator/operators/clustermanager/controllers/certrotationcontroller/certrotation_controller_test.go +++ b/pkg/operator/operators/clustermanager/controllers/certrotationcontroller/certrotation_controller_test.go @@ -175,6 +175,7 @@ func TestCertRotation(t *testing.T) { helpers.SignerSecret: newOnTermInformer(helpers.SignerSecret).Core().V1().Secrets(), helpers.RegistrationWebhookSecret: newOnTermInformer(helpers.RegistrationWebhookSecret).Core().V1().Secrets(), helpers.WorkWebhookSecret: newOnTermInformer(helpers.WorkWebhookSecret).Core().V1().Secrets(), + helpers.AddonWebhookSecret: newOnTermInformer(helpers.AddonWebhookSecret).Core().V1().Secrets(), helpers.GRPCServerSecret: newOnTermInformer(helpers.GRPCServerSecret).Core().V1().Secrets(), } @@ -318,6 +319,7 @@ func TestCertRotationGRPCAuth(t *testing.T) { helpers.SignerSecret: newOnTermInformer(helpers.SignerSecret).Core().V1().Secrets(), helpers.RegistrationWebhookSecret: newOnTermInformer(helpers.RegistrationWebhookSecret).Core().V1().Secrets(), helpers.WorkWebhookSecret: newOnTermInformer(helpers.WorkWebhookSecret).Core().V1().Secrets(), + helpers.AddonWebhookSecret: newOnTermInformer(helpers.AddonWebhookSecret).Core().V1().Secrets(), helpers.GRPCServerSecret: newOnTermInformer(helpers.GRPCServerSecret).Core().V1().Secrets(), } @@ -673,6 +675,7 @@ func TestCertRotationGRPCServerHostNames(t *testing.T) { helpers.SignerSecret: newOnTermInformer(helpers.SignerSecret).Core().V1().Secrets(), helpers.RegistrationWebhookSecret: newOnTermInformer(helpers.RegistrationWebhookSecret).Core().V1().Secrets(), helpers.WorkWebhookSecret: newOnTermInformer(helpers.WorkWebhookSecret).Core().V1().Secrets(), + helpers.AddonWebhookSecret: newOnTermInformer(helpers.AddonWebhookSecret).Core().V1().Secrets(), helpers.GRPCServerSecret: newOnTermInformer(helpers.GRPCServerSecret).Core().V1().Secrets(), } diff --git a/pkg/operator/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_controller.go b/pkg/operator/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_controller.go index aa338f7b5..e18f521a5 100644 --- a/pkg/operator/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_controller.go +++ b/pkg/operator/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_controller.go @@ -170,6 +170,9 @@ func (n *clusterManagerController) sync(ctx context.Context, controllerContext f WorkWebhook: manifests.Webhook{ Port: defaultWebhookPort, }, + AddonWebhook: manifests.Webhook{ + Port: defaultWebhookPort, + }, ResourceRequirementResourceType: helpers.ResourceType(clusterManager), ResourceRequirements: resourceRequirements, WorkDriver: string(workDriver), @@ -294,6 +297,7 @@ func (n *clusterManagerController) sync(ctx context.Context, controllerContext f encodedCaBundle := base64.StdEncoding.EncodeToString([]byte(caBundle)) config.RegistrationAPIServiceCABundle = encodedCaBundle config.WorkAPIServiceCABundle = encodedCaBundle + config.AddonAPIServiceCABundle = encodedCaBundle // check imagePulSecret here because there will be a warning event FailedToRetrieveImagePullSecret // if imagePullSecret does not exist. diff --git a/pkg/operator/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_controller_test.go b/pkg/operator/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_controller_test.go index 88030f37f..7fd1ca935 100644 --- a/pkg/operator/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_controller_test.go +++ b/pkg/operator/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_controller_test.go @@ -249,6 +249,29 @@ func setDeployment(clusterManagerName, clusterManagerNamespace string) []runtime ObservedGeneration: 1, }, }, + &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: clusterManagerName + "-addon-webhook", + Namespace: clusterManagerNamespace, + Generation: 1, + }, + Spec: appsv1.DeploymentSpec{ + Template: corev1.PodTemplateSpec{ + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: clusterManagerName + "-addon-webhook", + }, + }, + }, + }, + Replicas: &replicas, + }, + Status: appsv1.DeploymentStatus{ + ReadyReplicas: replicas, + ObservedGeneration: 1, + }, + }, &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: clusterManagerName + "-grpc-server", @@ -545,7 +568,7 @@ func TestSyncDeploy(t *testing.T) { "open-cluster-management.io/cluster-name": "test"} clusterManager := newClusterManager("testhub") clusterManager.SetLabels(labels) - assertDeployments(t, clusterManager, 28, 12) + assertDeployments(t, clusterManager, 30, 12) } func TestSyncDeployWithGRPCAuthEnabled(t *testing.T) { @@ -563,7 +586,7 @@ func TestSyncDeployWithGRPCAuthEnabled(t *testing.T) { }, }, } - assertDeployments(t, clusterManager, 32, 12) + assertDeployments(t, clusterManager, 34, 12) } func TestSyncDeployNoWebhook(t *testing.T) { @@ -589,7 +612,7 @@ func TestSyncDeployNoWebhook(t *testing.T) { // Check if resources are created as expected // We expect create the namespace twice respectively in the management cluster and the hub cluster. - testingcommon.AssertEqualNumber(t, len(createKubeObjects), 30) + testingcommon.AssertEqualNumber(t, len(createKubeObjects), 33) for _, object := range createKubeObjects { ensureObject(t, object, clusterManager, false) } @@ -612,7 +635,7 @@ func TestSyncDelete(t *testing.T) { now := metav1.Now() clusterManager.ObjectMeta.SetDeletionTimestamp(&now) - assertDeletion(t, clusterManager, 30, 16) + assertDeletion(t, clusterManager, 32, 16) } func TestSyncDeleteWithGRPCAuthEnabled(t *testing.T) { @@ -629,7 +652,7 @@ func TestSyncDeleteWithGRPCAuthEnabled(t *testing.T) { } now := metav1.Now() clusterManager.ObjectMeta.SetDeletionTimestamp(&now) - assertDeletion(t, clusterManager, 34, 16) + assertDeletion(t, clusterManager, 36, 16) } // TestDeleteCRD test delete crds @@ -802,6 +825,7 @@ func newFakeHubConfigWithResourceRequirement(t *testing.T, r *operatorapiv1.Reso func getManifestFiles() []string { return []string{ "cluster-manager/management/addon-manager/deployment.yaml", + "cluster-manager/management/addon-manager/webhook-deployment.yaml", "cluster-manager/management/work/deployment.yaml", "cluster-manager/management/placement/deployment.yaml", "cluster-manager/management/registration/deployment.yaml", diff --git a/pkg/operator/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_hub_reconcile.go b/pkg/operator/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_hub_reconcile.go index 4dcbc56df..3ae8c3d2a 100644 --- a/pkg/operator/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_hub_reconcile.go +++ b/pkg/operator/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_hub_reconcile.go @@ -45,6 +45,8 @@ var ( "cluster-manager/hub/placement/clusterrole.yaml", "cluster-manager/hub/placement/clusterrolebinding.yaml", "cluster-manager/hub/placement/serviceaccount.yaml", + // addon-webhook + "cluster-manager/hub/addon-manager/webhook-serviceaccount.yaml", } workControllerResourceFiles = []string{ @@ -66,13 +68,16 @@ var ( hubDefaultWebhookServiceFiles = []string{ "cluster-manager/hub/registration/webhook-service.yaml", "cluster-manager/hub/work/webhook-service.yaml", + "cluster-manager/hub/addon-manager/webhook-service.yaml", } + // Note: addon conversion webhook is not supported in hosted mode hubHostedWebhookServiceFiles = []string{ "cluster-manager/hub/registration/webhook-service-hosted.yaml", "cluster-manager/hub/work/webhook-service-hosted.yaml", } // hubHostedWebhookEndpointFiles only apply when the deploy mode is hosted and address is IPFormat. + // Note: addon conversion webhook is not supported in hosted mode hubHostedWebhookEndpointRegistration = "cluster-manager/hub/registration/webhook-endpoint-hosted.yaml" hubHostedWebhookEndpointWork = "cluster-manager/hub/work/webhook-endpoint-hosted.yaml" @@ -177,6 +182,7 @@ func getHubResources(mode operatorapiv1.InstallMode, config manifests.HubConfig) } // the hubHostedWebhookServiceFiles are only used in hosted mode + // Note: addon conversion webhook is not supported in hosted mode if helpers.IsHosted(mode) { hubResources = append(hubResources, hubHostedWebhookServiceFiles...) if config.RegistrationWebhook.IsIPFormat { diff --git a/pkg/operator/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_runtime_reconcile.go b/pkg/operator/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_runtime_reconcile.go index 196b1b01e..6526f5c1c 100644 --- a/pkg/operator/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_runtime_reconcile.go +++ b/pkg/operator/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_runtime_reconcile.go @@ -31,6 +31,7 @@ var ( "cluster-manager/management/registration/webhook-deployment.yaml", "cluster-manager/management/work/webhook-deployment.yaml", "cluster-manager/management/placement/deployment.yaml", + "cluster-manager/management/addon-manager/webhook-deployment.yaml", } addOnManagerDeploymentFiles = []string{ diff --git a/pkg/operator/operators/clustermanager/controllers/migrationcontroller/migration_controller.go b/pkg/operator/operators/clustermanager/controllers/migrationcontroller/migration_controller.go index 71d8fa68a..fc61ff732 100644 --- a/pkg/operator/operators/clustermanager/controllers/migrationcontroller/migration_controller.go +++ b/pkg/operator/operators/clustermanager/controllers/migrationcontroller/migration_controller.go @@ -16,6 +16,7 @@ import ( "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" @@ -456,9 +457,14 @@ func generateHubClients(hubKubeConfig *rest.Config) (apiextensionsclient.Interfa } func newClusterManagerOwner(clusterManager *operatorapiv1.ClusterManager) metav1.OwnerReference { + gvk := schema.GroupVersionKind{ + Group: operatorapiv1.GroupName, + Version: operatorapiv1.GroupVersion.Version, + Kind: "ClusterManager", + } return metav1.OwnerReference{ - APIVersion: operatorapiv1.GroupVersion.WithKind("ClusterManager").GroupVersion().String(), - Kind: operatorapiv1.GroupVersion.WithKind("ClusterManager").Kind, + APIVersion: gvk.GroupVersion().String(), + Kind: gvk.Kind, Name: clusterManager.Name, UID: clusterManager.UID, } diff --git a/pkg/operator/operators/clustermanager/options.go b/pkg/operator/operators/clustermanager/options.go index d64a35b8d..5e1644d75 100644 --- a/pkg/operator/operators/clustermanager/options.go +++ b/pkg/operator/operators/clustermanager/options.go @@ -57,6 +57,7 @@ func (o *Options) RunClusterManagerOperator(ctx context.Context, controllerConte signerSecretInformer := newOneTermInformer(helpers.SignerSecret) registrationSecretInformer := newOneTermInformer(helpers.RegistrationWebhookSecret) workSecretInformer := newOneTermInformer(helpers.WorkWebhookSecret) + addonSecretInformer := newOneTermInformer(helpers.AddonWebhookSecret) grpcServerSecretInformer := newOneTermInformer(helpers.GRPCServerSecret) configmapInformer := newOneTermInformer(helpers.CaBundleConfigmap) @@ -77,6 +78,7 @@ func (o *Options) RunClusterManagerOperator(ctx context.Context, controllerConte helpers.SignerSecret: signerSecretInformer.Core().V1().Secrets(), helpers.RegistrationWebhookSecret: registrationSecretInformer.Core().V1().Secrets(), helpers.WorkWebhookSecret: workSecretInformer.Core().V1().Secrets(), + helpers.AddonWebhookSecret: addonSecretInformer.Core().V1().Secrets(), helpers.GRPCServerSecret: grpcServerSecretInformer.Core().V1().Secrets(), } @@ -128,6 +130,7 @@ func (o *Options) RunClusterManagerOperator(ctx context.Context, controllerConte go signerSecretInformer.Start(ctx.Done()) go registrationSecretInformer.Start(ctx.Done()) go workSecretInformer.Start(ctx.Done()) + go addonSecretInformer.Start(ctx.Done()) go grpcServerSecretInformer.Start(ctx.Done()) go configmapInformer.Start(ctx.Done()) go clusterManagerController.Run(ctx, 1) diff --git a/pkg/placement/controllers/scheduling/scheduling_controller.go b/pkg/placement/controllers/scheduling/scheduling_controller.go index 02b617908..afa924e7f 100644 --- a/pkg/placement/controllers/scheduling/scheduling_controller.go +++ b/pkg/placement/controllers/scheduling/scheduling_controller.go @@ -16,6 +16,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/selection" "k8s.io/apimachinery/pkg/util/intstr" utilruntime "k8s.io/apimachinery/pkg/util/runtime" @@ -577,7 +578,11 @@ func (c *schedulingController) generateDecision( var placementDecisions []*clusterapiv1beta1.PlacementDecision for index, decisionSlice := range decisionSlices { placementDecisionName := fmt.Sprintf("%s-decision-%d", placement.Name, placementDecisionIndex+index) - owner := metav1.NewControllerRef(placement, clusterapiv1beta1.GroupVersion.WithKind("Placement")) + owner := metav1.NewControllerRef(placement, schema.GroupVersionKind{ + Group: clusterapiv1beta1.GroupName, + Version: clusterapiv1beta1.GroupVersion.Version, + Kind: "Placement", + }) placementDecision := &clusterapiv1beta1.PlacementDecision{ ObjectMeta: metav1.ObjectMeta{ Name: placementDecisionName, diff --git a/pkg/registration/webhook/v1beta2/webhook.go b/pkg/registration/webhook/v1beta2/webhook.go index 990163a9b..7e1028ba4 100644 --- a/pkg/registration/webhook/v1beta2/webhook.go +++ b/pkg/registration/webhook/v1beta2/webhook.go @@ -3,6 +3,7 @@ package v1beta2 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/kubernetes" ctrl "sigs.k8s.io/controller-runtime" @@ -17,11 +18,12 @@ var ( // Adds the list of known types to api.Scheme. func addKnownTypes(scheme *runtime.Scheme) error { - scheme.AddKnownTypes(v1beta2.GroupVersion, + gv := schema.GroupVersion{Group: v1beta2.GroupName, Version: v1beta2.GroupVersion.Version} + scheme.AddKnownTypes(gv, &ManagedClusterSet{}, &v1beta2.ManagedClusterSetBinding{}, ) - metav1.AddToGroupVersion(scheme, v1beta2.GroupVersion) + metav1.AddToGroupVersion(scheme, gv) return nil } diff --git a/pkg/work/helper/helpers.go b/pkg/work/helper/helpers.go index bd6e4bada..20737354a 100644 --- a/pkg/work/helper/helpers.go +++ b/pkg/work/helper/helpers.go @@ -345,9 +345,14 @@ func IsOwnedBy(myOwner metav1.OwnerReference, existingOwners []metav1.OwnerRefer } func NewAppliedManifestWorkOwner(appliedWork *workapiv1.AppliedManifestWork) *metav1.OwnerReference { + gvk := schema.GroupVersionKind{ + Group: workapiv1.GroupName, + Version: workapiv1.GroupVersion.Version, + Kind: "AppliedManifestWork", + } return &metav1.OwnerReference{ - APIVersion: workapiv1.GroupVersion.WithKind("AppliedManifestWork").GroupVersion().String(), - Kind: workapiv1.GroupVersion.WithKind("AppliedManifestWork").Kind, + APIVersion: gvk.GroupVersion().String(), + Kind: gvk.Kind, Name: appliedWork.Name, UID: appliedWork.UID, } diff --git a/test/e2e/addon_conversion_webhook_test.go b/test/e2e/addon_conversion_webhook_test.go new file mode 100644 index 000000000..f395f5318 --- /dev/null +++ b/test/e2e/addon_conversion_webhook_test.go @@ -0,0 +1,825 @@ +package e2e + +import ( + "context" + "fmt" + "reflect" + + ginkgo "github.com/onsi/ginkgo/v2" + "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/rand" + + addonv1alpha1 "open-cluster-management.io/api/addon/v1alpha1" + addonv1beta1 "open-cluster-management.io/api/addon/v1beta1" +) + +var _ = ginkgo.Describe("Create v1alpha1 ManagedClusterAddOn", ginkgo.Label("addon-conversion"), func() { + ginkgo.It("Create a v1alpha1 ManagedClusterAddOn and get/update/delete with v1alpha1 client", func() { + clusterName := universalClusterName + suffix := rand.String(6) + addonName := fmt.Sprintf("addon-%s", suffix) + + ginkgo.By("Create a v1alpha1 ManagedClusterAddOn") + addon := &addonv1alpha1.ManagedClusterAddOn{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: clusterName, + Name: addonName, + }, + Spec: addonv1alpha1.ManagedClusterAddOnSpec{ + InstallNamespace: "test-install-ns", + }, + } + + _, err := hub.AddonClient.AddonV1alpha1().ManagedClusterAddOns(clusterName).Create( + context.Background(), addon, metav1.CreateOptions{}) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + + ginkgo.By("Get v1alpha1 ManagedClusterAddOn using v1alpha1 client") + gomega.Eventually(func() bool { + addon, err = hub.GetManagedClusterAddOnV1Alpha1(clusterName, addonName) + if err != nil { + return false + } + return true + }).Should(gomega.BeTrue()) + + ginkgo.By("Update v1alpha1 ManagedClusterAddOn status using v1alpha1 client") + gomega.Eventually(func() error { + addon, err = hub.GetManagedClusterAddOnV1Alpha1(clusterName, addonName) + if err != nil { + return err + } + // Only update if not already set + if len(addon.Status.ConfigReferences) == 0 { + addon.Status.ConfigReferences = []addonv1alpha1.ConfigReference{ + { + ConfigGroupResource: addonv1alpha1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + ConfigReferent: addonv1alpha1.ConfigReferent{ + Namespace: "test-ns", + Name: "test-config", + }, + DesiredConfig: &addonv1alpha1.ConfigSpecHash{ + ConfigReferent: addonv1alpha1.ConfigReferent{ + Namespace: "test-ns", + Name: "test-config", + }, + }, + }, + } + } + _, err = hub.AddonClient.AddonV1alpha1().ManagedClusterAddOns(clusterName).UpdateStatus( + context.Background(), addon, metav1.UpdateOptions{}) + return err + }).Should(gomega.Succeed()) + + ginkgo.By("Delete v1alpha1 ManagedClusterAddOn using v1alpha1 client") + gomega.Eventually(func() bool { + err = hub.AddonClient.AddonV1alpha1().ManagedClusterAddOns(clusterName).Delete( + context.Background(), addonName, metav1.DeleteOptions{}) + if err != nil { + return false + } + return true + }).Should(gomega.BeTrue()) + }) + + ginkgo.It("Create a v1alpha1 ManagedClusterAddOn and get/update/delete with v1beta1 client", func() { + clusterName := universalClusterName + suffix := rand.String(6) + addonName := fmt.Sprintf("addon-%s", suffix) + + ginkgo.By("Create a v1alpha1 ManagedClusterAddOn") + addon := &addonv1alpha1.ManagedClusterAddOn{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: clusterName, + Name: addonName, + }, + Spec: addonv1alpha1.ManagedClusterAddOnSpec{ + InstallNamespace: "test-install-ns", + }, + } + + _, err := hub.AddonClient.AddonV1alpha1().ManagedClusterAddOns(clusterName).Create( + context.Background(), addon, metav1.CreateOptions{}) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + + ginkgo.By("Update v1alpha1 ManagedClusterAddOn status using v1alpha1 client") + gomega.Eventually(func() error { + addon, err = hub.GetManagedClusterAddOnV1Alpha1(clusterName, addonName) + if err != nil { + return err + } + // Only update if not already set + if len(addon.Status.ConfigReferences) == 0 { + addon.Status.ConfigReferences = []addonv1alpha1.ConfigReference{ + { + ConfigGroupResource: addonv1alpha1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + ConfigReferent: addonv1alpha1.ConfigReferent{ + Namespace: "test-ns", + Name: "test-config", + }, + DesiredConfig: &addonv1alpha1.ConfigSpecHash{ + ConfigReferent: addonv1alpha1.ConfigReferent{ + Namespace: "test-ns", + Name: "test-config", + }, + }, + }, + } + } + _, err = hub.AddonClient.AddonV1alpha1().ManagedClusterAddOns(clusterName).UpdateStatus( + context.Background(), addon, metav1.UpdateOptions{}) + return err + }).Should(gomega.Succeed()) + + ginkgo.By("Get v1alpha1 ManagedClusterAddOn using v1beta1 client and verify conversion") + gomega.Eventually(func() bool { + v1beta1Addon, err := hub.GetManagedClusterAddOnV1Beta1(clusterName, addonName) + if err != nil { + return false + } + // Verify InstallNamespace annotation is preserved + if v1beta1Addon.Annotations["addon.open-cluster-management.io/v1alpha1-install-namespace"] != "test-install-ns" { + return false + } + // Verify status.ConfigReferences conversion + if len(v1beta1Addon.Status.ConfigReferences) != 1 { + return false + } + if v1beta1Addon.Status.ConfigReferences[0].DesiredConfig == nil { + return false + } + if v1beta1Addon.Status.ConfigReferences[0].DesiredConfig.Name != "test-config" { + return false + } + return true + }).Should(gomega.BeTrue()) + + ginkgo.By("Update v1alpha1 ManagedClusterAddOn status using v1beta1 client") + gomega.Eventually(func() error { + v1beta1Addon, err := hub.GetManagedClusterAddOnV1Beta1(clusterName, addonName) + if err != nil { + return err + } + // Only append if not already present (should have 2 configs after append) + if len(v1beta1Addon.Status.ConfigReferences) < 2 { + v1beta1Addon.Status.ConfigReferences = append(v1beta1Addon.Status.ConfigReferences, + addonv1beta1.ConfigReference{ + ConfigGroupResource: addonv1beta1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + DesiredConfig: &addonv1beta1.ConfigSpecHash{ + ConfigReferent: addonv1beta1.ConfigReferent{ + Namespace: "beta-ns", + Name: "beta-config", + }, + }, + }) + } + _, err = hub.AddonClient.AddonV1beta1().ManagedClusterAddOns(clusterName).UpdateStatus( + context.Background(), v1beta1Addon, metav1.UpdateOptions{}) + return err + }).Should(gomega.Succeed()) + + ginkgo.By("Verify status update via v1alpha1 client") + gomega.Eventually(func() bool { + addon, err = hub.GetManagedClusterAddOnV1Alpha1(clusterName, addonName) + if err != nil { + return false + } + return len(addon.Status.ConfigReferences) == 2 + }).Should(gomega.BeTrue()) + + ginkgo.By("Delete v1alpha1 ManagedClusterAddOn using v1beta1 client") + gomega.Eventually(func() bool { + err = hub.AddonClient.AddonV1beta1().ManagedClusterAddOns(clusterName).Delete( + context.Background(), addonName, metav1.DeleteOptions{}) + if err != nil { + return false + } + return true + }).Should(gomega.BeTrue()) + }) +}) + +var _ = ginkgo.Describe("Create v1beta1 ManagedClusterAddOn", ginkgo.Label("addon-conversion"), func() { + ginkgo.It("Create a v1beta1 ManagedClusterAddOn and get/update/delete with v1beta1 client", func() { + clusterName := universalClusterName + suffix := rand.String(6) + addonName := fmt.Sprintf("addon-%s", suffix) + + ginkgo.By("Create a v1beta1 ManagedClusterAddOn") + addon := &addonv1beta1.ManagedClusterAddOn{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: clusterName, + Name: addonName, + }, + Spec: addonv1beta1.ManagedClusterAddOnSpec{}, + } + + _, err := hub.AddonClient.AddonV1beta1().ManagedClusterAddOns(clusterName).Create( + context.Background(), addon, metav1.CreateOptions{}) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + + ginkgo.By("Get v1beta1 ManagedClusterAddOn using v1beta1 client") + gomega.Eventually(func() bool { + addon, err = hub.GetManagedClusterAddOnV1Beta1(clusterName, addonName) + if err != nil { + return false + } + return true + }).Should(gomega.BeTrue()) + + ginkgo.By("Update v1beta1 ManagedClusterAddOn status using v1beta1 client") + gomega.Eventually(func() bool { + addon, err = hub.GetManagedClusterAddOnV1Beta1(clusterName, addonName) + if err != nil { + return false + } + addon.Status.ConfigReferences = []addonv1beta1.ConfigReference{ + { + ConfigGroupResource: addonv1beta1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + DesiredConfig: &addonv1beta1.ConfigSpecHash{ + ConfigReferent: addonv1beta1.ConfigReferent{ + Namespace: "test-ns", + Name: "test-config", + }, + }, + }, + } + _, err = hub.AddonClient.AddonV1beta1().ManagedClusterAddOns(clusterName).UpdateStatus( + context.Background(), addon, metav1.UpdateOptions{}) + if err != nil { + return false + } + return true + }).Should(gomega.BeTrue()) + + ginkgo.By("Delete v1beta1 ManagedClusterAddOn using v1beta1 client") + gomega.Eventually(func() bool { + err = hub.AddonClient.AddonV1beta1().ManagedClusterAddOns(clusterName).Delete( + context.Background(), addonName, metav1.DeleteOptions{}) + if err != nil { + return false + } + return true + }).Should(gomega.BeTrue()) + }) + + ginkgo.It("Create a v1beta1 ManagedClusterAddOn and get/update/delete with v1alpha1 client", func() { + clusterName := universalClusterName + suffix := rand.String(6) + addonName := fmt.Sprintf("addon-%s", suffix) + + ginkgo.By("Create a v1beta1 ManagedClusterAddOn") + addon := &addonv1beta1.ManagedClusterAddOn{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: clusterName, + Name: addonName, + }, + Spec: addonv1beta1.ManagedClusterAddOnSpec{}, + } + + _, err := hub.AddonClient.AddonV1beta1().ManagedClusterAddOns(clusterName).Create( + context.Background(), addon, metav1.CreateOptions{}) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + + ginkgo.By("Update v1beta1 ManagedClusterAddOn status using v1beta1 client") + gomega.Eventually(func() bool { + addon, err = hub.GetManagedClusterAddOnV1Beta1(clusterName, addonName) + if err != nil { + return false + } + addon.Status.ConfigReferences = []addonv1beta1.ConfigReference{ + { + ConfigGroupResource: addonv1beta1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + DesiredConfig: &addonv1beta1.ConfigSpecHash{ + ConfigReferent: addonv1beta1.ConfigReferent{ + Namespace: "test-ns", + Name: "test-config", + }, + }, + }, + } + _, err = hub.AddonClient.AddonV1beta1().ManagedClusterAddOns(clusterName).UpdateStatus( + context.Background(), addon, metav1.UpdateOptions{}) + if err != nil { + return false + } + return true + }).Should(gomega.BeTrue()) + + ginkgo.By("Get v1beta1 ManagedClusterAddOn using v1alpha1 client and verify conversion") + gomega.Eventually(func() bool { + v1alpha1Addon, err := hub.GetManagedClusterAddOnV1Alpha1(clusterName, addonName) + if err != nil { + return false + } + // Verify status.ConfigReferences conversion + if len(v1alpha1Addon.Status.ConfigReferences) != 1 { + return false + } + if !reflect.DeepEqual(v1alpha1Addon.Status.ConfigReferences[0].ConfigReferent.Name, "test-config") { + return false + } + return true + }).Should(gomega.BeTrue()) + + ginkgo.By("Update v1beta1 ManagedClusterAddOn status using v1alpha1 client") + gomega.Eventually(func() bool { + v1alpha1Addon, err := hub.GetManagedClusterAddOnV1Alpha1(clusterName, addonName) + if err != nil { + return false + } + v1alpha1Addon.Status.ConfigReferences = append(v1alpha1Addon.Status.ConfigReferences, + addonv1alpha1.ConfigReference{ + ConfigGroupResource: addonv1alpha1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + ConfigReferent: addonv1alpha1.ConfigReferent{ + Namespace: "alpha-ns", + Name: "alpha-config", + }, + }) + _, err = hub.AddonClient.AddonV1alpha1().ManagedClusterAddOns(clusterName).UpdateStatus( + context.Background(), v1alpha1Addon, metav1.UpdateOptions{}) + if err != nil { + return false + } + return true + }).Should(gomega.BeTrue()) + + ginkgo.By("Verify status update via v1beta1 client") + gomega.Eventually(func() bool { + addon, err = hub.GetManagedClusterAddOnV1Beta1(clusterName, addonName) + if err != nil { + return false + } + return len(addon.Status.ConfigReferences) == 2 + }).Should(gomega.BeTrue()) + + ginkgo.By("Delete v1beta1 ManagedClusterAddOn using v1alpha1 client") + gomega.Eventually(func() bool { + err = hub.AddonClient.AddonV1alpha1().ManagedClusterAddOns(clusterName).Delete( + context.Background(), addonName, metav1.DeleteOptions{}) + if err != nil { + return false + } + return true + }).Should(gomega.BeTrue()) + }) +}) + +var _ = ginkgo.Describe("Create v1alpha1 ClusterManagementAddOn", ginkgo.Label("addon-conversion"), func() { + ginkgo.It("Create a v1alpha1 ClusterManagementAddOn and get/update/delete with v1alpha1 client", func() { + suffix := rand.String(6) + addonName := fmt.Sprintf("cma-%s", suffix) + + ginkgo.By("Create a v1alpha1 ClusterManagementAddOn") + addon := &addonv1alpha1.ClusterManagementAddOn{ + ObjectMeta: metav1.ObjectMeta{ + Name: addonName, + }, + Spec: addonv1alpha1.ClusterManagementAddOnSpec{ + AddOnMeta: addonv1alpha1.AddOnMeta{ + DisplayName: "Test Addon", + Description: "Test addon for conversion", + }, + InstallStrategy: addonv1alpha1.InstallStrategy{ + Type: addonv1alpha1.AddonInstallStrategyManual, + }, + SupportedConfigs: []addonv1alpha1.ConfigMeta{ + { + ConfigGroupResource: addonv1alpha1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + DefaultConfig: &addonv1alpha1.ConfigReferent{Name: "test-config"}, + }, + }, + }, + } + + _, err := hub.CreateClusterManagementAddOnV1Alpha1(addonName, addon) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + + ginkgo.By("Get v1alpha1 ClusterManagementAddOn using v1alpha1 client") + gomega.Eventually(func() bool { + addon, err = hub.GetClusterManagementAddOnV1Alpha1(addonName) + if err != nil { + return false + } + return true + }).Should(gomega.BeTrue()) + + ginkgo.By("Update v1alpha1 ClusterManagementAddOn status using v1alpha1 client") + gomega.Eventually(func() bool { + addon, err = hub.GetClusterManagementAddOnV1Alpha1(addonName) + if err != nil { + return false + } + addon.Status.DefaultConfigReferences = []addonv1alpha1.DefaultConfigReference{ + { + ConfigGroupResource: addonv1alpha1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + DesiredConfig: &addonv1alpha1.ConfigSpecHash{ + ConfigReferent: addonv1alpha1.ConfigReferent{ + Name: "status-config", + }, + }, + }, + } + _, err = hub.AddonClient.AddonV1alpha1().ClusterManagementAddOns().UpdateStatus( + context.Background(), addon, metav1.UpdateOptions{}) + if err != nil { + return false + } + return true + }).Should(gomega.BeTrue()) + + ginkgo.By("Delete v1alpha1 ClusterManagementAddOn using v1alpha1 client") + gomega.Eventually(func() bool { + err = hub.DeleteClusterManagementAddOnV1Alpha1(addonName) + if err != nil { + return false + } + return true + }).Should(gomega.BeTrue()) + }) + + ginkgo.It("Create a v1alpha1 ClusterManagementAddOn and get/update/delete with v1beta1 client", func() { + suffix := rand.String(6) + addonName := fmt.Sprintf("cma-%s", suffix) + + ginkgo.By("Create a v1alpha1 ClusterManagementAddOn") + addon := &addonv1alpha1.ClusterManagementAddOn{ + ObjectMeta: metav1.ObjectMeta{ + Name: addonName, + }, + Spec: addonv1alpha1.ClusterManagementAddOnSpec{ + AddOnMeta: addonv1alpha1.AddOnMeta{ + DisplayName: "Test Addon", + Description: "Test addon for conversion", + }, + InstallStrategy: addonv1alpha1.InstallStrategy{ + Type: addonv1alpha1.AddonInstallStrategyManual, + }, + SupportedConfigs: []addonv1alpha1.ConfigMeta{ + { + ConfigGroupResource: addonv1alpha1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + DefaultConfig: &addonv1alpha1.ConfigReferent{Name: "test-config"}, + }, + }, + }, + } + + _, err := hub.CreateClusterManagementAddOnV1Alpha1(addonName, addon) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + + ginkgo.By("Update v1alpha1 ClusterManagementAddOn status using v1alpha1 client") + gomega.Eventually(func() bool { + addon, err = hub.GetClusterManagementAddOnV1Alpha1(addonName) + if err != nil { + return false + } + addon.Status.DefaultConfigReferences = []addonv1alpha1.DefaultConfigReference{ + { + ConfigGroupResource: addonv1alpha1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + DesiredConfig: &addonv1alpha1.ConfigSpecHash{ + ConfigReferent: addonv1alpha1.ConfigReferent{ + Name: "status-config", + }, + }, + }, + } + _, err = hub.AddonClient.AddonV1alpha1().ClusterManagementAddOns().UpdateStatus( + context.Background(), addon, metav1.UpdateOptions{}) + if err != nil { + return false + } + return true + }).Should(gomega.BeTrue()) + + ginkgo.By("Get v1alpha1 ClusterManagementAddOn using v1beta1 client and verify conversion") + gomega.Eventually(func() bool { + v1beta1Addon, err := hub.GetClusterManagementAddOnV1Beta1(addonName) + if err != nil { + return false + } + // Verify spec.supportedConfigs → spec.defaultConfigs conversion + if len(v1beta1Addon.Spec.DefaultConfigs) != 1 { + return false + } + if v1beta1Addon.Spec.DefaultConfigs[0].Name != "test-config" { + return false + } + // Verify status.DefaultConfigReferences conversion + if len(v1beta1Addon.Status.DefaultConfigReferences) != 1 { + return false + } + if v1beta1Addon.Status.DefaultConfigReferences[0].DesiredConfig.Name != "status-config" { + return false + } + return true + }).Should(gomega.BeTrue()) + + ginkgo.By("Update v1alpha1 ClusterManagementAddOn using v1beta1 client") + gomega.Eventually(func() error { + v1beta1Addon, err := hub.GetClusterManagementAddOnV1Beta1(addonName) + if err != nil { + return err + } + // Only append if not already present + if len(v1beta1Addon.Spec.DefaultConfigs) < 2 { + v1beta1Addon.Spec.DefaultConfigs = append(v1beta1Addon.Spec.DefaultConfigs, + addonv1beta1.AddOnConfig{ + ConfigGroupResource: addonv1beta1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addontemplates", // Different resource to avoid duplicate key + }, + ConfigReferent: addonv1beta1.ConfigReferent{Name: "beta-config"}, + }) + } + _, err = hub.UpdateClusterManagementAddOnV1Beta1(v1beta1Addon) + return err + }).Should(gomega.Succeed()) + + ginkgo.By("Verify spec update via v1alpha1 client") + gomega.Eventually(func() bool { + addon, err = hub.GetClusterManagementAddOnV1Alpha1(addonName) + if err != nil { + return false + } + return len(addon.Spec.SupportedConfigs) == 2 + }).Should(gomega.BeTrue()) + + ginkgo.By("Delete v1alpha1 ClusterManagementAddOn using v1beta1 client") + gomega.Eventually(func() bool { + err = hub.DeleteClusterManagementAddOnV1Beta1(addonName) + if err != nil { + return false + } + return true + }).Should(gomega.BeTrue()) + }) +}) + +var _ = ginkgo.Describe("Create v1beta1 ClusterManagementAddOn", ginkgo.Label("addon-conversion"), func() { + ginkgo.It("Create a v1beta1 ClusterManagementAddOn and get/update/delete with v1beta1 client", func() { + suffix := rand.String(6) + addonName := fmt.Sprintf("cma-%s", suffix) + + ginkgo.By("Create a v1beta1 ClusterManagementAddOn") + addon := &addonv1beta1.ClusterManagementAddOn{ + ObjectMeta: metav1.ObjectMeta{ + Name: addonName, + }, + Spec: addonv1beta1.ClusterManagementAddOnSpec{ + AddOnMeta: addonv1beta1.AddOnMeta{ + DisplayName: "Test Beta Addon", + Description: "Test addon for v1beta1", + }, + InstallStrategy: addonv1beta1.InstallStrategy{ + Type: addonv1beta1.AddonInstallStrategyManual, + }, + DefaultConfigs: []addonv1beta1.AddOnConfig{ + { + ConfigGroupResource: addonv1beta1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + ConfigReferent: addonv1beta1.ConfigReferent{Name: "beta-config"}, + }, + }, + }, + } + + _, err := hub.CreateClusterManagementAddOnV1Beta1(addonName, addon) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + + ginkgo.By("Get v1beta1 ClusterManagementAddOn using v1beta1 client") + gomega.Eventually(func() bool { + addon, err = hub.GetClusterManagementAddOnV1Beta1(addonName) + if err != nil { + return false + } + return true + }).Should(gomega.BeTrue()) + + ginkgo.By("Update v1beta1 ClusterManagementAddOn status using v1beta1 client") + gomega.Eventually(func() bool { + addon, err = hub.GetClusterManagementAddOnV1Beta1(addonName) + if err != nil { + return false + } + addon.Status.InstallProgressions = []addonv1beta1.InstallProgression{ + { + PlacementRef: addonv1beta1.PlacementRef{ + Name: "test-placement", + Namespace: "default", + }, + ConfigReferences: []addonv1beta1.InstallConfigReference{ + { + ConfigGroupResource: addonv1beta1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + DesiredConfig: &addonv1beta1.ConfigSpecHash{ + ConfigReferent: addonv1beta1.ConfigReferent{ + Name: "progression-config", + }, + }, + }, + }, + }, + } + _, err = hub.AddonClient.AddonV1beta1().ClusterManagementAddOns().UpdateStatus( + context.Background(), addon, metav1.UpdateOptions{}) + if err != nil { + return false + } + return true + }).Should(gomega.BeTrue()) + + ginkgo.By("Delete v1beta1 ClusterManagementAddOn using v1beta1 client") + gomega.Eventually(func() bool { + err = hub.DeleteClusterManagementAddOnV1Beta1(addonName) + if err != nil { + return false + } + return true + }).Should(gomega.BeTrue()) + }) + + ginkgo.It("Create a v1beta1 ClusterManagementAddOn and get/update/delete with v1alpha1 client", func() { + suffix := rand.String(6) + addonName := fmt.Sprintf("cma-%s", suffix) + + ginkgo.By("Create a v1beta1 ClusterManagementAddOn") + addon := &addonv1beta1.ClusterManagementAddOn{ + ObjectMeta: metav1.ObjectMeta{ + Name: addonName, + }, + Spec: addonv1beta1.ClusterManagementAddOnSpec{ + AddOnMeta: addonv1beta1.AddOnMeta{ + DisplayName: "Test Beta Addon", + Description: "Test addon for v1beta1", + }, + InstallStrategy: addonv1beta1.InstallStrategy{ + Type: addonv1beta1.AddonInstallStrategyManual, + }, + DefaultConfigs: []addonv1beta1.AddOnConfig{ + { + ConfigGroupResource: addonv1beta1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + ConfigReferent: addonv1beta1.ConfigReferent{Name: "beta-config"}, + }, + }, + }, + } + + _, err := hub.CreateClusterManagementAddOnV1Beta1(addonName, addon) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + + ginkgo.By("Update v1beta1 ClusterManagementAddOn status using v1beta1 client") + gomega.Eventually(func() bool { + addon, err = hub.GetClusterManagementAddOnV1Beta1(addonName) + if err != nil { + return false + } + addon.Status.InstallProgressions = []addonv1beta1.InstallProgression{ + { + PlacementRef: addonv1beta1.PlacementRef{ + Name: "test-placement", + Namespace: "default", + }, + ConfigReferences: []addonv1beta1.InstallConfigReference{ + { + ConfigGroupResource: addonv1beta1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addondeploymentconfigs", + }, + DesiredConfig: &addonv1beta1.ConfigSpecHash{ + ConfigReferent: addonv1beta1.ConfigReferent{ + Name: "progression-config", + }, + }, + }, + }, + }, + } + _, err = hub.AddonClient.AddonV1beta1().ClusterManagementAddOns().UpdateStatus( + context.Background(), addon, metav1.UpdateOptions{}) + if err != nil { + return false + } + return true + }).Should(gomega.BeTrue()) + + ginkgo.By("Get v1beta1 ClusterManagementAddOn using v1alpha1 client and verify conversion") + gomega.Eventually(func() bool { + v1alpha1Addon, err := hub.GetClusterManagementAddOnV1Alpha1(addonName) + if err != nil { + return false + } + // Verify spec.defaultConfigs → spec.supportedConfigs conversion + if len(v1alpha1Addon.Spec.SupportedConfigs) != 1 { + return false + } + if v1alpha1Addon.Spec.SupportedConfigs[0].DefaultConfig.Name != "beta-config" { + return false + } + // Verify status.InstallProgressions conversion + if len(v1alpha1Addon.Status.InstallProgressions) != 1 { + return false + } + if len(v1alpha1Addon.Status.InstallProgressions[0].ConfigReferences) != 1 { + return false + } + if v1alpha1Addon.Status.InstallProgressions[0].ConfigReferences[0].DesiredConfig.Name != "progression-config" { + return false + } + return true + }).Should(gomega.BeTrue()) + + ginkgo.By("Update v1beta1 ClusterManagementAddOn using v1alpha1 client") + gomega.Eventually(func() error { + v1alpha1Addon, err := hub.GetClusterManagementAddOnV1Alpha1(addonName) + if err != nil { + return err + } + // Only append if not already present + if len(v1alpha1Addon.Spec.SupportedConfigs) < 2 { + v1alpha1Addon.Spec.SupportedConfigs = append(v1alpha1Addon.Spec.SupportedConfigs, + addonv1alpha1.ConfigMeta{ + ConfigGroupResource: addonv1alpha1.ConfigGroupResource{ + Group: "addon.open-cluster-management.io", + Resource: "addontemplates", // Different resource to avoid duplicate key + }, + DefaultConfig: &addonv1alpha1.ConfigReferent{Name: "alpha-config"}, + }) + } + _, err = hub.UpdateClusterManagementAddOnV1Alpha1(v1alpha1Addon) + return err + }).Should(gomega.Succeed()) + + ginkgo.By("Verify spec update via v1beta1 client") + gomega.Eventually(func() bool { + addon, err = hub.GetClusterManagementAddOnV1Beta1(addonName) + if err != nil { + return false + } + return len(addon.Spec.DefaultConfigs) == 2 + }).Should(gomega.BeTrue()) + + ginkgo.By("Delete v1beta1 ClusterManagementAddOn using v1alpha1 client") + gomega.Eventually(func() bool { + err = hub.DeleteClusterManagementAddOnV1Alpha1(addonName) + if err != nil { + return false + } + return true + }).Should(gomega.BeTrue()) + }) +}) + +var _ = ginkgo.Describe("Webhook infrastructure", ginkgo.Label("addon-conversion"), func() { + ginkgo.It("should have CRD conversion configured", func() { + ginkgo.By("Verifying ManagedClusterAddOn CRD has webhook conversion") + mcaCRD, err := hub.APIExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Get( + context.Background(), "managedclusteraddons.addon.open-cluster-management.io", metav1.GetOptions{}) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + gomega.Expect(string(mcaCRD.Spec.Conversion.Strategy)).To(gomega.Equal("Webhook")) + + ginkgo.By("Verifying ClusterManagementAddOn CRD has webhook conversion") + cmaCRD, err := hub.APIExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Get( + context.Background(), "clustermanagementaddons.addon.open-cluster-management.io", metav1.GetOptions{}) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + gomega.Expect(string(cmaCRD.Spec.Conversion.Strategy)).To(gomega.Equal("Webhook")) + }) +}) diff --git a/test/framework/clustermanagementaddon.go b/test/framework/clustermanagementaddon.go new file mode 100644 index 000000000..d0e3f7c25 --- /dev/null +++ b/test/framework/clustermanagementaddon.go @@ -0,0 +1,74 @@ +package framework + +import ( + "context" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + addonv1alpha1 "open-cluster-management.io/api/addon/v1alpha1" + addonv1beta1 "open-cluster-management.io/api/addon/v1beta1" +) + +// CreateClusterManagementAddOnV1Alpha1 creates a ClusterManagementAddOn using v1alpha1 API +func (hub *Hub) CreateClusterManagementAddOnV1Alpha1(name string, addon *addonv1alpha1.ClusterManagementAddOn) (*addonv1alpha1.ClusterManagementAddOn, error) { + if addon == nil { + addon = &addonv1alpha1.ClusterManagementAddOn{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + Spec: addonv1alpha1.ClusterManagementAddOnSpec{}, + } + } + return hub.AddonClient.AddonV1alpha1().ClusterManagementAddOns().Create( + context.TODO(), addon, metav1.CreateOptions{}) +} + +// GetClusterManagementAddOnV1Alpha1 gets a ClusterManagementAddOn using v1alpha1 API +func (hub *Hub) GetClusterManagementAddOnV1Alpha1(name string) (*addonv1alpha1.ClusterManagementAddOn, error) { + return hub.AddonClient.AddonV1alpha1().ClusterManagementAddOns().Get( + context.TODO(), name, metav1.GetOptions{}) +} + +// UpdateClusterManagementAddOnV1Alpha1 updates a ClusterManagementAddOn using v1alpha1 API +func (hub *Hub) UpdateClusterManagementAddOnV1Alpha1(addon *addonv1alpha1.ClusterManagementAddOn) (*addonv1alpha1.ClusterManagementAddOn, error) { + return hub.AddonClient.AddonV1alpha1().ClusterManagementAddOns().Update( + context.TODO(), addon, metav1.UpdateOptions{}) +} + +// DeleteClusterManagementAddOnV1Alpha1 deletes a ClusterManagementAddOn using v1alpha1 API +func (hub *Hub) DeleteClusterManagementAddOnV1Alpha1(name string) error { + return hub.AddonClient.AddonV1alpha1().ClusterManagementAddOns().Delete( + context.TODO(), name, metav1.DeleteOptions{}) +} + +// CreateClusterManagementAddOnV1Beta1 creates a ClusterManagementAddOn using v1beta1 API +func (hub *Hub) CreateClusterManagementAddOnV1Beta1(name string, addon *addonv1beta1.ClusterManagementAddOn) (*addonv1beta1.ClusterManagementAddOn, error) { + if addon == nil { + addon = &addonv1beta1.ClusterManagementAddOn{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + Spec: addonv1beta1.ClusterManagementAddOnSpec{}, + } + } + return hub.AddonClient.AddonV1beta1().ClusterManagementAddOns().Create( + context.TODO(), addon, metav1.CreateOptions{}) +} + +// GetClusterManagementAddOnV1Beta1 gets a ClusterManagementAddOn using v1beta1 API +func (hub *Hub) GetClusterManagementAddOnV1Beta1(name string) (*addonv1beta1.ClusterManagementAddOn, error) { + return hub.AddonClient.AddonV1beta1().ClusterManagementAddOns().Get( + context.TODO(), name, metav1.GetOptions{}) +} + +// UpdateClusterManagementAddOnV1Beta1 updates a ClusterManagementAddOn using v1beta1 API +func (hub *Hub) UpdateClusterManagementAddOnV1Beta1(addon *addonv1beta1.ClusterManagementAddOn) (*addonv1beta1.ClusterManagementAddOn, error) { + return hub.AddonClient.AddonV1beta1().ClusterManagementAddOns().Update( + context.TODO(), addon, metav1.UpdateOptions{}) +} + +// DeleteClusterManagementAddOnV1Beta1 deletes a ClusterManagementAddOn using v1beta1 API +func (hub *Hub) DeleteClusterManagementAddOnV1Beta1(name string) error { + return hub.AddonClient.AddonV1beta1().ClusterManagementAddOns().Delete( + context.TODO(), name, metav1.DeleteOptions{}) +} diff --git a/test/framework/managedclusteraddon.go b/test/framework/managedclusteraddon.go index 991e445ab..2381c6654 100644 --- a/test/framework/managedclusteraddon.go +++ b/test/framework/managedclusteraddon.go @@ -12,6 +12,7 @@ import ( "k8s.io/client-go/util/retry" addonv1alpha1 "open-cluster-management.io/api/addon/v1alpha1" + addonv1beta1 "open-cluster-management.io/api/addon/v1beta1" ) func (hub *Hub) CreateManagedClusterAddOn(managedClusterNamespace, addOnName, installNamespace string) error { @@ -94,3 +95,62 @@ func (hub *Hub) CheckManagedClusterAddOnStatus(managedClusterNamespace, addOnNam return nil } + +// CreateManagedClusterAddOnV1Beta1 creates a ManagedClusterAddOn using v1beta1 API +func (hub *Hub) CreateManagedClusterAddOnV1Beta1(managedClusterNamespace, addOnName, installNamespace string) error { + _, err := hub.AddonClient.AddonV1beta1().ManagedClusterAddOns(managedClusterNamespace).Create( + context.TODO(), + &addonv1beta1.ManagedClusterAddOn{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: managedClusterNamespace, + Name: addOnName, + }, + Spec: addonv1beta1.ManagedClusterAddOnSpec{}, + }, + metav1.CreateOptions{}, + ) + + if err != nil { + return err + } + + return retry.RetryOnConflict(retry.DefaultBackoff, func() error { + addOn, err := hub.AddonClient.AddonV1beta1().ManagedClusterAddOns(managedClusterNamespace).Get( + context.TODO(), addOnName, metav1.GetOptions{}) + if err != nil { + return err + } + + if addOn.Status.Namespace == installNamespace { + return nil + } + addOn.Status.Namespace = installNamespace + _, err = hub.AddonClient.AddonV1beta1().ManagedClusterAddOns(managedClusterNamespace).UpdateStatus( + context.TODO(), addOn, metav1.UpdateOptions{}) + return err + }) +} + +// GetManagedClusterAddOnV1Beta1 gets a ManagedClusterAddOn using v1beta1 API +func (hub *Hub) GetManagedClusterAddOnV1Beta1(managedClusterNamespace, addOnName string) (*addonv1beta1.ManagedClusterAddOn, error) { + return hub.AddonClient.AddonV1beta1().ManagedClusterAddOns(managedClusterNamespace).Get( + context.TODO(), addOnName, metav1.GetOptions{}) +} + +// UpdateManagedClusterAddOnV1Beta1 updates a ManagedClusterAddOn using v1beta1 API +func (hub *Hub) UpdateManagedClusterAddOnV1Beta1(addon *addonv1beta1.ManagedClusterAddOn) (*addonv1beta1.ManagedClusterAddOn, error) { + return hub.AddonClient.AddonV1beta1().ManagedClusterAddOns(addon.Namespace).Update( + context.TODO(), addon, metav1.UpdateOptions{}) +} + +// GetManagedClusterAddOnV1Alpha1 gets a ManagedClusterAddOn using v1alpha1 API +func (hub *Hub) GetManagedClusterAddOnV1Alpha1(managedClusterNamespace, addOnName string) (*addonv1alpha1.ManagedClusterAddOn, error) { + return hub.AddonClient.AddonV1alpha1().ManagedClusterAddOns(managedClusterNamespace).Get( + context.TODO(), addOnName, metav1.GetOptions{}) +} + +// UpdateManagedClusterAddOnV1Alpha1 updates a ManagedClusterAddOn using v1alpha1 API +func (hub *Hub) UpdateManagedClusterAddOnV1Alpha1(addon *addonv1alpha1.ManagedClusterAddOn) (*addonv1alpha1.ManagedClusterAddOn, error) { + return hub.AddonClient.AddonV1alpha1().ManagedClusterAddOns(addon.Namespace).Update( + context.TODO(), addon, metav1.UpdateOptions{}) +} diff --git a/test/integration/operator/clustermanager_hosted_test.go b/test/integration/operator/clustermanager_hosted_test.go index 6a6b92f3c..ec8a8dc81 100644 --- a/test/integration/operator/clustermanager_hosted_test.go +++ b/test/integration/operator/clustermanager_hosted_test.go @@ -70,8 +70,8 @@ var _ = ginkgo.Describe("ClusterManager Hosted Mode", func() { var hubRegistrationWebhookDeployment = fmt.Sprintf("%s-registration-webhook", clusterManagerName) var hubWorkWebhookDeployment = fmt.Sprintf("%s-work-webhook", clusterManagerName) var hubAddOnManagerDeployment = fmt.Sprintf("%s-addon-manager-controller", clusterManagerName) + var hubAddOnWebhookDeployment = fmt.Sprintf("%s-addon-webhook", clusterManagerName) var hubWorkControllerDeployment = fmt.Sprintf("%s-work-controller", clusterManagerName) - var hubAddonManagerDeployment = fmt.Sprintf("%s-addon-manager-controller", clusterManagerName) var hubRegistrationClusterRole = fmt.Sprintf("open-cluster-management:%s-registration:controller", clusterManagerName) var hubRegistrationWebhookClusterRole = fmt.Sprintf("open-cluster-management:%s-registration:webhook", clusterManagerName) var hubWorkWebhookClusterRole = fmt.Sprintf("open-cluster-management:%s-registration:webhook", clusterManagerName) @@ -227,7 +227,7 @@ var _ = ginkgo.Describe("ClusterManager Hosted Mode", func() { }, eventuallyTimeout, eventuallyInterval).Should(gomega.BeNil()) gomega.Eventually(func() error { - if _, err := hostedKubeClient.AppsV1().Deployments(hubNamespaceHosted).Get(hostedCtx, hubAddonManagerDeployment, metav1.GetOptions{}); err != nil { + if _, err := hostedKubeClient.AppsV1().Deployments(hubNamespaceHosted).Get(hostedCtx, hubAddOnManagerDeployment, metav1.GetOptions{}); err != nil { return err } return nil @@ -287,7 +287,7 @@ var _ = ginkgo.Describe("ClusterManager Hosted Mode", func() { ginkgo.By("Update the deployment status to fail to prevent other cases from interfering") updateDeploymentsStatusFail(hostedKubeClient, hubNamespaceHosted, hubRegistrationDeployment, hubPlacementDeployment, hubRegistrationWebhookDeployment, - hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddonManagerDeployment) + hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddOnManagerDeployment, hubAddOnWebhookDeployment) // Check validating webhook registrationValidtingWebhook := "managedclustervalidators.admission.cluster.open-cluster-management.io" @@ -305,7 +305,7 @@ var _ = ginkgo.Describe("ClusterManager Hosted Mode", func() { updateDeploymentsStatusSuccess(hostedKubeClient, hubNamespaceHosted, hubRegistrationDeployment, hubPlacementDeployment, hubRegistrationWebhookDeployment, - hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddonManagerDeployment) + hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddOnManagerDeployment, hubAddOnWebhookDeployment) gomega.Eventually(func() error { _, err := hostedKubeClient.AdmissionregistrationV1().ValidatingWebhookConfigurations().Get( @@ -392,7 +392,7 @@ var _ = ginkgo.Describe("ClusterManager Hosted Mode", func() { updateDeploymentsStatusSuccess(hostedKubeClient, hubNamespaceHosted, hubRegistrationDeployment, hubPlacementDeployment, hubRegistrationWebhookDeployment, - hubWorkWebhookDeployment, hubAddOnManagerDeployment) + hubWorkWebhookDeployment, hubAddOnManagerDeployment, hubAddOnWebhookDeployment) // Check if relatedResources are correct gomega.Eventually(func() error { @@ -401,8 +401,8 @@ var _ = ginkgo.Describe("ClusterManager Hosted Mode", func() { if err != nil { return err } - if len(actual.Status.RelatedResources) != 41 { - return fmt.Errorf("should get 41 relatedResources, actual got %v, %v", + if len(actual.Status.RelatedResources) != 43 { + return fmt.Errorf("should get 43 relatedResources, actual got %v, %v", len(actual.Status.RelatedResources), actual.Status.RelatedResources) } return nil @@ -472,7 +472,7 @@ var _ = ginkgo.Describe("ClusterManager Hosted Mode", func() { updateDeploymentsStatusSuccess(hostedKubeClient, hubNamespaceHosted, hubRegistrationDeployment, hubPlacementDeployment, hubRegistrationWebhookDeployment, - hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddonManagerDeployment) + hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddOnManagerDeployment, hubAddOnWebhookDeployment) // Check if relatedResources are correct gomega.Eventually(func() error { actual, err := hostedOperatorClient.OperatorV1().ClusterManagers().Get( @@ -480,8 +480,8 @@ var _ = ginkgo.Describe("ClusterManager Hosted Mode", func() { if err != nil { return err } - if len(actual.Status.RelatedResources) != 45 { - return fmt.Errorf("should get 45 relatedResources, actual got %v, %v", + if len(actual.Status.RelatedResources) != 47 { + return fmt.Errorf("should get 47 relatedResources, actual got %v, %v", len(actual.Status.RelatedResources), actual.Status.RelatedResources) } return nil @@ -694,8 +694,8 @@ var _ = ginkgo.Describe("ClusterManager Hosted Mode", func() { if err != nil { return err } - if len(actual.Status.RelatedResources) != 40 { - return fmt.Errorf("should get 40 relatedResources, actual got %v, %v", + if len(actual.Status.RelatedResources) != 42 { + return fmt.Errorf("should get 42 relatedResources, actual got %v, %v", len(actual.Status.RelatedResources), actual.Status.RelatedResources) } return nil @@ -748,15 +748,15 @@ var _ = ginkgo.Describe("ClusterManager Hosted Mode", func() { updateDeploymentsStatusSuccess(hostedKubeClient, hubNamespaceHosted, hubRegistrationDeployment, hubPlacementDeployment, hubRegistrationWebhookDeployment, - hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddonManagerDeployment) + hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddOnManagerDeployment, hubAddOnWebhookDeployment) // Check if relatedResources are correct gomega.Eventually(func() error { actual, err := hostedOperatorClient.OperatorV1().ClusterManagers().Get(context.Background(), clusterManagerName, metav1.GetOptions{}) if err != nil { return err } - if len(actual.Status.RelatedResources) != 45 { - return fmt.Errorf("should get 45 relatedResources, actual got %v, %v", len(actual.Status.RelatedResources), actual.Status.RelatedResources) + if len(actual.Status.RelatedResources) != 47 { + return fmt.Errorf("should get 47 relatedResources, actual got %v, %v", len(actual.Status.RelatedResources), actual.Status.RelatedResources) } return nil }, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred()) @@ -808,7 +808,7 @@ var _ = ginkgo.Describe("ClusterManager Hosted Mode", func() { updateDeploymentsStatusSuccess(hostedKubeClient, hubNamespaceHosted, hubRegistrationDeployment, hubPlacementDeployment, hubRegistrationWebhookDeployment, - hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddonManagerDeployment) + hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddOnManagerDeployment, hubAddOnWebhookDeployment) // Check if generations are correct gomega.Eventually(func() error { @@ -871,7 +871,7 @@ var _ = ginkgo.Describe("ClusterManager Hosted Mode", func() { updateDeploymentsStatusSuccess(hostedKubeClient, hubNamespaceHosted, hubRegistrationDeployment, hubPlacementDeployment, hubRegistrationWebhookDeployment, - hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddonManagerDeployment) + hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddOnManagerDeployment, hubAddOnWebhookDeployment) }) ginkgo.It("Deployment should be reconciled when manually updated", func() { @@ -943,7 +943,7 @@ var _ = ginkgo.Describe("ClusterManager Hosted Mode", func() { // Update replica of deployment updateDeploymentsStatusSuccess(hostedKubeClient, hubNamespaceHosted, hubRegistrationDeployment, hubPlacementDeployment, hubRegistrationWebhookDeployment, - hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddonManagerDeployment) + hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddOnManagerDeployment, hubAddOnWebhookDeployment) // The cluster manager should be functional at last util.AssertClusterManagerCondition(clusterManagerName, hostedOperatorClient, "HubRegistrationDegraded", "RegistrationFunctional", metav1.ConditionFalse) diff --git a/test/integration/operator/clustermanager_test.go b/test/integration/operator/clustermanager_test.go index d05c12739..3e6cb2f6f 100644 --- a/test/integration/operator/clustermanager_test.go +++ b/test/integration/operator/clustermanager_test.go @@ -64,7 +64,7 @@ var _ = ginkgo.Describe("ClusterManager Default Mode", ginkgo.Ordered, func() { var hubWorkWebhookDeployment = fmt.Sprintf("%s-work-webhook", clusterManagerName) var hubAddOnManagerDeployment = fmt.Sprintf("%s-addon-manager-controller", clusterManagerName) var hubWorkControllerDeployment = fmt.Sprintf("%s-work-controller", clusterManagerName) - var hubAddonManagerDeployment = fmt.Sprintf("%s-addon-manager-controller", clusterManagerName) + var hubAddOnWebhookDeployment = fmt.Sprintf("%s-addon-webhook", clusterManagerName) var hubRegistrationClusterRole = fmt.Sprintf("open-cluster-management:%s-registration:controller", clusterManagerName) var hubRegistrationWebhookClusterRole = fmt.Sprintf("open-cluster-management:%s-registration:webhook", clusterManagerName) var hubWorkWebhookClusterRole = fmt.Sprintf("open-cluster-management:%s-work:webhook", clusterManagerName) @@ -213,7 +213,14 @@ var _ = ginkgo.Describe("ClusterManager Default Mode", ginkgo.Ordered, func() { }, eventuallyTimeout, eventuallyInterval).Should(gomega.BeNil()) gomega.Eventually(func() error { - if _, err := kubeClient.AppsV1().Deployments(hubNamespace).Get(context.Background(), hubAddonManagerDeployment, metav1.GetOptions{}); err != nil { + if _, err := kubeClient.AppsV1().Deployments(hubNamespace).Get(context.Background(), hubAddOnManagerDeployment, metav1.GetOptions{}); err != nil { + return err + } + return nil + }, eventuallyTimeout, eventuallyInterval).Should(gomega.BeNil()) + + gomega.Eventually(func() error { + if _, err := kubeClient.AppsV1().Deployments(hubNamespace).Get(context.Background(), hubAddOnWebhookDeployment, metav1.GetOptions{}); err != nil { return err } return nil @@ -269,9 +276,17 @@ var _ = ginkgo.Describe("ClusterManager Default Mode", ginkgo.Ordered, func() { }, eventuallyTimeout, eventuallyInterval).Should(gomega.BeNil()) ginkgo.By("Update the deployment status to fail to prevent other cases from interfering") + // Ensure addon webhook deployment exists before updating status + gomega.Eventually(func() error { + if _, err := kubeClient.AppsV1().Deployments(hubNamespace).Get(context.Background(), hubAddOnWebhookDeployment, metav1.GetOptions{}); err != nil { + return err + } + return nil + }, eventuallyTimeout, eventuallyInterval).Should(gomega.BeNil()) + updateDeploymentsStatusFail(kubeClient, hubNamespace, hubRegistrationDeployment, hubPlacementDeployment, hubRegistrationWebhookDeployment, - hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddonManagerDeployment) + hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddOnManagerDeployment, hubAddOnWebhookDeployment) // Check validating webhook registrationValidatingWebhook := "managedclustervalidators.admission.cluster.open-cluster-management.io" @@ -287,9 +302,17 @@ var _ = ginkgo.Describe("ClusterManager Default Mode", ginkgo.Ordered, func() { gomega.Expect(err).To(gomega.HaveOccurred()) // Update ready replica of deployment + // Ensure addon webhook deployment exists before updating status + gomega.Eventually(func() error { + if _, err := kubeClient.AppsV1().Deployments(hubNamespace).Get(context.Background(), hubAddOnWebhookDeployment, metav1.GetOptions{}); err != nil { + return err + } + return nil + }, eventuallyTimeout, eventuallyInterval).Should(gomega.BeNil()) + updateDeploymentsStatusSuccess(kubeClient, hubNamespace, hubRegistrationDeployment, hubPlacementDeployment, hubRegistrationWebhookDeployment, - hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddonManagerDeployment) + hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddOnManagerDeployment, hubAddOnWebhookDeployment) gomega.Eventually(func() error { _, err := kubeClient.AdmissionregistrationV1().ValidatingWebhookConfigurations().Get( @@ -384,8 +407,8 @@ var _ = ginkgo.Describe("ClusterManager Default Mode", ginkgo.Ordered, func() { if err != nil { return err } - if len(actual.Status.RelatedResources) != 41 { - return fmt.Errorf("should get 41 relatedResources, actual got %v, %v", + if len(actual.Status.RelatedResources) != 44 { + return fmt.Errorf("should get 44 relatedResources, actual got %v, %v", len(actual.Status.RelatedResources), actual.Status.RelatedResources) } return nil @@ -455,7 +478,7 @@ var _ = ginkgo.Describe("ClusterManager Default Mode", ginkgo.Ordered, func() { updateDeploymentsStatusSuccess(kubeClient, hubNamespace, hubRegistrationDeployment, hubPlacementDeployment, hubRegistrationWebhookDeployment, - hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddonManagerDeployment) + hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddOnManagerDeployment, hubAddOnWebhookDeployment) // Check if relatedResources are correct gomega.Eventually(func() error { actual, err := operatorClient.OperatorV1().ClusterManagers().Get( @@ -463,8 +486,8 @@ var _ = ginkgo.Describe("ClusterManager Default Mode", ginkgo.Ordered, func() { if err != nil { return err } - if len(actual.Status.RelatedResources) != 45 { - return fmt.Errorf("should get 45 relatedResources, actual got %v, %v", + if len(actual.Status.RelatedResources) != 48 { + return fmt.Errorf("should get 48 relatedResources, actual got %v, %v", len(actual.Status.RelatedResources), actual.Status.RelatedResources) } return nil @@ -675,8 +698,8 @@ var _ = ginkgo.Describe("ClusterManager Default Mode", ginkgo.Ordered, func() { if err != nil { return err } - if len(actual.Status.RelatedResources) != 40 { - return fmt.Errorf("should get 40 relatedResources, actual got %v", len(actual.Status.RelatedResources)) + if len(actual.Status.RelatedResources) != 43 { + return fmt.Errorf("should get 43 relatedResources, actual got %v", len(actual.Status.RelatedResources)) } return nil }, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred()) @@ -724,15 +747,15 @@ var _ = ginkgo.Describe("ClusterManager Default Mode", ginkgo.Ordered, func() { updateDeploymentsStatusSuccess(kubeClient, hubNamespace, hubRegistrationDeployment, hubPlacementDeployment, hubRegistrationWebhookDeployment, - hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddonManagerDeployment) + hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddOnManagerDeployment, hubAddOnWebhookDeployment) // Check if relatedResources are correct gomega.Eventually(func() error { actual, err := operatorClient.OperatorV1().ClusterManagers().Get(context.Background(), clusterManagerName, metav1.GetOptions{}) if err != nil { return err } - if len(actual.Status.RelatedResources) != 45 { - return fmt.Errorf("should get 45 relatedResources, actual got %v", len(actual.Status.RelatedResources)) + if len(actual.Status.RelatedResources) != 48 { + return fmt.Errorf("should get 48 relatedResources, actual got %v", len(actual.Status.RelatedResources)) } return nil }, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred()) @@ -989,7 +1012,7 @@ var _ = ginkgo.Describe("ClusterManager Default Mode", ginkgo.Ordered, func() { updateDeploymentsStatusSuccess(kubeClient, hubNamespace, hubRegistrationDeployment, hubPlacementDeployment, hubRegistrationWebhookDeployment, - hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddonManagerDeployment) + hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddOnManagerDeployment, hubAddOnWebhookDeployment) // Check if generations are correct gomega.Eventually(func() error { @@ -1011,8 +1034,8 @@ var _ = ginkgo.Describe("ClusterManager Default Mode", ginkgo.Ordered, func() { if err != nil { return err } - if len(actual.Status.RelatedResources) != 46 { - return fmt.Errorf("should get 46 relatedResources, actual got %v", len(actual.Status.RelatedResources)) + if len(actual.Status.RelatedResources) != 49 { + return fmt.Errorf("should get 49 relatedResources, actual got %v", len(actual.Status.RelatedResources)) } return nil }, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred()) @@ -1063,7 +1086,7 @@ var _ = ginkgo.Describe("ClusterManager Default Mode", ginkgo.Ordered, func() { }, eventuallyTimeout, eventuallyInterval).Should(gomega.BeNil()) updateDeploymentsStatusSuccess(kubeClient, hubNamespace, hubRegistrationDeployment, hubPlacementDeployment, hubRegistrationWebhookDeployment, - hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddonManagerDeployment) + hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddOnManagerDeployment, hubAddOnWebhookDeployment) }) ginkgo.It("Deployment should be reconciled when manually updated", func() { @@ -1313,7 +1336,7 @@ var _ = ginkgo.Describe("ClusterManager Default Mode", ginkgo.Ordered, func() { // Update replica of deployment updateDeploymentsStatusSuccess(kubeClient, hubNamespace, hubRegistrationDeployment, hubPlacementDeployment, hubRegistrationWebhookDeployment, - hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddonManagerDeployment) + hubWorkWebhookDeployment, hubWorkControllerDeployment, hubAddOnManagerDeployment, hubAddOnWebhookDeployment) // The cluster manager should be functional at last util.AssertClusterManagerCondition(clusterManagerName, operatorClient, "HubRegistrationDegraded", "RegistrationFunctional", metav1.ConditionFalse) diff --git a/vendor/modules.txt b/vendor/modules.txt index de5f9a9e2..8c945ac05 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1872,7 +1872,7 @@ k8s.io/utils/path k8s.io/utils/pointer k8s.io/utils/ptr k8s.io/utils/trace -# open-cluster-management.io/addon-framework v1.1.1-0.20251216020304-d6b232cac146 +# open-cluster-management.io/addon-framework v1.1.1-0.20251222073158-b5846d76add9 ## explicit; go 1.25.0 open-cluster-management.io/addon-framework/pkg/addonfactory open-cluster-management.io/addon-framework/pkg/addonmanager @@ -1888,7 +1888,7 @@ open-cluster-management.io/addon-framework/pkg/agent open-cluster-management.io/addon-framework/pkg/assets open-cluster-management.io/addon-framework/pkg/index open-cluster-management.io/addon-framework/pkg/utils -# open-cluster-management.io/api v1.1.1-0.20251216020302-b4274bb2f05a +# open-cluster-management.io/api v1.1.1-0.20251222023835-510285203ee6 ## explicit; go 1.25.0 open-cluster-management.io/api/addon/v1alpha1 open-cluster-management.io/api/addon/v1beta1 diff --git a/vendor/open-cluster-management.io/addon-framework/pkg/addonmanager/controllers/agentdeploy/utils.go b/vendor/open-cluster-management.io/addon-framework/pkg/addonmanager/controllers/agentdeploy/utils.go index 1f8590fe6..3e7c2e341 100644 --- a/vendor/open-cluster-management.io/addon-framework/pkg/addonmanager/controllers/agentdeploy/utils.go +++ b/vendor/open-cluster-management.io/addon-framework/pkg/addonmanager/controllers/agentdeploy/utils.go @@ -8,6 +8,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/klog/v2" addonapiv1alpha1 "open-cluster-management.io/api/addon/v1alpha1" clusterv1 "open-cluster-management.io/api/cluster/v1" @@ -269,7 +270,11 @@ func (b *addonWorksBuilder) BuildDeployWorks(installMode, addonWorkNamespace str // This owner is only added to the manifestWork deployed in managed cluster ns. // the manifestWork in managed cluster ns is cleaned up via the addon ownerRef, so need to add the owner. // the manifestWork in hosting cluster ns is cleaned up by its controller since it and its addon cross ns. - owner := metav1.NewControllerRef(addon, addonapiv1alpha1.GroupVersion.WithKind("ManagedClusterAddOn")) + owner := metav1.NewControllerRef(addon, schema.GroupVersionKind{ + Group: addonapiv1alpha1.GroupName, + Version: addonapiv1alpha1.GroupVersion.Version, + Kind: "ManagedClusterAddOn", + }) var deletionOrphaningRules []workapiv1.OrphaningRule for _, object := range objects { @@ -331,7 +336,11 @@ func (b *addonWorksBuilder) BuildHookWork(installMode, addonWorkNamespace string var hookManifests []workapiv1.Manifest var hookManifestConfigs []workapiv1.ManifestConfigOption - owner := metav1.NewControllerRef(addon, addonapiv1alpha1.GroupVersion.WithKind("ManagedClusterAddOn")) + owner := metav1.NewControllerRef(addon, schema.GroupVersionKind{ + Group: addonapiv1alpha1.GroupName, + Version: addonapiv1alpha1.GroupVersion.Version, + Kind: "ManagedClusterAddOn", + }) for _, object := range objects { deployable, err := b.processor.deployable(b.hostedModeEnabled, installMode, object) diff --git a/vendor/open-cluster-management.io/api/addon/v1alpha1/doc.go b/vendor/open-cluster-management.io/api/addon/v1alpha1/doc.go index 212ef14b7..f73e8c5c1 100644 --- a/vendor/open-cluster-management.io/api/addon/v1alpha1/doc.go +++ b/vendor/open-cluster-management.io/api/addon/v1alpha1/doc.go @@ -1,8 +1,8 @@ // Copyright Contributors to the Open Cluster Management project // Package v1alpha1 contains API Schema definitions for the addon v1alpha1 API group -// +k8s:deepcopy-gen=package,register -// +k8s:openapi-gen=true +// +k8s:deepcopy-gen=package,register // +kubebuilder:validation:Optional +// +kubebuilder:object:generate=true // +groupName=addon.open-cluster-management.io package v1alpha1 diff --git a/vendor/open-cluster-management.io/api/addon/v1alpha1/register.go b/vendor/open-cluster-management.io/api/addon/v1alpha1/register.go deleted file mode 100644 index bd7878d8b..000000000 --- a/vendor/open-cluster-management.io/api/addon/v1alpha1/register.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright Contributors to the Open Cluster Management project -package v1alpha1 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -var ( - GroupName = "addon.open-cluster-management.io" - GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} - schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) - // Install is a function which adds this version to a scheme - Install = schemeBuilder.AddToScheme - - // SchemeGroupVersion generated code relies on this name - // Deprecated - SchemeGroupVersion = GroupVersion - // AddToScheme exists solely to keep the old generators creating valid code - // DEPRECATED - AddToScheme = schemeBuilder.AddToScheme -) - -// Resource generated code relies on this being here, but it logically belongs to the group -// DEPRECATED -func Resource(resource string) schema.GroupResource { - return schema.GroupResource{Group: GroupName, Resource: resource} -} - -// Adds the list of known types to api.Scheme. -func addKnownTypes(scheme *runtime.Scheme) error { - scheme.AddKnownTypes(GroupVersion, - &ClusterManagementAddOn{}, - &ClusterManagementAddOnList{}, - &ManagedClusterAddOn{}, - &ManagedClusterAddOnList{}, - &AddOnDeploymentConfig{}, - &AddOnDeploymentConfigList{}, - &AddOnTemplate{}, - &AddOnTemplateList{}, - ) - metav1.AddToGroupVersion(scheme, GroupVersion) - return nil -} diff --git a/vendor/open-cluster-management.io/api/addon/v1alpha1/zz_generated.register.go b/vendor/open-cluster-management.io/api/addon/v1alpha1/zz_generated.register.go new file mode 100644 index 000000000..1d1bc08ec --- /dev/null +++ b/vendor/open-cluster-management.io/api/addon/v1alpha1/zz_generated.register.go @@ -0,0 +1,61 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright Contributors to the Open Cluster Management project +// Code generated by register-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName specifies the group name used to register the objects. +const GroupName = "addon.open-cluster-management.io" + +// GroupVersion specifies the group and the version used to register the objects. +var GroupVersion = v1.GroupVersion{Group: GroupName, Version: "v1alpha1"} + +// SchemeGroupVersion is group version used to register these objects +// Deprecated: use GroupVersion instead. +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. + SchemeBuilder runtime.SchemeBuilder + localSchemeBuilder = &SchemeBuilder + // Deprecated: use Install instead + AddToScheme = localSchemeBuilder.AddToScheme + Install = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addKnownTypes) +} + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &AddOnDeploymentConfig{}, + &AddOnDeploymentConfigList{}, + &AddOnTemplate{}, + &AddOnTemplateList{}, + &ClusterManagementAddOn{}, + &ClusterManagementAddOnList{}, + &ManagedClusterAddOn{}, + &ManagedClusterAddOnList{}, + ) + // AddToGroupVersion allows the serialization of client types like ListOptions. + v1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/open-cluster-management.io/api/addon/v1beta1/conversion.go b/vendor/open-cluster-management.io/api/addon/v1beta1/conversion.go new file mode 100644 index 000000000..898dae051 --- /dev/null +++ b/vendor/open-cluster-management.io/api/addon/v1beta1/conversion.go @@ -0,0 +1,174 @@ +// Copyright Contributors to the Open Cluster Management project +package v1beta1 + +import ( + "fmt" + certificates "k8s.io/api/certificates/v1" + "k8s.io/apimachinery/pkg/conversion" + "open-cluster-management.io/api/addon/v1alpha1" +) + +const ( + // ReservedNoDefaultConfigName is a reserved sentinel value used internally during API version conversion. + // It indicates that a v1alpha1 ConfigMeta had no defaultConfig when converting to v1beta1. + // This value is intentionally invalid as a Kubernetes resource name (starts with "__") to prevent + // collision with legitimate user-provided config names and ensure data integrity on round-trip conversions. + // WARNING: This value is reserved and MUST NOT be used as a real config name. + ReservedNoDefaultConfigName = "__reserved_no_default__" +) + +// nolint:staticcheck +func Convert_v1beta1_ClusterManagementAddOnSpec_To_v1alpha1_ClusterManagementAddOnSpec(in *ClusterManagementAddOnSpec, out *v1alpha1.ClusterManagementAddOnSpec, s conversion.Scope) error { + if err := autoConvert_v1beta1_ClusterManagementAddOnSpec_To_v1alpha1_ClusterManagementAddOnSpec(in, out, s); err != nil { + return err + } + + config := []v1alpha1.ConfigMeta{} + for _, inConfig := range in.DefaultConfigs { + c := v1alpha1.ConfigMeta{ + ConfigGroupResource: v1alpha1.ConfigGroupResource{ + Group: inConfig.Group, + Resource: inConfig.Resource, + }, + } + + // If there's a config referent and it's not the reserved sentinel, convert it to default config + // The reserved sentinel indicates there was no defaultConfig in the original v1alpha1 + if inConfig.Name != "" && inConfig.Name != ReservedNoDefaultConfigName { + c.DefaultConfig = &v1alpha1.ConfigReferent{ + Namespace: inConfig.Namespace, + Name: inConfig.Name, + } + } + config = append(config, c) + } + out.SupportedConfigs = config + return nil +} + +// nolint:staticcheck +func Convert_v1alpha1_ClusterManagementAddOnSpec_To_v1beta1_ClusterManagementAddOnSpec(in *v1alpha1.ClusterManagementAddOnSpec, out *ClusterManagementAddOnSpec, s conversion.Scope) error { + if err := autoConvert_v1alpha1_ClusterManagementAddOnSpec_To_v1beta1_ClusterManagementAddOnSpec(in, out, s); err != nil { + return err + } + + configs := []AddOnConfig{} + for _, inConfig := range in.SupportedConfigs { + c := AddOnConfig{ + ConfigGroupResource: ConfigGroupResource{ + Resource: inConfig.Resource, + Group: inConfig.Group, + }, + } + + if inConfig.DefaultConfig != nil { + c.ConfigReferent = ConfigReferent{ + Name: inConfig.DefaultConfig.Name, + Namespace: inConfig.DefaultConfig.Namespace, + } + } else { + c.ConfigReferent = ConfigReferent{ + Name: ReservedNoDefaultConfigName, + } + } + configs = append(configs, c) + } + out.DefaultConfigs = configs + return nil +} + +func Convert_v1alpha1_ConfigReference_To_v1beta1_ConfigReference(in *v1alpha1.ConfigReference, out *ConfigReference, s conversion.Scope) error { + if err := autoConvert_v1alpha1_ConfigReference_To_v1beta1_ConfigReference(in, out, s); err != nil { + return err + } + + return nil +} + +func Convert_v1alpha1_ManagedClusterAddOnSpec_To_v1beta1_ManagedClusterAddOnSpec(in *v1alpha1.ManagedClusterAddOnSpec, out *ManagedClusterAddOnSpec, s conversion.Scope) error { + // installNamespace should be treated outside this converter since it will be set on annotation + for _, inConfig := range in.Configs { + outConfig := AddOnConfig{} + if err := Convert_v1alpha1_AddOnConfig_To_v1beta1_AddOnConfig(&inConfig, &outConfig, s); err != nil { + return err + } + out.Configs = append(out.Configs, outConfig) + } + + return nil +} + +func Convert_v1alpha1_ManagedClusterAddOnStatus_To_v1beta1_ManagedClusterAddOnStatus(in *v1alpha1.ManagedClusterAddOnStatus, out *ManagedClusterAddOnStatus, s conversion.Scope) error { + if err := autoConvert_v1alpha1_ManagedClusterAddOnStatus_To_v1beta1_ManagedClusterAddOnStatus(in, out, s); err != nil { + return err + } + + return nil +} + +// nolint:staticcheck +func Convert_v1beta1_RegistrationConfig_To_v1alpha1_RegistrationConfig(in *RegistrationConfig, out *v1alpha1.RegistrationConfig, s conversion.Scope) error { + if in.Type == KubeClient { + out.SignerName = certificates.KubeAPIServerClientSignerName + if in.KubeClient == nil { + return fmt.Errorf("nil KubeClient") + } + out.Subject = v1alpha1.Subject{ + User: in.KubeClient.Subject.User, + Groups: in.KubeClient.Subject.Groups, + } + } else { + if in.CSR == nil { + return fmt.Errorf("nil CSR") + } + out.SignerName = in.CSR.SignerName + if err := Convert_v1beta1_Subject_To_v1alpha1_Subject(&in.CSR.Subject, &out.Subject, s); err != nil { + return err + } + } + + return nil +} + +// nolint:staticcheck +func Convert_v1alpha1_RegistrationConfig_To_v1beta1_RegistrationConfig(in *v1alpha1.RegistrationConfig, out *RegistrationConfig, s conversion.Scope) error { + if in.SignerName == certificates.KubeAPIServerClientSignerName { + out.Type = KubeClient + out.KubeClient = &KubeClientConfig{ + Subject: KubeClientSubject{ + BaseSubject{ + User: in.Subject.User, + Groups: in.Subject.Groups, + }, + }, + } + } else { + out.Type = CSR + out.CSR = &CSRConfig{ + SignerName: in.SignerName, + Subject: Subject{ + BaseSubject: BaseSubject{ + User: in.Subject.User, + Groups: in.Subject.Groups, + }, + OrganizationUnits: in.Subject.OrganizationUnits, + }, + } + } + + return nil +} + +func Convert_v1beta1_Subject_To_v1alpha1_Subject(in *Subject, out *v1alpha1.Subject, s conversion.Scope) error { + out.User = in.User + out.Groups = in.Groups + out.OrganizationUnits = in.OrganizationUnits + return nil +} + +func Convert_v1alpha1_Subject_To_v1beta1_Subject(in *v1alpha1.Subject, out *Subject, s conversion.Scope) error { + out.User = in.User + out.Groups = in.Groups + out.OrganizationUnits = in.OrganizationUnits + return nil +} diff --git a/vendor/open-cluster-management.io/api/addon/v1beta1/doc.go b/vendor/open-cluster-management.io/api/addon/v1beta1/doc.go index 5d5abb5e9..a5af55b98 100644 --- a/vendor/open-cluster-management.io/api/addon/v1beta1/doc.go +++ b/vendor/open-cluster-management.io/api/addon/v1beta1/doc.go @@ -1,8 +1,8 @@ // Copyright Contributors to the Open Cluster Management project // Package v1beta1 contains API Schema definitions for the addon v1beta1 API group -// +k8s:deepcopy-gen=package,register -// +k8s:openapi-gen=true +// +k8s:deepcopy-gen=package,register // +kubebuilder:validation:Optional // +groupName=addon.open-cluster-management.io +// +k8s:conversion-gen=open-cluster-management.io/api/addon/v1alpha1 package v1beta1 diff --git a/vendor/open-cluster-management.io/api/addon/v1beta1/register.go b/vendor/open-cluster-management.io/api/addon/v1beta1/register.go deleted file mode 100644 index 27ff94aa7..000000000 --- a/vendor/open-cluster-management.io/api/addon/v1beta1/register.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright Contributors to the Open Cluster Management project -package v1beta1 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -var ( - GroupName = "addon.open-cluster-management.io" - GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"} - schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) - // Install is a function which adds this version to a scheme - Install = schemeBuilder.AddToScheme - - // SchemeGroupVersion generated code relies on this name - // Deprecated - SchemeGroupVersion = GroupVersion - // AddToScheme exists solely to keep the old generators creating valid code - // DEPRECATED - AddToScheme = schemeBuilder.AddToScheme -) - -// Resource generated code relies on this being here, but it logically belongs to the group -// DEPRECATED -func Resource(resource string) schema.GroupResource { - return schema.GroupResource{Group: GroupName, Resource: resource} -} - -// Adds the list of known types to api.Scheme. -func addKnownTypes(scheme *runtime.Scheme) error { - scheme.AddKnownTypes(GroupVersion, - &ClusterManagementAddOn{}, - &ClusterManagementAddOnList{}, - &ManagedClusterAddOn{}, - &ManagedClusterAddOnList{}, - ) - metav1.AddToGroupVersion(scheme, GroupVersion) - return nil -} diff --git a/vendor/open-cluster-management.io/api/addon/v1beta1/zz_generated.conversion.go b/vendor/open-cluster-management.io/api/addon/v1beta1/zz_generated.conversion.go new file mode 100644 index 000000000..1f636bf91 --- /dev/null +++ b/vendor/open-cluster-management.io/api/addon/v1beta1/zz_generated.conversion.go @@ -0,0 +1,929 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright Contributors to the Open Cluster Management project +// Code generated by conversion-gen. DO NOT EDIT. + +package v1beta1 + +import ( + unsafe "unsafe" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + v1alpha1 "open-cluster-management.io/api/addon/v1alpha1" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(s *runtime.Scheme) error { + if err := s.AddGeneratedConversionFunc((*AddOnConfig)(nil), (*v1alpha1.AddOnConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_AddOnConfig_To_v1alpha1_AddOnConfig(a.(*AddOnConfig), b.(*v1alpha1.AddOnConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.AddOnConfig)(nil), (*AddOnConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_AddOnConfig_To_v1beta1_AddOnConfig(a.(*v1alpha1.AddOnConfig), b.(*AddOnConfig), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*AddOnMeta)(nil), (*v1alpha1.AddOnMeta)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_AddOnMeta_To_v1alpha1_AddOnMeta(a.(*AddOnMeta), b.(*v1alpha1.AddOnMeta), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.AddOnMeta)(nil), (*AddOnMeta)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_AddOnMeta_To_v1beta1_AddOnMeta(a.(*v1alpha1.AddOnMeta), b.(*AddOnMeta), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ClusterManagementAddOn)(nil), (*v1alpha1.ClusterManagementAddOn)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ClusterManagementAddOn_To_v1alpha1_ClusterManagementAddOn(a.(*ClusterManagementAddOn), b.(*v1alpha1.ClusterManagementAddOn), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.ClusterManagementAddOn)(nil), (*ClusterManagementAddOn)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ClusterManagementAddOn_To_v1beta1_ClusterManagementAddOn(a.(*v1alpha1.ClusterManagementAddOn), b.(*ClusterManagementAddOn), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ClusterManagementAddOnList)(nil), (*v1alpha1.ClusterManagementAddOnList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ClusterManagementAddOnList_To_v1alpha1_ClusterManagementAddOnList(a.(*ClusterManagementAddOnList), b.(*v1alpha1.ClusterManagementAddOnList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.ClusterManagementAddOnList)(nil), (*ClusterManagementAddOnList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ClusterManagementAddOnList_To_v1beta1_ClusterManagementAddOnList(a.(*v1alpha1.ClusterManagementAddOnList), b.(*ClusterManagementAddOnList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ClusterManagementAddOnStatus)(nil), (*v1alpha1.ClusterManagementAddOnStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ClusterManagementAddOnStatus_To_v1alpha1_ClusterManagementAddOnStatus(a.(*ClusterManagementAddOnStatus), b.(*v1alpha1.ClusterManagementAddOnStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.ClusterManagementAddOnStatus)(nil), (*ClusterManagementAddOnStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ClusterManagementAddOnStatus_To_v1beta1_ClusterManagementAddOnStatus(a.(*v1alpha1.ClusterManagementAddOnStatus), b.(*ClusterManagementAddOnStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ConfigGroupResource)(nil), (*v1alpha1.ConfigGroupResource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ConfigGroupResource_To_v1alpha1_ConfigGroupResource(a.(*ConfigGroupResource), b.(*v1alpha1.ConfigGroupResource), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.ConfigGroupResource)(nil), (*ConfigGroupResource)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ConfigGroupResource_To_v1beta1_ConfigGroupResource(a.(*v1alpha1.ConfigGroupResource), b.(*ConfigGroupResource), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ConfigReference)(nil), (*v1alpha1.ConfigReference)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ConfigReference_To_v1alpha1_ConfigReference(a.(*ConfigReference), b.(*v1alpha1.ConfigReference), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ConfigReferent)(nil), (*v1alpha1.ConfigReferent)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ConfigReferent_To_v1alpha1_ConfigReferent(a.(*ConfigReferent), b.(*v1alpha1.ConfigReferent), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.ConfigReferent)(nil), (*ConfigReferent)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ConfigReferent_To_v1beta1_ConfigReferent(a.(*v1alpha1.ConfigReferent), b.(*ConfigReferent), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ConfigSpecHash)(nil), (*v1alpha1.ConfigSpecHash)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ConfigSpecHash_To_v1alpha1_ConfigSpecHash(a.(*ConfigSpecHash), b.(*v1alpha1.ConfigSpecHash), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.ConfigSpecHash)(nil), (*ConfigSpecHash)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ConfigSpecHash_To_v1beta1_ConfigSpecHash(a.(*v1alpha1.ConfigSpecHash), b.(*ConfigSpecHash), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*DefaultConfigReference)(nil), (*v1alpha1.DefaultConfigReference)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_DefaultConfigReference_To_v1alpha1_DefaultConfigReference(a.(*DefaultConfigReference), b.(*v1alpha1.DefaultConfigReference), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.DefaultConfigReference)(nil), (*DefaultConfigReference)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_DefaultConfigReference_To_v1beta1_DefaultConfigReference(a.(*v1alpha1.DefaultConfigReference), b.(*DefaultConfigReference), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*HealthCheck)(nil), (*v1alpha1.HealthCheck)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_HealthCheck_To_v1alpha1_HealthCheck(a.(*HealthCheck), b.(*v1alpha1.HealthCheck), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.HealthCheck)(nil), (*HealthCheck)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_HealthCheck_To_v1beta1_HealthCheck(a.(*v1alpha1.HealthCheck), b.(*HealthCheck), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*InstallConfigReference)(nil), (*v1alpha1.InstallConfigReference)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_InstallConfigReference_To_v1alpha1_InstallConfigReference(a.(*InstallConfigReference), b.(*v1alpha1.InstallConfigReference), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.InstallConfigReference)(nil), (*InstallConfigReference)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_InstallConfigReference_To_v1beta1_InstallConfigReference(a.(*v1alpha1.InstallConfigReference), b.(*InstallConfigReference), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*InstallProgression)(nil), (*v1alpha1.InstallProgression)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_InstallProgression_To_v1alpha1_InstallProgression(a.(*InstallProgression), b.(*v1alpha1.InstallProgression), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.InstallProgression)(nil), (*InstallProgression)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_InstallProgression_To_v1beta1_InstallProgression(a.(*v1alpha1.InstallProgression), b.(*InstallProgression), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*InstallStrategy)(nil), (*v1alpha1.InstallStrategy)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_InstallStrategy_To_v1alpha1_InstallStrategy(a.(*InstallStrategy), b.(*v1alpha1.InstallStrategy), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.InstallStrategy)(nil), (*InstallStrategy)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_InstallStrategy_To_v1beta1_InstallStrategy(a.(*v1alpha1.InstallStrategy), b.(*InstallStrategy), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ManagedClusterAddOn)(nil), (*v1alpha1.ManagedClusterAddOn)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ManagedClusterAddOn_To_v1alpha1_ManagedClusterAddOn(a.(*ManagedClusterAddOn), b.(*v1alpha1.ManagedClusterAddOn), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.ManagedClusterAddOn)(nil), (*ManagedClusterAddOn)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ManagedClusterAddOn_To_v1beta1_ManagedClusterAddOn(a.(*v1alpha1.ManagedClusterAddOn), b.(*ManagedClusterAddOn), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ManagedClusterAddOnList)(nil), (*v1alpha1.ManagedClusterAddOnList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ManagedClusterAddOnList_To_v1alpha1_ManagedClusterAddOnList(a.(*ManagedClusterAddOnList), b.(*v1alpha1.ManagedClusterAddOnList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.ManagedClusterAddOnList)(nil), (*ManagedClusterAddOnList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ManagedClusterAddOnList_To_v1beta1_ManagedClusterAddOnList(a.(*v1alpha1.ManagedClusterAddOnList), b.(*ManagedClusterAddOnList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ManagedClusterAddOnSpec)(nil), (*v1alpha1.ManagedClusterAddOnSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ManagedClusterAddOnSpec_To_v1alpha1_ManagedClusterAddOnSpec(a.(*ManagedClusterAddOnSpec), b.(*v1alpha1.ManagedClusterAddOnSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ManagedClusterAddOnStatus)(nil), (*v1alpha1.ManagedClusterAddOnStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ManagedClusterAddOnStatus_To_v1alpha1_ManagedClusterAddOnStatus(a.(*ManagedClusterAddOnStatus), b.(*v1alpha1.ManagedClusterAddOnStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ObjectReference)(nil), (*v1alpha1.ObjectReference)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ObjectReference_To_v1alpha1_ObjectReference(a.(*ObjectReference), b.(*v1alpha1.ObjectReference), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.ObjectReference)(nil), (*ObjectReference)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ObjectReference_To_v1beta1_ObjectReference(a.(*v1alpha1.ObjectReference), b.(*ObjectReference), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*PlacementRef)(nil), (*v1alpha1.PlacementRef)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_PlacementRef_To_v1alpha1_PlacementRef(a.(*PlacementRef), b.(*v1alpha1.PlacementRef), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.PlacementRef)(nil), (*PlacementRef)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_PlacementRef_To_v1beta1_PlacementRef(a.(*v1alpha1.PlacementRef), b.(*PlacementRef), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*PlacementStrategy)(nil), (*v1alpha1.PlacementStrategy)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_PlacementStrategy_To_v1alpha1_PlacementStrategy(a.(*PlacementStrategy), b.(*v1alpha1.PlacementStrategy), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1alpha1.PlacementStrategy)(nil), (*PlacementStrategy)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_PlacementStrategy_To_v1beta1_PlacementStrategy(a.(*v1alpha1.PlacementStrategy), b.(*PlacementStrategy), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1alpha1.ClusterManagementAddOnSpec)(nil), (*ClusterManagementAddOnSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ClusterManagementAddOnSpec_To_v1beta1_ClusterManagementAddOnSpec(a.(*v1alpha1.ClusterManagementAddOnSpec), b.(*ClusterManagementAddOnSpec), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1alpha1.ConfigReference)(nil), (*ConfigReference)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ConfigReference_To_v1beta1_ConfigReference(a.(*v1alpha1.ConfigReference), b.(*ConfigReference), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1alpha1.ManagedClusterAddOnSpec)(nil), (*ManagedClusterAddOnSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ManagedClusterAddOnSpec_To_v1beta1_ManagedClusterAddOnSpec(a.(*v1alpha1.ManagedClusterAddOnSpec), b.(*ManagedClusterAddOnSpec), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1alpha1.ManagedClusterAddOnStatus)(nil), (*ManagedClusterAddOnStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ManagedClusterAddOnStatus_To_v1beta1_ManagedClusterAddOnStatus(a.(*v1alpha1.ManagedClusterAddOnStatus), b.(*ManagedClusterAddOnStatus), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1alpha1.RegistrationConfig)(nil), (*RegistrationConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_RegistrationConfig_To_v1beta1_RegistrationConfig(a.(*v1alpha1.RegistrationConfig), b.(*RegistrationConfig), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1alpha1.Subject)(nil), (*Subject)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_Subject_To_v1beta1_Subject(a.(*v1alpha1.Subject), b.(*Subject), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*ClusterManagementAddOnSpec)(nil), (*v1alpha1.ClusterManagementAddOnSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ClusterManagementAddOnSpec_To_v1alpha1_ClusterManagementAddOnSpec(a.(*ClusterManagementAddOnSpec), b.(*v1alpha1.ClusterManagementAddOnSpec), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*RegistrationConfig)(nil), (*v1alpha1.RegistrationConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_RegistrationConfig_To_v1alpha1_RegistrationConfig(a.(*RegistrationConfig), b.(*v1alpha1.RegistrationConfig), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*Subject)(nil), (*v1alpha1.Subject)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_Subject_To_v1alpha1_Subject(a.(*Subject), b.(*v1alpha1.Subject), scope) + }); err != nil { + return err + } + return nil +} + +func autoConvert_v1beta1_AddOnConfig_To_v1alpha1_AddOnConfig(in *AddOnConfig, out *v1alpha1.AddOnConfig, s conversion.Scope) error { + if err := Convert_v1beta1_ConfigGroupResource_To_v1alpha1_ConfigGroupResource(&in.ConfigGroupResource, &out.ConfigGroupResource, s); err != nil { + return err + } + if err := Convert_v1beta1_ConfigReferent_To_v1alpha1_ConfigReferent(&in.ConfigReferent, &out.ConfigReferent, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_AddOnConfig_To_v1alpha1_AddOnConfig is an autogenerated conversion function. +func Convert_v1beta1_AddOnConfig_To_v1alpha1_AddOnConfig(in *AddOnConfig, out *v1alpha1.AddOnConfig, s conversion.Scope) error { + return autoConvert_v1beta1_AddOnConfig_To_v1alpha1_AddOnConfig(in, out, s) +} + +func autoConvert_v1alpha1_AddOnConfig_To_v1beta1_AddOnConfig(in *v1alpha1.AddOnConfig, out *AddOnConfig, s conversion.Scope) error { + if err := Convert_v1alpha1_ConfigGroupResource_To_v1beta1_ConfigGroupResource(&in.ConfigGroupResource, &out.ConfigGroupResource, s); err != nil { + return err + } + if err := Convert_v1alpha1_ConfigReferent_To_v1beta1_ConfigReferent(&in.ConfigReferent, &out.ConfigReferent, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_AddOnConfig_To_v1beta1_AddOnConfig is an autogenerated conversion function. +func Convert_v1alpha1_AddOnConfig_To_v1beta1_AddOnConfig(in *v1alpha1.AddOnConfig, out *AddOnConfig, s conversion.Scope) error { + return autoConvert_v1alpha1_AddOnConfig_To_v1beta1_AddOnConfig(in, out, s) +} + +func autoConvert_v1beta1_AddOnMeta_To_v1alpha1_AddOnMeta(in *AddOnMeta, out *v1alpha1.AddOnMeta, s conversion.Scope) error { + out.DisplayName = in.DisplayName + out.Description = in.Description + return nil +} + +// Convert_v1beta1_AddOnMeta_To_v1alpha1_AddOnMeta is an autogenerated conversion function. +func Convert_v1beta1_AddOnMeta_To_v1alpha1_AddOnMeta(in *AddOnMeta, out *v1alpha1.AddOnMeta, s conversion.Scope) error { + return autoConvert_v1beta1_AddOnMeta_To_v1alpha1_AddOnMeta(in, out, s) +} + +func autoConvert_v1alpha1_AddOnMeta_To_v1beta1_AddOnMeta(in *v1alpha1.AddOnMeta, out *AddOnMeta, s conversion.Scope) error { + out.DisplayName = in.DisplayName + out.Description = in.Description + return nil +} + +// Convert_v1alpha1_AddOnMeta_To_v1beta1_AddOnMeta is an autogenerated conversion function. +func Convert_v1alpha1_AddOnMeta_To_v1beta1_AddOnMeta(in *v1alpha1.AddOnMeta, out *AddOnMeta, s conversion.Scope) error { + return autoConvert_v1alpha1_AddOnMeta_To_v1beta1_AddOnMeta(in, out, s) +} + +func autoConvert_v1beta1_ClusterManagementAddOn_To_v1alpha1_ClusterManagementAddOn(in *ClusterManagementAddOn, out *v1alpha1.ClusterManagementAddOn, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1beta1_ClusterManagementAddOnSpec_To_v1alpha1_ClusterManagementAddOnSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1beta1_ClusterManagementAddOnStatus_To_v1alpha1_ClusterManagementAddOnStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_ClusterManagementAddOn_To_v1alpha1_ClusterManagementAddOn is an autogenerated conversion function. +func Convert_v1beta1_ClusterManagementAddOn_To_v1alpha1_ClusterManagementAddOn(in *ClusterManagementAddOn, out *v1alpha1.ClusterManagementAddOn, s conversion.Scope) error { + return autoConvert_v1beta1_ClusterManagementAddOn_To_v1alpha1_ClusterManagementAddOn(in, out, s) +} + +func autoConvert_v1alpha1_ClusterManagementAddOn_To_v1beta1_ClusterManagementAddOn(in *v1alpha1.ClusterManagementAddOn, out *ClusterManagementAddOn, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha1_ClusterManagementAddOnSpec_To_v1beta1_ClusterManagementAddOnSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha1_ClusterManagementAddOnStatus_To_v1beta1_ClusterManagementAddOnStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_ClusterManagementAddOn_To_v1beta1_ClusterManagementAddOn is an autogenerated conversion function. +func Convert_v1alpha1_ClusterManagementAddOn_To_v1beta1_ClusterManagementAddOn(in *v1alpha1.ClusterManagementAddOn, out *ClusterManagementAddOn, s conversion.Scope) error { + return autoConvert_v1alpha1_ClusterManagementAddOn_To_v1beta1_ClusterManagementAddOn(in, out, s) +} + +func autoConvert_v1beta1_ClusterManagementAddOnList_To_v1alpha1_ClusterManagementAddOnList(in *ClusterManagementAddOnList, out *v1alpha1.ClusterManagementAddOnList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]v1alpha1.ClusterManagementAddOn, len(*in)) + for i := range *in { + if err := Convert_v1beta1_ClusterManagementAddOn_To_v1alpha1_ClusterManagementAddOn(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1beta1_ClusterManagementAddOnList_To_v1alpha1_ClusterManagementAddOnList is an autogenerated conversion function. +func Convert_v1beta1_ClusterManagementAddOnList_To_v1alpha1_ClusterManagementAddOnList(in *ClusterManagementAddOnList, out *v1alpha1.ClusterManagementAddOnList, s conversion.Scope) error { + return autoConvert_v1beta1_ClusterManagementAddOnList_To_v1alpha1_ClusterManagementAddOnList(in, out, s) +} + +func autoConvert_v1alpha1_ClusterManagementAddOnList_To_v1beta1_ClusterManagementAddOnList(in *v1alpha1.ClusterManagementAddOnList, out *ClusterManagementAddOnList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ClusterManagementAddOn, len(*in)) + for i := range *in { + if err := Convert_v1alpha1_ClusterManagementAddOn_To_v1beta1_ClusterManagementAddOn(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1alpha1_ClusterManagementAddOnList_To_v1beta1_ClusterManagementAddOnList is an autogenerated conversion function. +func Convert_v1alpha1_ClusterManagementAddOnList_To_v1beta1_ClusterManagementAddOnList(in *v1alpha1.ClusterManagementAddOnList, out *ClusterManagementAddOnList, s conversion.Scope) error { + return autoConvert_v1alpha1_ClusterManagementAddOnList_To_v1beta1_ClusterManagementAddOnList(in, out, s) +} + +func autoConvert_v1beta1_ClusterManagementAddOnSpec_To_v1alpha1_ClusterManagementAddOnSpec(in *ClusterManagementAddOnSpec, out *v1alpha1.ClusterManagementAddOnSpec, s conversion.Scope) error { + if err := Convert_v1beta1_AddOnMeta_To_v1alpha1_AddOnMeta(&in.AddOnMeta, &out.AddOnMeta, s); err != nil { + return err + } + // WARNING: in.DefaultConfigs requires manual conversion: does not exist in peer-type + if err := Convert_v1beta1_InstallStrategy_To_v1alpha1_InstallStrategy(&in.InstallStrategy, &out.InstallStrategy, s); err != nil { + return err + } + return nil +} + +func autoConvert_v1alpha1_ClusterManagementAddOnSpec_To_v1beta1_ClusterManagementAddOnSpec(in *v1alpha1.ClusterManagementAddOnSpec, out *ClusterManagementAddOnSpec, s conversion.Scope) error { + if err := Convert_v1alpha1_AddOnMeta_To_v1beta1_AddOnMeta(&in.AddOnMeta, &out.AddOnMeta, s); err != nil { + return err + } + // WARNING: in.AddOnConfiguration requires manual conversion: does not exist in peer-type + // WARNING: in.SupportedConfigs requires manual conversion: does not exist in peer-type + if err := Convert_v1alpha1_InstallStrategy_To_v1beta1_InstallStrategy(&in.InstallStrategy, &out.InstallStrategy, s); err != nil { + return err + } + return nil +} + +func autoConvert_v1beta1_ClusterManagementAddOnStatus_To_v1alpha1_ClusterManagementAddOnStatus(in *ClusterManagementAddOnStatus, out *v1alpha1.ClusterManagementAddOnStatus, s conversion.Scope) error { + out.DefaultConfigReferences = *(*[]v1alpha1.DefaultConfigReference)(unsafe.Pointer(&in.DefaultConfigReferences)) + out.InstallProgressions = *(*[]v1alpha1.InstallProgression)(unsafe.Pointer(&in.InstallProgressions)) + return nil +} + +// Convert_v1beta1_ClusterManagementAddOnStatus_To_v1alpha1_ClusterManagementAddOnStatus is an autogenerated conversion function. +func Convert_v1beta1_ClusterManagementAddOnStatus_To_v1alpha1_ClusterManagementAddOnStatus(in *ClusterManagementAddOnStatus, out *v1alpha1.ClusterManagementAddOnStatus, s conversion.Scope) error { + return autoConvert_v1beta1_ClusterManagementAddOnStatus_To_v1alpha1_ClusterManagementAddOnStatus(in, out, s) +} + +func autoConvert_v1alpha1_ClusterManagementAddOnStatus_To_v1beta1_ClusterManagementAddOnStatus(in *v1alpha1.ClusterManagementAddOnStatus, out *ClusterManagementAddOnStatus, s conversion.Scope) error { + out.DefaultConfigReferences = *(*[]DefaultConfigReference)(unsafe.Pointer(&in.DefaultConfigReferences)) + out.InstallProgressions = *(*[]InstallProgression)(unsafe.Pointer(&in.InstallProgressions)) + return nil +} + +// Convert_v1alpha1_ClusterManagementAddOnStatus_To_v1beta1_ClusterManagementAddOnStatus is an autogenerated conversion function. +func Convert_v1alpha1_ClusterManagementAddOnStatus_To_v1beta1_ClusterManagementAddOnStatus(in *v1alpha1.ClusterManagementAddOnStatus, out *ClusterManagementAddOnStatus, s conversion.Scope) error { + return autoConvert_v1alpha1_ClusterManagementAddOnStatus_To_v1beta1_ClusterManagementAddOnStatus(in, out, s) +} + +func autoConvert_v1beta1_ConfigGroupResource_To_v1alpha1_ConfigGroupResource(in *ConfigGroupResource, out *v1alpha1.ConfigGroupResource, s conversion.Scope) error { + out.Group = in.Group + out.Resource = in.Resource + return nil +} + +// Convert_v1beta1_ConfigGroupResource_To_v1alpha1_ConfigGroupResource is an autogenerated conversion function. +func Convert_v1beta1_ConfigGroupResource_To_v1alpha1_ConfigGroupResource(in *ConfigGroupResource, out *v1alpha1.ConfigGroupResource, s conversion.Scope) error { + return autoConvert_v1beta1_ConfigGroupResource_To_v1alpha1_ConfigGroupResource(in, out, s) +} + +func autoConvert_v1alpha1_ConfigGroupResource_To_v1beta1_ConfigGroupResource(in *v1alpha1.ConfigGroupResource, out *ConfigGroupResource, s conversion.Scope) error { + out.Group = in.Group + out.Resource = in.Resource + return nil +} + +// Convert_v1alpha1_ConfigGroupResource_To_v1beta1_ConfigGroupResource is an autogenerated conversion function. +func Convert_v1alpha1_ConfigGroupResource_To_v1beta1_ConfigGroupResource(in *v1alpha1.ConfigGroupResource, out *ConfigGroupResource, s conversion.Scope) error { + return autoConvert_v1alpha1_ConfigGroupResource_To_v1beta1_ConfigGroupResource(in, out, s) +} + +func autoConvert_v1beta1_ConfigReference_To_v1alpha1_ConfigReference(in *ConfigReference, out *v1alpha1.ConfigReference, s conversion.Scope) error { + if err := Convert_v1beta1_ConfigGroupResource_To_v1alpha1_ConfigGroupResource(&in.ConfigGroupResource, &out.ConfigGroupResource, s); err != nil { + return err + } + out.LastObservedGeneration = in.LastObservedGeneration + out.DesiredConfig = (*v1alpha1.ConfigSpecHash)(unsafe.Pointer(in.DesiredConfig)) + out.LastAppliedConfig = (*v1alpha1.ConfigSpecHash)(unsafe.Pointer(in.LastAppliedConfig)) + return nil +} + +// Convert_v1beta1_ConfigReference_To_v1alpha1_ConfigReference is an autogenerated conversion function. +func Convert_v1beta1_ConfigReference_To_v1alpha1_ConfigReference(in *ConfigReference, out *v1alpha1.ConfigReference, s conversion.Scope) error { + return autoConvert_v1beta1_ConfigReference_To_v1alpha1_ConfigReference(in, out, s) +} + +func autoConvert_v1alpha1_ConfigReference_To_v1beta1_ConfigReference(in *v1alpha1.ConfigReference, out *ConfigReference, s conversion.Scope) error { + if err := Convert_v1alpha1_ConfigGroupResource_To_v1beta1_ConfigGroupResource(&in.ConfigGroupResource, &out.ConfigGroupResource, s); err != nil { + return err + } + // WARNING: in.ConfigReferent requires manual conversion: does not exist in peer-type + out.LastObservedGeneration = in.LastObservedGeneration + out.DesiredConfig = (*ConfigSpecHash)(unsafe.Pointer(in.DesiredConfig)) + out.LastAppliedConfig = (*ConfigSpecHash)(unsafe.Pointer(in.LastAppliedConfig)) + return nil +} + +func autoConvert_v1beta1_ConfigReferent_To_v1alpha1_ConfigReferent(in *ConfigReferent, out *v1alpha1.ConfigReferent, s conversion.Scope) error { + out.Namespace = in.Namespace + out.Name = in.Name + return nil +} + +// Convert_v1beta1_ConfigReferent_To_v1alpha1_ConfigReferent is an autogenerated conversion function. +func Convert_v1beta1_ConfigReferent_To_v1alpha1_ConfigReferent(in *ConfigReferent, out *v1alpha1.ConfigReferent, s conversion.Scope) error { + return autoConvert_v1beta1_ConfigReferent_To_v1alpha1_ConfigReferent(in, out, s) +} + +func autoConvert_v1alpha1_ConfigReferent_To_v1beta1_ConfigReferent(in *v1alpha1.ConfigReferent, out *ConfigReferent, s conversion.Scope) error { + out.Namespace = in.Namespace + out.Name = in.Name + return nil +} + +// Convert_v1alpha1_ConfigReferent_To_v1beta1_ConfigReferent is an autogenerated conversion function. +func Convert_v1alpha1_ConfigReferent_To_v1beta1_ConfigReferent(in *v1alpha1.ConfigReferent, out *ConfigReferent, s conversion.Scope) error { + return autoConvert_v1alpha1_ConfigReferent_To_v1beta1_ConfigReferent(in, out, s) +} + +func autoConvert_v1beta1_ConfigSpecHash_To_v1alpha1_ConfigSpecHash(in *ConfigSpecHash, out *v1alpha1.ConfigSpecHash, s conversion.Scope) error { + if err := Convert_v1beta1_ConfigReferent_To_v1alpha1_ConfigReferent(&in.ConfigReferent, &out.ConfigReferent, s); err != nil { + return err + } + out.SpecHash = in.SpecHash + return nil +} + +// Convert_v1beta1_ConfigSpecHash_To_v1alpha1_ConfigSpecHash is an autogenerated conversion function. +func Convert_v1beta1_ConfigSpecHash_To_v1alpha1_ConfigSpecHash(in *ConfigSpecHash, out *v1alpha1.ConfigSpecHash, s conversion.Scope) error { + return autoConvert_v1beta1_ConfigSpecHash_To_v1alpha1_ConfigSpecHash(in, out, s) +} + +func autoConvert_v1alpha1_ConfigSpecHash_To_v1beta1_ConfigSpecHash(in *v1alpha1.ConfigSpecHash, out *ConfigSpecHash, s conversion.Scope) error { + if err := Convert_v1alpha1_ConfigReferent_To_v1beta1_ConfigReferent(&in.ConfigReferent, &out.ConfigReferent, s); err != nil { + return err + } + out.SpecHash = in.SpecHash + return nil +} + +// Convert_v1alpha1_ConfigSpecHash_To_v1beta1_ConfigSpecHash is an autogenerated conversion function. +func Convert_v1alpha1_ConfigSpecHash_To_v1beta1_ConfigSpecHash(in *v1alpha1.ConfigSpecHash, out *ConfigSpecHash, s conversion.Scope) error { + return autoConvert_v1alpha1_ConfigSpecHash_To_v1beta1_ConfigSpecHash(in, out, s) +} + +func autoConvert_v1beta1_DefaultConfigReference_To_v1alpha1_DefaultConfigReference(in *DefaultConfigReference, out *v1alpha1.DefaultConfigReference, s conversion.Scope) error { + if err := Convert_v1beta1_ConfigGroupResource_To_v1alpha1_ConfigGroupResource(&in.ConfigGroupResource, &out.ConfigGroupResource, s); err != nil { + return err + } + out.DesiredConfig = (*v1alpha1.ConfigSpecHash)(unsafe.Pointer(in.DesiredConfig)) + return nil +} + +// Convert_v1beta1_DefaultConfigReference_To_v1alpha1_DefaultConfigReference is an autogenerated conversion function. +func Convert_v1beta1_DefaultConfigReference_To_v1alpha1_DefaultConfigReference(in *DefaultConfigReference, out *v1alpha1.DefaultConfigReference, s conversion.Scope) error { + return autoConvert_v1beta1_DefaultConfigReference_To_v1alpha1_DefaultConfigReference(in, out, s) +} + +func autoConvert_v1alpha1_DefaultConfigReference_To_v1beta1_DefaultConfigReference(in *v1alpha1.DefaultConfigReference, out *DefaultConfigReference, s conversion.Scope) error { + if err := Convert_v1alpha1_ConfigGroupResource_To_v1beta1_ConfigGroupResource(&in.ConfigGroupResource, &out.ConfigGroupResource, s); err != nil { + return err + } + out.DesiredConfig = (*ConfigSpecHash)(unsafe.Pointer(in.DesiredConfig)) + return nil +} + +// Convert_v1alpha1_DefaultConfigReference_To_v1beta1_DefaultConfigReference is an autogenerated conversion function. +func Convert_v1alpha1_DefaultConfigReference_To_v1beta1_DefaultConfigReference(in *v1alpha1.DefaultConfigReference, out *DefaultConfigReference, s conversion.Scope) error { + return autoConvert_v1alpha1_DefaultConfigReference_To_v1beta1_DefaultConfigReference(in, out, s) +} + +func autoConvert_v1beta1_HealthCheck_To_v1alpha1_HealthCheck(in *HealthCheck, out *v1alpha1.HealthCheck, s conversion.Scope) error { + out.Mode = v1alpha1.HealthCheckMode(in.Mode) + return nil +} + +// Convert_v1beta1_HealthCheck_To_v1alpha1_HealthCheck is an autogenerated conversion function. +func Convert_v1beta1_HealthCheck_To_v1alpha1_HealthCheck(in *HealthCheck, out *v1alpha1.HealthCheck, s conversion.Scope) error { + return autoConvert_v1beta1_HealthCheck_To_v1alpha1_HealthCheck(in, out, s) +} + +func autoConvert_v1alpha1_HealthCheck_To_v1beta1_HealthCheck(in *v1alpha1.HealthCheck, out *HealthCheck, s conversion.Scope) error { + out.Mode = HealthCheckMode(in.Mode) + return nil +} + +// Convert_v1alpha1_HealthCheck_To_v1beta1_HealthCheck is an autogenerated conversion function. +func Convert_v1alpha1_HealthCheck_To_v1beta1_HealthCheck(in *v1alpha1.HealthCheck, out *HealthCheck, s conversion.Scope) error { + return autoConvert_v1alpha1_HealthCheck_To_v1beta1_HealthCheck(in, out, s) +} + +func autoConvert_v1beta1_InstallConfigReference_To_v1alpha1_InstallConfigReference(in *InstallConfigReference, out *v1alpha1.InstallConfigReference, s conversion.Scope) error { + if err := Convert_v1beta1_ConfigGroupResource_To_v1alpha1_ConfigGroupResource(&in.ConfigGroupResource, &out.ConfigGroupResource, s); err != nil { + return err + } + out.DesiredConfig = (*v1alpha1.ConfigSpecHash)(unsafe.Pointer(in.DesiredConfig)) + out.LastKnownGoodConfig = (*v1alpha1.ConfigSpecHash)(unsafe.Pointer(in.LastKnownGoodConfig)) + out.LastAppliedConfig = (*v1alpha1.ConfigSpecHash)(unsafe.Pointer(in.LastAppliedConfig)) + return nil +} + +// Convert_v1beta1_InstallConfigReference_To_v1alpha1_InstallConfigReference is an autogenerated conversion function. +func Convert_v1beta1_InstallConfigReference_To_v1alpha1_InstallConfigReference(in *InstallConfigReference, out *v1alpha1.InstallConfigReference, s conversion.Scope) error { + return autoConvert_v1beta1_InstallConfigReference_To_v1alpha1_InstallConfigReference(in, out, s) +} + +func autoConvert_v1alpha1_InstallConfigReference_To_v1beta1_InstallConfigReference(in *v1alpha1.InstallConfigReference, out *InstallConfigReference, s conversion.Scope) error { + if err := Convert_v1alpha1_ConfigGroupResource_To_v1beta1_ConfigGroupResource(&in.ConfigGroupResource, &out.ConfigGroupResource, s); err != nil { + return err + } + out.DesiredConfig = (*ConfigSpecHash)(unsafe.Pointer(in.DesiredConfig)) + out.LastKnownGoodConfig = (*ConfigSpecHash)(unsafe.Pointer(in.LastKnownGoodConfig)) + out.LastAppliedConfig = (*ConfigSpecHash)(unsafe.Pointer(in.LastAppliedConfig)) + return nil +} + +// Convert_v1alpha1_InstallConfigReference_To_v1beta1_InstallConfigReference is an autogenerated conversion function. +func Convert_v1alpha1_InstallConfigReference_To_v1beta1_InstallConfigReference(in *v1alpha1.InstallConfigReference, out *InstallConfigReference, s conversion.Scope) error { + return autoConvert_v1alpha1_InstallConfigReference_To_v1beta1_InstallConfigReference(in, out, s) +} + +func autoConvert_v1beta1_InstallProgression_To_v1alpha1_InstallProgression(in *InstallProgression, out *v1alpha1.InstallProgression, s conversion.Scope) error { + if err := Convert_v1beta1_PlacementRef_To_v1alpha1_PlacementRef(&in.PlacementRef, &out.PlacementRef, s); err != nil { + return err + } + out.ConfigReferences = *(*[]v1alpha1.InstallConfigReference)(unsafe.Pointer(&in.ConfigReferences)) + out.Conditions = *(*[]v1.Condition)(unsafe.Pointer(&in.Conditions)) + return nil +} + +// Convert_v1beta1_InstallProgression_To_v1alpha1_InstallProgression is an autogenerated conversion function. +func Convert_v1beta1_InstallProgression_To_v1alpha1_InstallProgression(in *InstallProgression, out *v1alpha1.InstallProgression, s conversion.Scope) error { + return autoConvert_v1beta1_InstallProgression_To_v1alpha1_InstallProgression(in, out, s) +} + +func autoConvert_v1alpha1_InstallProgression_To_v1beta1_InstallProgression(in *v1alpha1.InstallProgression, out *InstallProgression, s conversion.Scope) error { + if err := Convert_v1alpha1_PlacementRef_To_v1beta1_PlacementRef(&in.PlacementRef, &out.PlacementRef, s); err != nil { + return err + } + out.ConfigReferences = *(*[]InstallConfigReference)(unsafe.Pointer(&in.ConfigReferences)) + out.Conditions = *(*[]v1.Condition)(unsafe.Pointer(&in.Conditions)) + return nil +} + +// Convert_v1alpha1_InstallProgression_To_v1beta1_InstallProgression is an autogenerated conversion function. +func Convert_v1alpha1_InstallProgression_To_v1beta1_InstallProgression(in *v1alpha1.InstallProgression, out *InstallProgression, s conversion.Scope) error { + return autoConvert_v1alpha1_InstallProgression_To_v1beta1_InstallProgression(in, out, s) +} + +func autoConvert_v1beta1_InstallStrategy_To_v1alpha1_InstallStrategy(in *InstallStrategy, out *v1alpha1.InstallStrategy, s conversion.Scope) error { + out.Type = in.Type + out.Placements = *(*[]v1alpha1.PlacementStrategy)(unsafe.Pointer(&in.Placements)) + return nil +} + +// Convert_v1beta1_InstallStrategy_To_v1alpha1_InstallStrategy is an autogenerated conversion function. +func Convert_v1beta1_InstallStrategy_To_v1alpha1_InstallStrategy(in *InstallStrategy, out *v1alpha1.InstallStrategy, s conversion.Scope) error { + return autoConvert_v1beta1_InstallStrategy_To_v1alpha1_InstallStrategy(in, out, s) +} + +func autoConvert_v1alpha1_InstallStrategy_To_v1beta1_InstallStrategy(in *v1alpha1.InstallStrategy, out *InstallStrategy, s conversion.Scope) error { + out.Type = in.Type + out.Placements = *(*[]PlacementStrategy)(unsafe.Pointer(&in.Placements)) + return nil +} + +// Convert_v1alpha1_InstallStrategy_To_v1beta1_InstallStrategy is an autogenerated conversion function. +func Convert_v1alpha1_InstallStrategy_To_v1beta1_InstallStrategy(in *v1alpha1.InstallStrategy, out *InstallStrategy, s conversion.Scope) error { + return autoConvert_v1alpha1_InstallStrategy_To_v1beta1_InstallStrategy(in, out, s) +} + +func autoConvert_v1beta1_ManagedClusterAddOn_To_v1alpha1_ManagedClusterAddOn(in *ManagedClusterAddOn, out *v1alpha1.ManagedClusterAddOn, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1beta1_ManagedClusterAddOnSpec_To_v1alpha1_ManagedClusterAddOnSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1beta1_ManagedClusterAddOnStatus_To_v1alpha1_ManagedClusterAddOnStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_ManagedClusterAddOn_To_v1alpha1_ManagedClusterAddOn is an autogenerated conversion function. +func Convert_v1beta1_ManagedClusterAddOn_To_v1alpha1_ManagedClusterAddOn(in *ManagedClusterAddOn, out *v1alpha1.ManagedClusterAddOn, s conversion.Scope) error { + return autoConvert_v1beta1_ManagedClusterAddOn_To_v1alpha1_ManagedClusterAddOn(in, out, s) +} + +func autoConvert_v1alpha1_ManagedClusterAddOn_To_v1beta1_ManagedClusterAddOn(in *v1alpha1.ManagedClusterAddOn, out *ManagedClusterAddOn, s conversion.Scope) error { + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha1_ManagedClusterAddOnSpec_To_v1beta1_ManagedClusterAddOnSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha1_ManagedClusterAddOnStatus_To_v1beta1_ManagedClusterAddOnStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_ManagedClusterAddOn_To_v1beta1_ManagedClusterAddOn is an autogenerated conversion function. +func Convert_v1alpha1_ManagedClusterAddOn_To_v1beta1_ManagedClusterAddOn(in *v1alpha1.ManagedClusterAddOn, out *ManagedClusterAddOn, s conversion.Scope) error { + return autoConvert_v1alpha1_ManagedClusterAddOn_To_v1beta1_ManagedClusterAddOn(in, out, s) +} + +func autoConvert_v1beta1_ManagedClusterAddOnList_To_v1alpha1_ManagedClusterAddOnList(in *ManagedClusterAddOnList, out *v1alpha1.ManagedClusterAddOnList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]v1alpha1.ManagedClusterAddOn, len(*in)) + for i := range *in { + if err := Convert_v1beta1_ManagedClusterAddOn_To_v1alpha1_ManagedClusterAddOn(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1beta1_ManagedClusterAddOnList_To_v1alpha1_ManagedClusterAddOnList is an autogenerated conversion function. +func Convert_v1beta1_ManagedClusterAddOnList_To_v1alpha1_ManagedClusterAddOnList(in *ManagedClusterAddOnList, out *v1alpha1.ManagedClusterAddOnList, s conversion.Scope) error { + return autoConvert_v1beta1_ManagedClusterAddOnList_To_v1alpha1_ManagedClusterAddOnList(in, out, s) +} + +func autoConvert_v1alpha1_ManagedClusterAddOnList_To_v1beta1_ManagedClusterAddOnList(in *v1alpha1.ManagedClusterAddOnList, out *ManagedClusterAddOnList, s conversion.Scope) error { + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ManagedClusterAddOn, len(*in)) + for i := range *in { + if err := Convert_v1alpha1_ManagedClusterAddOn_To_v1beta1_ManagedClusterAddOn(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1alpha1_ManagedClusterAddOnList_To_v1beta1_ManagedClusterAddOnList is an autogenerated conversion function. +func Convert_v1alpha1_ManagedClusterAddOnList_To_v1beta1_ManagedClusterAddOnList(in *v1alpha1.ManagedClusterAddOnList, out *ManagedClusterAddOnList, s conversion.Scope) error { + return autoConvert_v1alpha1_ManagedClusterAddOnList_To_v1beta1_ManagedClusterAddOnList(in, out, s) +} + +func autoConvert_v1beta1_ManagedClusterAddOnSpec_To_v1alpha1_ManagedClusterAddOnSpec(in *ManagedClusterAddOnSpec, out *v1alpha1.ManagedClusterAddOnSpec, s conversion.Scope) error { + out.Configs = *(*[]v1alpha1.AddOnConfig)(unsafe.Pointer(&in.Configs)) + return nil +} + +// Convert_v1beta1_ManagedClusterAddOnSpec_To_v1alpha1_ManagedClusterAddOnSpec is an autogenerated conversion function. +func Convert_v1beta1_ManagedClusterAddOnSpec_To_v1alpha1_ManagedClusterAddOnSpec(in *ManagedClusterAddOnSpec, out *v1alpha1.ManagedClusterAddOnSpec, s conversion.Scope) error { + return autoConvert_v1beta1_ManagedClusterAddOnSpec_To_v1alpha1_ManagedClusterAddOnSpec(in, out, s) +} + +func autoConvert_v1alpha1_ManagedClusterAddOnSpec_To_v1beta1_ManagedClusterAddOnSpec(in *v1alpha1.ManagedClusterAddOnSpec, out *ManagedClusterAddOnSpec, s conversion.Scope) error { + // WARNING: in.InstallNamespace requires manual conversion: does not exist in peer-type + out.Configs = *(*[]AddOnConfig)(unsafe.Pointer(&in.Configs)) + return nil +} + +func autoConvert_v1beta1_ManagedClusterAddOnStatus_To_v1alpha1_ManagedClusterAddOnStatus(in *ManagedClusterAddOnStatus, out *v1alpha1.ManagedClusterAddOnStatus, s conversion.Scope) error { + out.Conditions = *(*[]v1.Condition)(unsafe.Pointer(&in.Conditions)) + out.RelatedObjects = *(*[]v1alpha1.ObjectReference)(unsafe.Pointer(&in.RelatedObjects)) + if err := Convert_v1beta1_AddOnMeta_To_v1alpha1_AddOnMeta(&in.AddOnMeta, &out.AddOnMeta, s); err != nil { + return err + } + out.SupportedConfigs = *(*[]v1alpha1.ConfigGroupResource)(unsafe.Pointer(&in.SupportedConfigs)) + if in.ConfigReferences != nil { + in, out := &in.ConfigReferences, &out.ConfigReferences + *out = make([]v1alpha1.ConfigReference, len(*in)) + for i := range *in { + if err := Convert_v1beta1_ConfigReference_To_v1alpha1_ConfigReference(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.ConfigReferences = nil + } + out.Namespace = in.Namespace + if in.Registrations != nil { + in, out := &in.Registrations, &out.Registrations + *out = make([]v1alpha1.RegistrationConfig, len(*in)) + for i := range *in { + if err := Convert_v1beta1_RegistrationConfig_To_v1alpha1_RegistrationConfig(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Registrations = nil + } + if err := Convert_v1beta1_HealthCheck_To_v1alpha1_HealthCheck(&in.HealthCheck, &out.HealthCheck, s); err != nil { + return err + } + return nil +} + +// Convert_v1beta1_ManagedClusterAddOnStatus_To_v1alpha1_ManagedClusterAddOnStatus is an autogenerated conversion function. +func Convert_v1beta1_ManagedClusterAddOnStatus_To_v1alpha1_ManagedClusterAddOnStatus(in *ManagedClusterAddOnStatus, out *v1alpha1.ManagedClusterAddOnStatus, s conversion.Scope) error { + return autoConvert_v1beta1_ManagedClusterAddOnStatus_To_v1alpha1_ManagedClusterAddOnStatus(in, out, s) +} + +func autoConvert_v1alpha1_ManagedClusterAddOnStatus_To_v1beta1_ManagedClusterAddOnStatus(in *v1alpha1.ManagedClusterAddOnStatus, out *ManagedClusterAddOnStatus, s conversion.Scope) error { + out.Conditions = *(*[]v1.Condition)(unsafe.Pointer(&in.Conditions)) + out.RelatedObjects = *(*[]ObjectReference)(unsafe.Pointer(&in.RelatedObjects)) + if err := Convert_v1alpha1_AddOnMeta_To_v1beta1_AddOnMeta(&in.AddOnMeta, &out.AddOnMeta, s); err != nil { + return err + } + // WARNING: in.AddOnConfiguration requires manual conversion: does not exist in peer-type + out.SupportedConfigs = *(*[]ConfigGroupResource)(unsafe.Pointer(&in.SupportedConfigs)) + if in.ConfigReferences != nil { + in, out := &in.ConfigReferences, &out.ConfigReferences + *out = make([]ConfigReference, len(*in)) + for i := range *in { + if err := Convert_v1alpha1_ConfigReference_To_v1beta1_ConfigReference(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.ConfigReferences = nil + } + out.Namespace = in.Namespace + if in.Registrations != nil { + in, out := &in.Registrations, &out.Registrations + *out = make([]RegistrationConfig, len(*in)) + for i := range *in { + if err := Convert_v1alpha1_RegistrationConfig_To_v1beta1_RegistrationConfig(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Registrations = nil + } + if err := Convert_v1alpha1_HealthCheck_To_v1beta1_HealthCheck(&in.HealthCheck, &out.HealthCheck, s); err != nil { + return err + } + return nil +} + +func autoConvert_v1beta1_ObjectReference_To_v1alpha1_ObjectReference(in *ObjectReference, out *v1alpha1.ObjectReference, s conversion.Scope) error { + out.Group = in.Group + out.Resource = in.Resource + out.Namespace = in.Namespace + out.Name = in.Name + return nil +} + +// Convert_v1beta1_ObjectReference_To_v1alpha1_ObjectReference is an autogenerated conversion function. +func Convert_v1beta1_ObjectReference_To_v1alpha1_ObjectReference(in *ObjectReference, out *v1alpha1.ObjectReference, s conversion.Scope) error { + return autoConvert_v1beta1_ObjectReference_To_v1alpha1_ObjectReference(in, out, s) +} + +func autoConvert_v1alpha1_ObjectReference_To_v1beta1_ObjectReference(in *v1alpha1.ObjectReference, out *ObjectReference, s conversion.Scope) error { + out.Group = in.Group + out.Resource = in.Resource + out.Namespace = in.Namespace + out.Name = in.Name + return nil +} + +// Convert_v1alpha1_ObjectReference_To_v1beta1_ObjectReference is an autogenerated conversion function. +func Convert_v1alpha1_ObjectReference_To_v1beta1_ObjectReference(in *v1alpha1.ObjectReference, out *ObjectReference, s conversion.Scope) error { + return autoConvert_v1alpha1_ObjectReference_To_v1beta1_ObjectReference(in, out, s) +} + +func autoConvert_v1beta1_PlacementRef_To_v1alpha1_PlacementRef(in *PlacementRef, out *v1alpha1.PlacementRef, s conversion.Scope) error { + out.Namespace = in.Namespace + out.Name = in.Name + return nil +} + +// Convert_v1beta1_PlacementRef_To_v1alpha1_PlacementRef is an autogenerated conversion function. +func Convert_v1beta1_PlacementRef_To_v1alpha1_PlacementRef(in *PlacementRef, out *v1alpha1.PlacementRef, s conversion.Scope) error { + return autoConvert_v1beta1_PlacementRef_To_v1alpha1_PlacementRef(in, out, s) +} + +func autoConvert_v1alpha1_PlacementRef_To_v1beta1_PlacementRef(in *v1alpha1.PlacementRef, out *PlacementRef, s conversion.Scope) error { + out.Namespace = in.Namespace + out.Name = in.Name + return nil +} + +// Convert_v1alpha1_PlacementRef_To_v1beta1_PlacementRef is an autogenerated conversion function. +func Convert_v1alpha1_PlacementRef_To_v1beta1_PlacementRef(in *v1alpha1.PlacementRef, out *PlacementRef, s conversion.Scope) error { + return autoConvert_v1alpha1_PlacementRef_To_v1beta1_PlacementRef(in, out, s) +} + +func autoConvert_v1beta1_PlacementStrategy_To_v1alpha1_PlacementStrategy(in *PlacementStrategy, out *v1alpha1.PlacementStrategy, s conversion.Scope) error { + if err := Convert_v1beta1_PlacementRef_To_v1alpha1_PlacementRef(&in.PlacementRef, &out.PlacementRef, s); err != nil { + return err + } + out.Configs = *(*[]v1alpha1.AddOnConfig)(unsafe.Pointer(&in.Configs)) + out.RolloutStrategy = in.RolloutStrategy + return nil +} + +// Convert_v1beta1_PlacementStrategy_To_v1alpha1_PlacementStrategy is an autogenerated conversion function. +func Convert_v1beta1_PlacementStrategy_To_v1alpha1_PlacementStrategy(in *PlacementStrategy, out *v1alpha1.PlacementStrategy, s conversion.Scope) error { + return autoConvert_v1beta1_PlacementStrategy_To_v1alpha1_PlacementStrategy(in, out, s) +} + +func autoConvert_v1alpha1_PlacementStrategy_To_v1beta1_PlacementStrategy(in *v1alpha1.PlacementStrategy, out *PlacementStrategy, s conversion.Scope) error { + if err := Convert_v1alpha1_PlacementRef_To_v1beta1_PlacementRef(&in.PlacementRef, &out.PlacementRef, s); err != nil { + return err + } + out.Configs = *(*[]AddOnConfig)(unsafe.Pointer(&in.Configs)) + out.RolloutStrategy = in.RolloutStrategy + return nil +} + +// Convert_v1alpha1_PlacementStrategy_To_v1beta1_PlacementStrategy is an autogenerated conversion function. +func Convert_v1alpha1_PlacementStrategy_To_v1beta1_PlacementStrategy(in *v1alpha1.PlacementStrategy, out *PlacementStrategy, s conversion.Scope) error { + return autoConvert_v1alpha1_PlacementStrategy_To_v1beta1_PlacementStrategy(in, out, s) +} + +func autoConvert_v1beta1_RegistrationConfig_To_v1alpha1_RegistrationConfig(in *RegistrationConfig, out *v1alpha1.RegistrationConfig, s conversion.Scope) error { + // WARNING: in.Type requires manual conversion: does not exist in peer-type + // WARNING: in.KubeClient requires manual conversion: does not exist in peer-type + // WARNING: in.CSR requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1alpha1_RegistrationConfig_To_v1beta1_RegistrationConfig(in *v1alpha1.RegistrationConfig, out *RegistrationConfig, s conversion.Scope) error { + // WARNING: in.SignerName requires manual conversion: does not exist in peer-type + // WARNING: in.Subject requires manual conversion: does not exist in peer-type + return nil +} + +func autoConvert_v1beta1_Subject_To_v1alpha1_Subject(in *Subject, out *v1alpha1.Subject, s conversion.Scope) error { + // WARNING: in.BaseSubject requires manual conversion: does not exist in peer-type + out.OrganizationUnits = *(*[]string)(unsafe.Pointer(&in.OrganizationUnits)) + return nil +} + +func autoConvert_v1alpha1_Subject_To_v1beta1_Subject(in *v1alpha1.Subject, out *Subject, s conversion.Scope) error { + // WARNING: in.User requires manual conversion: does not exist in peer-type + // WARNING: in.Groups requires manual conversion: does not exist in peer-type + out.OrganizationUnits = *(*[]string)(unsafe.Pointer(&in.OrganizationUnits)) + return nil +} diff --git a/vendor/open-cluster-management.io/api/addon/v1beta1/zz_generated.register.go b/vendor/open-cluster-management.io/api/addon/v1beta1/zz_generated.register.go new file mode 100644 index 000000000..1752074e6 --- /dev/null +++ b/vendor/open-cluster-management.io/api/addon/v1beta1/zz_generated.register.go @@ -0,0 +1,57 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright Contributors to the Open Cluster Management project +// Code generated by register-gen. DO NOT EDIT. + +package v1beta1 + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName specifies the group name used to register the objects. +const GroupName = "addon.open-cluster-management.io" + +// GroupVersion specifies the group and the version used to register the objects. +var GroupVersion = v1.GroupVersion{Group: GroupName, Version: "v1beta1"} + +// SchemeGroupVersion is group version used to register these objects +// Deprecated: use GroupVersion instead. +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. + SchemeBuilder runtime.SchemeBuilder + localSchemeBuilder = &SchemeBuilder + // Deprecated: use Install instead + AddToScheme = localSchemeBuilder.AddToScheme + Install = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addKnownTypes) +} + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &ClusterManagementAddOn{}, + &ClusterManagementAddOnList{}, + &ManagedClusterAddOn{}, + &ManagedClusterAddOnList{}, + ) + // AddToGroupVersion allows the serialization of client types like ListOptions. + v1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/open-cluster-management.io/api/cluster/v1/doc.go b/vendor/open-cluster-management.io/api/cluster/v1/doc.go index 67138dc2e..6b51e091e 100644 --- a/vendor/open-cluster-management.io/api/cluster/v1/doc.go +++ b/vendor/open-cluster-management.io/api/cluster/v1/doc.go @@ -1,8 +1,7 @@ // Copyright Contributors to the Open Cluster Management project // Package v1 contains API Schema definitions for the cluster v1 API group -// +k8s:deepcopy-gen=package,register -// +k8s:openapi-gen=true +// +k8s:deepcopy-gen=package,register // +kubebuilder:validation:Optional // +groupName=cluster.open-cluster-management.io package v1 diff --git a/vendor/open-cluster-management.io/api/cluster/v1/register.go b/vendor/open-cluster-management.io/api/cluster/v1/register.go deleted file mode 100644 index 95074d323..000000000 --- a/vendor/open-cluster-management.io/api/cluster/v1/register.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright Contributors to the Open Cluster Management project -package v1 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -var ( - GroupName = "cluster.open-cluster-management.io" - GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"} - schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) - // Install is a function which adds this version to a scheme - Install = schemeBuilder.AddToScheme - - // SchemeGroupVersion generated code relies on this name - // Deprecated - SchemeGroupVersion = GroupVersion - // AddToScheme exists solely to keep the old generators creating valid code - // DEPRECATED - AddToScheme = schemeBuilder.AddToScheme -) - -// Resource generated code relies on this being here, but it logically belongs to the group -// DEPRECATED -func Resource(resource string) schema.GroupResource { - return schema.GroupResource{Group: GroupName, Resource: resource} -} - -// Adds the list of known types to api.Scheme. -func addKnownTypes(scheme *runtime.Scheme) error { - scheme.AddKnownTypes(GroupVersion, - &ManagedCluster{}, - &ManagedClusterList{}, - ) - metav1.AddToGroupVersion(scheme, GroupVersion) - return nil -} diff --git a/vendor/open-cluster-management.io/api/cluster/v1/zz_generated.register.go b/vendor/open-cluster-management.io/api/cluster/v1/zz_generated.register.go new file mode 100644 index 000000000..2daa4676a --- /dev/null +++ b/vendor/open-cluster-management.io/api/cluster/v1/zz_generated.register.go @@ -0,0 +1,55 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright Contributors to the Open Cluster Management project +// Code generated by register-gen. DO NOT EDIT. + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName specifies the group name used to register the objects. +const GroupName = "cluster.open-cluster-management.io" + +// GroupVersion specifies the group and the version used to register the objects. +var GroupVersion = metav1.GroupVersion{Group: GroupName, Version: "v1"} + +// SchemeGroupVersion is group version used to register these objects +// Deprecated: use GroupVersion instead. +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. + SchemeBuilder runtime.SchemeBuilder + localSchemeBuilder = &SchemeBuilder + // Deprecated: use Install instead + AddToScheme = localSchemeBuilder.AddToScheme + Install = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addKnownTypes) +} + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &ManagedCluster{}, + &ManagedClusterList{}, + ) + // AddToGroupVersion allows the serialization of client types like ListOptions. + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/open-cluster-management.io/api/cluster/v1alpha1/doc.go b/vendor/open-cluster-management.io/api/cluster/v1alpha1/doc.go index d9b82a576..4e010e720 100644 --- a/vendor/open-cluster-management.io/api/cluster/v1alpha1/doc.go +++ b/vendor/open-cluster-management.io/api/cluster/v1alpha1/doc.go @@ -1,8 +1,7 @@ // Copyright Contributors to the Open Cluster Management project // Package v1alpha1 contains API Schema definitions for the cluster v1alpha1 API group -// +k8s:deepcopy-gen=package,register -// +k8s:openapi-gen=true +// +k8s:deepcopy-gen=package,register // +kubebuilder:validation:Optional // +groupName=cluster.open-cluster-management.io package v1alpha1 diff --git a/vendor/open-cluster-management.io/api/cluster/v1alpha1/register.go b/vendor/open-cluster-management.io/api/cluster/v1alpha1/register.go deleted file mode 100644 index 94c2a2323..000000000 --- a/vendor/open-cluster-management.io/api/cluster/v1alpha1/register.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright Contributors to the Open Cluster Management project -package v1alpha1 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -var ( - GroupName = "cluster.open-cluster-management.io" - GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} - schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) - // Install is a function which adds this version to a scheme - Install = schemeBuilder.AddToScheme - - // SchemeGroupVersion generated code relies on this name - // Deprecated - SchemeGroupVersion = GroupVersion - // AddToScheme exists solely to keep the old generators creating valid code - // DEPRECATED - AddToScheme = schemeBuilder.AddToScheme -) - -// Resource generated code relies on this being here, but it logically belongs to the group -// DEPRECATED -func Resource(resource string) schema.GroupResource { - return schema.GroupResource{Group: GroupName, Resource: resource} -} - -// Adds the list of known types to api.Scheme. -func addKnownTypes(scheme *runtime.Scheme) error { - scheme.AddKnownTypes(GroupVersion, - &AddOnPlacementScore{}, - &AddOnPlacementScoreList{}, - &ClusterClaim{}, - &ClusterClaimList{}, - ) - metav1.AddToGroupVersion(scheme, GroupVersion) - return nil -} diff --git a/vendor/open-cluster-management.io/api/cluster/v1alpha1/zz_generated.register.go b/vendor/open-cluster-management.io/api/cluster/v1alpha1/zz_generated.register.go new file mode 100644 index 000000000..058dfd303 --- /dev/null +++ b/vendor/open-cluster-management.io/api/cluster/v1alpha1/zz_generated.register.go @@ -0,0 +1,57 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright Contributors to the Open Cluster Management project +// Code generated by register-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName specifies the group name used to register the objects. +const GroupName = "cluster.open-cluster-management.io" + +// GroupVersion specifies the group and the version used to register the objects. +var GroupVersion = v1.GroupVersion{Group: GroupName, Version: "v1alpha1"} + +// SchemeGroupVersion is group version used to register these objects +// Deprecated: use GroupVersion instead. +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. + SchemeBuilder runtime.SchemeBuilder + localSchemeBuilder = &SchemeBuilder + // Deprecated: use Install instead + AddToScheme = localSchemeBuilder.AddToScheme + Install = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addKnownTypes) +} + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &AddOnPlacementScore{}, + &AddOnPlacementScoreList{}, + &ClusterClaim{}, + &ClusterClaimList{}, + ) + // AddToGroupVersion allows the serialization of client types like ListOptions. + v1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/open-cluster-management.io/api/cluster/v1beta1/doc.go b/vendor/open-cluster-management.io/api/cluster/v1beta1/doc.go index 8cbd8b29e..537dae4e7 100644 --- a/vendor/open-cluster-management.io/api/cluster/v1beta1/doc.go +++ b/vendor/open-cluster-management.io/api/cluster/v1beta1/doc.go @@ -1,8 +1,7 @@ // Copyright Contributors to the Open Cluster Management project // Package v1beta1 contains API Schema definitions for the cluster v1beta1 API group -// +k8s:deepcopy-gen=package,register -// +k8s:openapi-gen=true +// +k8s:deepcopy-gen=package,register // +kubebuilder:validation:Optional // +groupName=cluster.open-cluster-management.io package v1beta1 diff --git a/vendor/open-cluster-management.io/api/cluster/v1beta1/register.go b/vendor/open-cluster-management.io/api/cluster/v1beta1/register.go deleted file mode 100644 index 665b5416b..000000000 --- a/vendor/open-cluster-management.io/api/cluster/v1beta1/register.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright Contributors to the Open Cluster Management project -package v1beta1 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -var ( - GroupName = "cluster.open-cluster-management.io" - GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"} - schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) - // Install is a function which adds this version to a scheme - Install = schemeBuilder.AddToScheme - - // SchemeGroupVersion generated code relies on this name - // Deprecated - SchemeGroupVersion = GroupVersion - // AddToScheme exists solely to keep the old generators creating valid code - // DEPRECATED - AddToScheme = schemeBuilder.AddToScheme -) - -// Resource generated code relies on this being here, but it logically belongs to the group -// DEPRECATED -func Resource(resource string) schema.GroupResource { - return schema.GroupResource{Group: GroupName, Resource: resource} -} - -// Adds the list of known types to api.Scheme. -func addKnownTypes(scheme *runtime.Scheme) error { - scheme.AddKnownTypes(GroupVersion, - &Placement{}, - &PlacementList{}, - &PlacementDecision{}, - &PlacementDecisionList{}, - ) - metav1.AddToGroupVersion(scheme, GroupVersion) - return nil -} diff --git a/vendor/open-cluster-management.io/api/cluster/v1beta1/zz_generated.register.go b/vendor/open-cluster-management.io/api/cluster/v1beta1/zz_generated.register.go new file mode 100644 index 000000000..4b482ab17 --- /dev/null +++ b/vendor/open-cluster-management.io/api/cluster/v1beta1/zz_generated.register.go @@ -0,0 +1,57 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright Contributors to the Open Cluster Management project +// Code generated by register-gen. DO NOT EDIT. + +package v1beta1 + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName specifies the group name used to register the objects. +const GroupName = "cluster.open-cluster-management.io" + +// GroupVersion specifies the group and the version used to register the objects. +var GroupVersion = v1.GroupVersion{Group: GroupName, Version: "v1beta1"} + +// SchemeGroupVersion is group version used to register these objects +// Deprecated: use GroupVersion instead. +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. + SchemeBuilder runtime.SchemeBuilder + localSchemeBuilder = &SchemeBuilder + // Deprecated: use Install instead + AddToScheme = localSchemeBuilder.AddToScheme + Install = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addKnownTypes) +} + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &Placement{}, + &PlacementDecision{}, + &PlacementDecisionList{}, + &PlacementList{}, + ) + // AddToGroupVersion allows the serialization of client types like ListOptions. + v1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/open-cluster-management.io/api/cluster/v1beta2/doc.go b/vendor/open-cluster-management.io/api/cluster/v1beta2/doc.go index 8b69005f8..6b19e7b7a 100644 --- a/vendor/open-cluster-management.io/api/cluster/v1beta2/doc.go +++ b/vendor/open-cluster-management.io/api/cluster/v1beta2/doc.go @@ -1,8 +1,8 @@ // Copyright Contributors to the Open Cluster Management project // Package v1beta2 contains API Schema definitions for the cluster v1beta2 API group + // +k8s:deepcopy-gen=package,register // +k8s:openapi-gen=true - // +kubebuilder:validation:Optional // +groupName=cluster.open-cluster-management.io package v1beta2 diff --git a/vendor/open-cluster-management.io/api/cluster/v1beta2/register.go b/vendor/open-cluster-management.io/api/cluster/v1beta2/register.go deleted file mode 100644 index 777e45229..000000000 --- a/vendor/open-cluster-management.io/api/cluster/v1beta2/register.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright Contributors to the Open Cluster Management project -package v1beta2 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -var ( - GroupName = "cluster.open-cluster-management.io" - GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta2"} - schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) - // Install is a function which adds this version to a scheme - Install = schemeBuilder.AddToScheme - - // SchemeGroupVersion generated code relies on this name - // Deprecated - SchemeGroupVersion = GroupVersion - // AddToScheme exists solely to keep the old generators creating valid code - // DEPRECATED - AddToScheme = schemeBuilder.AddToScheme -) - -// Resource generated code relies on this being here, but it logically belongs to the group -// DEPRECATED -func Resource(resource string) schema.GroupResource { - return schema.GroupResource{Group: GroupName, Resource: resource} -} - -// Adds the list of known types to api.Scheme. -func addKnownTypes(scheme *runtime.Scheme) error { - scheme.AddKnownTypes(GroupVersion, - &ManagedClusterSet{}, - &ManagedClusterSetList{}, - &ManagedClusterSetBinding{}, - &ManagedClusterSetBindingList{}, - ) - metav1.AddToGroupVersion(scheme, GroupVersion) - return nil -} diff --git a/vendor/open-cluster-management.io/api/cluster/v1beta2/zz_generated.register.go b/vendor/open-cluster-management.io/api/cluster/v1beta2/zz_generated.register.go new file mode 100644 index 000000000..a920daaf5 --- /dev/null +++ b/vendor/open-cluster-management.io/api/cluster/v1beta2/zz_generated.register.go @@ -0,0 +1,57 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright Contributors to the Open Cluster Management project +// Code generated by register-gen. DO NOT EDIT. + +package v1beta2 + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName specifies the group name used to register the objects. +const GroupName = "cluster.open-cluster-management.io" + +// GroupVersion specifies the group and the version used to register the objects. +var GroupVersion = v1.GroupVersion{Group: GroupName, Version: "v1beta2"} + +// SchemeGroupVersion is group version used to register these objects +// Deprecated: use GroupVersion instead. +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta2"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. + SchemeBuilder runtime.SchemeBuilder + localSchemeBuilder = &SchemeBuilder + // Deprecated: use Install instead + AddToScheme = localSchemeBuilder.AddToScheme + Install = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addKnownTypes) +} + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &ManagedClusterSet{}, + &ManagedClusterSetBinding{}, + &ManagedClusterSetBindingList{}, + &ManagedClusterSetList{}, + ) + // AddToGroupVersion allows the serialization of client types like ListOptions. + v1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/open-cluster-management.io/api/operator/v1/doc.go b/vendor/open-cluster-management.io/api/operator/v1/doc.go index 749c0e8f3..3565e3f82 100644 --- a/vendor/open-cluster-management.io/api/operator/v1/doc.go +++ b/vendor/open-cluster-management.io/api/operator/v1/doc.go @@ -1,8 +1,7 @@ // Copyright Contributors to the Open Cluster Management project // Package v1 contains API Schema definitions for the operator v1 API group -// +k8s:deepcopy-gen=package,register -// +k8s:openapi-gen=true +// +k8s:deepcopy-gen=package,register // +kubebuilder:validation:Optional // +groupName=operator.open-cluster-management.io package v1 diff --git a/vendor/open-cluster-management.io/api/operator/v1/register.go b/vendor/open-cluster-management.io/api/operator/v1/register.go deleted file mode 100644 index 895cfa788..000000000 --- a/vendor/open-cluster-management.io/api/operator/v1/register.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright Contributors to the Open Cluster Management project -package v1 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -var ( - GroupName = "operator.open-cluster-management.io" - GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"} - schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) - // Install is a function which adds this version to a scheme - Install = schemeBuilder.AddToScheme - - // SchemeGroupVersion generated code relies on this name - // Deprecated - SchemeGroupVersion = GroupVersion - // AddToScheme exists solely to keep the old generators creating valid code - // DEPRECATED - AddToScheme = schemeBuilder.AddToScheme -) - -// Resource generated code relies on this being here, but it logically belongs to the group -// DEPRECATED -func Resource(resource string) schema.GroupResource { - return schema.GroupResource{Group: GroupName, Resource: resource} -} - -// Adds the list of known types to api.Scheme. -func addKnownTypes(scheme *runtime.Scheme) error { - scheme.AddKnownTypes(GroupVersion, - &ClusterManager{}, - &ClusterManagerList{}, - &Klusterlet{}, - &KlusterletList{}) - metav1.AddToGroupVersion(scheme, GroupVersion) - return nil -} diff --git a/vendor/open-cluster-management.io/api/operator/v1/zz_generated.register.go b/vendor/open-cluster-management.io/api/operator/v1/zz_generated.register.go new file mode 100644 index 000000000..6b9c430ee --- /dev/null +++ b/vendor/open-cluster-management.io/api/operator/v1/zz_generated.register.go @@ -0,0 +1,57 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright Contributors to the Open Cluster Management project +// Code generated by register-gen. DO NOT EDIT. + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName specifies the group name used to register the objects. +const GroupName = "operator.open-cluster-management.io" + +// GroupVersion specifies the group and the version used to register the objects. +var GroupVersion = metav1.GroupVersion{Group: GroupName, Version: "v1"} + +// SchemeGroupVersion is group version used to register these objects +// Deprecated: use GroupVersion instead. +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. + SchemeBuilder runtime.SchemeBuilder + localSchemeBuilder = &SchemeBuilder + // Deprecated: use Install instead + AddToScheme = localSchemeBuilder.AddToScheme + Install = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addKnownTypes) +} + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &ClusterManager{}, + &ClusterManagerList{}, + &Klusterlet{}, + &KlusterletList{}, + ) + // AddToGroupVersion allows the serialization of client types like ListOptions. + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/open-cluster-management.io/api/work/v1/doc.go b/vendor/open-cluster-management.io/api/work/v1/doc.go index 19559fa00..7c611d3a8 100644 --- a/vendor/open-cluster-management.io/api/work/v1/doc.go +++ b/vendor/open-cluster-management.io/api/work/v1/doc.go @@ -1,8 +1,7 @@ // Copyright Contributors to the Open Cluster Management project // Package v1 contains API Schema definitions for the work v1 API group -// +k8s:deepcopy-gen=package,register -// +k8s:openapi-gen=true +// +k8s:deepcopy-gen=package,register // +kubebuilder:validation:Optional // +groupName=work.open-cluster-management.io package v1 diff --git a/vendor/open-cluster-management.io/api/work/v1/register.go b/vendor/open-cluster-management.io/api/work/v1/register.go deleted file mode 100644 index fc73a1037..000000000 --- a/vendor/open-cluster-management.io/api/work/v1/register.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright Contributors to the Open Cluster Management project -package v1 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -var ( - GroupName = "work.open-cluster-management.io" - GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"} - schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) - // Install is a function which adds this version to a scheme - Install = schemeBuilder.AddToScheme - - // SchemeGroupVersion generated code relies on this name - // Deprecated - SchemeGroupVersion = GroupVersion - // AddToScheme exists solely to keep the old generators creating valid code - // DEPRECATED - AddToScheme = schemeBuilder.AddToScheme -) - -// Resource generated code relies on this being here, but it logically belongs to the group -// DEPRECATED -func Resource(resource string) schema.GroupResource { - return schema.GroupResource{Group: GroupName, Resource: resource} -} - -// Adds the list of known types to api.Scheme. -func addKnownTypes(scheme *runtime.Scheme) error { - scheme.AddKnownTypes(GroupVersion, - &ManifestWork{}, - &ManifestWorkList{}, - &AppliedManifestWork{}, - &AppliedManifestWorkList{}, - ) - metav1.AddToGroupVersion(scheme, GroupVersion) - return nil -} diff --git a/vendor/open-cluster-management.io/api/work/v1/zz_generated.register.go b/vendor/open-cluster-management.io/api/work/v1/zz_generated.register.go new file mode 100644 index 000000000..8c61d7603 --- /dev/null +++ b/vendor/open-cluster-management.io/api/work/v1/zz_generated.register.go @@ -0,0 +1,57 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright Contributors to the Open Cluster Management project +// Code generated by register-gen. DO NOT EDIT. + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName specifies the group name used to register the objects. +const GroupName = "work.open-cluster-management.io" + +// GroupVersion specifies the group and the version used to register the objects. +var GroupVersion = metav1.GroupVersion{Group: GroupName, Version: "v1"} + +// SchemeGroupVersion is group version used to register these objects +// Deprecated: use GroupVersion instead. +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. + SchemeBuilder runtime.SchemeBuilder + localSchemeBuilder = &SchemeBuilder + // Deprecated: use Install instead + AddToScheme = localSchemeBuilder.AddToScheme + Install = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addKnownTypes) +} + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &AppliedManifestWork{}, + &AppliedManifestWorkList{}, + &ManifestWork{}, + &ManifestWorkList{}, + ) + // AddToGroupVersion allows the serialization of client types like ListOptions. + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/open-cluster-management.io/api/work/v1alpha1/doc.go b/vendor/open-cluster-management.io/api/work/v1alpha1/doc.go index 981a88e75..e79e3b818 100644 --- a/vendor/open-cluster-management.io/api/work/v1alpha1/doc.go +++ b/vendor/open-cluster-management.io/api/work/v1alpha1/doc.go @@ -1,8 +1,7 @@ // Copyright Contributors to the Open Cluster Management project // Package v1 contains API Schema definitions for the work v1 API group -// +k8s:deepcopy-gen=package,register -// +k8s:openapi-gen=true +// +k8s:deepcopy-gen=package,register // +kubebuilder:validation:Optional // +groupName=work.open-cluster-management.io package v1alpha1 diff --git a/vendor/open-cluster-management.io/api/work/v1alpha1/register.go b/vendor/open-cluster-management.io/api/work/v1alpha1/register.go deleted file mode 100644 index f49620450..000000000 --- a/vendor/open-cluster-management.io/api/work/v1alpha1/register.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright Contributors to the Open Cluster Management project -package v1alpha1 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -var ( - GroupName = "work.open-cluster-management.io" - GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} - schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) - // Install is a function which adds this version to a scheme - Install = schemeBuilder.AddToScheme - - // SchemeGroupVersion generated code relies on this name - // Deprecated - SchemeGroupVersion = GroupVersion - // AddToScheme exists solely to keep the old generators creating valid code - // DEPRECATED - AddToScheme = schemeBuilder.AddToScheme -) - -// Resource generated code relies on this being here, but it logically belongs to the group -// DEPRECATED -func Resource(resource string) schema.GroupResource { - return schema.GroupResource{Group: GroupName, Resource: resource} -} - -// Adds the list of known types to api.Scheme. -func addKnownTypes(scheme *runtime.Scheme) error { - scheme.AddKnownTypes(GroupVersion, - &ManifestWorkReplicaSet{}, - &ManifestWorkReplicaSetList{}, - ) - - metav1.AddToGroupVersion(scheme, GroupVersion) - return nil -} diff --git a/vendor/open-cluster-management.io/api/work/v1alpha1/zz_generated.register.go b/vendor/open-cluster-management.io/api/work/v1alpha1/zz_generated.register.go new file mode 100644 index 000000000..6e078c445 --- /dev/null +++ b/vendor/open-cluster-management.io/api/work/v1alpha1/zz_generated.register.go @@ -0,0 +1,55 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright Contributors to the Open Cluster Management project +// Code generated by register-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName specifies the group name used to register the objects. +const GroupName = "work.open-cluster-management.io" + +// GroupVersion specifies the group and the version used to register the objects. +var GroupVersion = v1.GroupVersion{Group: GroupName, Version: "v1alpha1"} + +// SchemeGroupVersion is group version used to register these objects +// Deprecated: use GroupVersion instead. +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. + SchemeBuilder runtime.SchemeBuilder + localSchemeBuilder = &SchemeBuilder + // Deprecated: use Install instead + AddToScheme = localSchemeBuilder.AddToScheme + Install = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addKnownTypes) +} + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &ManifestWorkReplicaSet{}, + &ManifestWorkReplicaSetList{}, + ) + // AddToGroupVersion allows the serialization of client types like ListOptions. + v1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +}