Add addon conversion webhook for v1alpha1/v1beta1 API migration (#1289)
Some checks failed
Post / images (amd64, addon-manager) (push) Failing after 46s
Post / images (amd64, placement) (push) Failing after 41s
Post / images (amd64, registration-operator) (push) Failing after 39s
Post / images (amd64, work) (push) Failing after 42s
Post / images (arm64, addon-manager) (push) Failing after 39s
Post / images (arm64, placement) (push) Failing after 39s
Post / images (arm64, registration) (push) Failing after 40s
Post / images (arm64, registration-operator) (push) Failing after 42s
Post / images (arm64, work) (push) Failing after 39s
Post / images (amd64, registration) (push) Failing after 7m46s
Post / image manifest (addon-manager) (push) Has been skipped
Post / image manifest (placement) (push) Has been skipped
Post / image manifest (registration) (push) Has been skipped
Post / image manifest (registration-operator) (push) Has been skipped
Post / image manifest (work) (push) Has been skipped
Post / trigger clusteradm e2e (push) Has been skipped
Post / coverage (push) Failing after 14m33s
Scorecard supply-chain security / Scorecard analysis (push) Failing after 1m25s
Close stale issues and PRs / stale (push) Successful in 46s

* Add addon conversion webhook for v1alpha1/v1beta1 API migration

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Qing Hao <qhao@redhat.com>

* Fix GroupVersion compatibility issues after API dependency update

This commit fixes compilation and test errors introduced by updating
the API dependency to use native conversion functions from PR #411.

Changes include:

1. Fix GroupVersion type mismatches across the codebase:
   - Updated OwnerReference creation to use schema.GroupVersion
   - Fixed webhook scheme registration to use proper GroupVersion type
   - Applied fixes to addon, placement, migration, work, and registration controllers

2. Enhance addon conversion webhook:
   - Use native API conversion functions from addon/v1beta1/conversion.go
   - Fix InstallNamespace annotation key to match expected format
   - Add custom logic to populate deprecated ConfigReferent field in ConfigReferences
   - Properly preserve annotations during v1alpha1 <-> v1beta1 conversion

3. Remove duplicate conversion code:
   - Deleted pkg/addon/webhook/conversion/ directory (~500 lines)
   - Now using native conversion functions from the API repository

4. Patch vendored addon-framework:
   - Fixed GroupVersion errors in agentdeploy utils

All unit tests pass successfully (97 packages, 0 failures).

Signed-off-by: Qing Hao <qhao@redhat.com>

---------

Signed-off-by: Qing Hao <qhao@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Qing Hao
2025-12-24 16:26:35 +08:00
committed by GitHub
parent 13aec02a58
commit c516beffa6
80 changed files with 5231 additions and 453 deletions

View File

@@ -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

View File

@@ -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
}

View File

@@ -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"

View File

@@ -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"

View File

@@ -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

View File

@@ -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

4
go.mod
View File

@@ -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

8
go.sum
View File

@@ -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=

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,5 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: addon-webhook-sa
namespace: {{ .ClusterManagerNamespace }}

View File

@@ -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: ""

View File

@@ -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: ""

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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{})

View File

@@ -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) {

4
pkg/addon/webhook/doc.go Normal file
View File

@@ -0,0 +1,4 @@
// Copyright Contributors to the Open Cluster Management project
// Package webhook implements the webhook server for addon APIs
package webhook

View File

@@ -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
}

View File

@@ -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() {}

View File

@@ -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() {}

View File

@@ -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()
}

View File

@@ -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
}

View File

@@ -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)
}
})
}
}

View File

@@ -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
}

View File

@@ -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)
}
})
}
}

View File

@@ -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()
}

31
pkg/cmd/webhook/addon.go Normal file
View File

@@ -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
}

View File

@@ -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)
}
}

View File

@@ -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

View File

@@ -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{

View File

@@ -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(),
}

View File

@@ -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.

View File

@@ -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",

View File

@@ -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 {

View File

@@ -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{

View File

@@ -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,
}

View File

@@ -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)

View File

@@ -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,

View File

@@ -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
}

View File

@@ -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,
}

View File

@@ -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"))
})
})

View File

@@ -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{})
}

View File

@@ -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{})
}

View File

@@ -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)

View File

@@ -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)

4
vendor/modules.txt vendored
View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
}