Merge pull request #24 from qiujian16/mdelder-adopt-api-1

adopt new operator api
This commit is contained in:
OpenShift Merge Robot
2020-06-03 15:32:37 +02:00
committed by GitHub
490 changed files with 52846 additions and 103171 deletions

View File

@@ -40,13 +40,13 @@ ifeq ($(GOHOSTOS),darwin)
endif
endif
$(call add-bindata,hub,./manifests/hub/...,bindata,bindata,./pkg/operators/hub/bindata/bindata.go)
$(call add-bindata,spoke,./manifests/spoke/...,bindata,bindata,./pkg/operators/spoke/bindata/bindata.go)
$(call add-bindata,cluster-manager,./manifests/cluster-manager/...,bindata,bindata,./pkg/operators/clustermanager/bindata/bindata.go)
$(call add-bindata,klusterlet,./manifests/klusterlet/...,bindata,bindata,./pkg/operators/klusterlet/bindata/bindata.go)
copy-crd:
bash -x hack/copy-crds.sh
update-all: copy-crd update-bindata-hub update-bindata-spoke update-csv
update-all: copy-crd update-bindata-cluster-manager update-bindata-klusterlet update-csv
verify-crds:
bash -x hack/verify-crds.sh
@@ -54,22 +54,22 @@ verify-crds:
verify: verify-crds
update-csv: ensure-operator-sdk
$(OPERATOR_SDK) generate csv --crd-dir=deploy/nucleus-hub/crds --deploy-dir=deploy/nucleus-hub --output-dir=deploy/nucleus-hub/olm-catalog/nucleus-hub --operator-name=nucleus-hub --csv-version=0.1.0
$(OPERATOR_SDK) generate csv --crd-dir=deploy/nucleus-spoke/crds --deploy-dir=deploy/nucleus-spoke --output-dir=deploy/nucleus-spoke/olm-catalog/nucleus-spoke --operator-name=nucleus-spoke --csv-version=0.1.0
$(OPERATOR_SDK) generate csv --crd-dir=deploy/cluster-manager/crds --deploy-dir=deploy/cluster-manager --output-dir=deploy/cluster-manager/olm-catalog/cluster-manager --operator-name=cluster-manager --csv-version=0.1.0
$(OPERATOR_SDK) generate csv --crd-dir=deploy/klusterlet/crds --deploy-dir=deploy/klusterlet --output-dir=deploy/klusterlet/olm-catalog/klusterlet --operator-name=klusterlet --csv-version=0.1.0
munge-hub-csv:
mkdir -p munge-csv
cp deploy/nucleus-hub/olm-catalog/nucleus-hub/manifests/nucleus-hub.clusterserviceversion.yaml munge-csv/nucleus-hub.clusterserviceversion.yaml.unmunged
sed -e "s,quay.io/open-cluster-management/nucleus:latest,$(IMAGE_NAME)," -i deploy/nucleus-hub/olm-catalog/nucleus-hub/manifests/nucleus-hub.clusterserviceversion.yaml
cp deploy/cluster-manager/olm-catalog/cluster-manager/manifests/cluster-manager.clusterserviceversion.yaml munge-csv/cluster-manager.clusterserviceversion.yaml.unmunged
sed -e "s,quay.io/open-cluster-management/nucleus:latest,$(IMAGE_NAME)," -i deploy/cluster-manager/olm-catalog/cluster-manager/manifests/cluster-manager.clusterserviceversion.yaml
munge-spoke-csv:
mkdir -p munge-csv
cp deploy/nucleus-spoke/olm-catalog/nucleus-spoke/manifests/nucleus-spoke.clusterserviceversion.yaml munge-csv/nucleus-spoke.clusterserviceversion.yaml.unmunged
sed -e "s,quay.io/open-cluster-management/nucleus:latest,$(IMAGE_NAME)," -i deploy/nucleus-spoke/olm-catalog/nucleus-spoke/manifests/nucleus-spoke.clusterserviceversion.yaml
cp deploy/klusterlet/olm-catalog/klusterlet/manifests/klusterlet.clusterserviceversion.yaml munge-csv/klusterlet.clusterserviceversion.yaml.unmunged
sed -e "s,quay.io/open-cluster-management/nucleus:latest,$(IMAGE_NAME)," -i deploy/klusterlet/olm-catalog/klusterlet/manifests/klusterlet.clusterserviceversion.yaml
unmunge-csv:
mv munge-csv/nucleus-hub.clusterserviceversion.yaml.unmunged deploy/nucleus-hub/olm-catalog/nucleus-hub/manifests/nucleus-hub.clusterserviceversion.yaml
mv munge-csv/nucleus-spoke.clusterserviceversion.yaml.unmunged deploy/nucleus-spoke/olm-catalog/nucleus-spoke/manifests/nucleus-spoke.clusterserviceversion.yaml
mv munge-csv/cluster-manager.clusterserviceversion.yaml.unmunged deploy/cluster-manager/olm-catalog/cluster-manager/manifests/cluster-manager.clusterserviceversion.yaml
mv munge-csv/klusterlet.clusterserviceversion.yaml.unmunged deploy/klusterlet/olm-catalog/klusterlet/manifests/klusterlet.clusterserviceversion.yaml
deploy: install-olm deploy-hub deploy-spoke unmunge-csv
@@ -80,22 +80,22 @@ install-olm: ensure-operator-sdk
$(KUBECTL) get ns open-cluster-management ; if [ $$? -ne 0 ] ; then $(KUBECTL) create ns open-cluster-management ; fi
deploy-hub: install-olm munge-hub-csv
$(OPERATOR_SDK) run --olm --operator-namespace open-cluster-management --operator-version 0.1.0 --manifests deploy/nucleus-hub/olm-catalog/nucleus-hub --olm-namespace $(OLM_NAMESPACE)
sed -e "s,quay.io/open-cluster-management/registration,$(REGISTRATION_IMAGE)," deploy/nucleus-hub/crds/nucleus_open-cluster-management_hubcores.cr.yaml | $(KUBECTL) apply -f -
$(OPERATOR_SDK) run --olm --operator-namespace open-cluster-management --operator-version 0.1.0 --manifests deploy/cluster-manager/olm-catalog/cluster-manager --olm-namespace $(OLM_NAMESPACE) --timeout 10m
sed -e "s,quay.io/open-cluster-management/registration,$(REGISTRATION_IMAGE)," deploy/cluster-manager/crds/operator_open-cluster-management_clustermanagers.cr.yaml | $(KUBECTL) apply -f -
clean-hub: ensure-operator-sdk
$(KUBECTL) delete -f deploy/nucleus-hub/crds/nucleus_open-cluster-management_hubcores.cr.yaml --ignore-not-found
$(OPERATOR_SDK) cleanup --olm --operator-namespace open-cluster-management --operator-version 0.1.0 --manifests deploy/nucleus-hub/olm-catalog/nucleus-hub --olm-namespace $(OLM_NAMESPACE)
$(KUBECTL) delete -f deploy/cluster-manager/crds/operator_open-cluster-management_clustermanagers.cr.yaml --ignore-not-found
$(OPERATOR_SDK) cleanup --olm --operator-namespace open-cluster-management --operator-version 0.1.0 --manifests deploy/cluster-manager/olm-catalog/cluster-manager --olm-namespace $(OLM_NAMESPACE) --timeout 10m
cluster-ip:
cluster-ip:
CLUSTER_IP?=$(shell $(KUBECTL) get svc kubernetes -n default -o jsonpath="{.spec.clusterIP}")
bootstrap-secret: cluster-ip
$(KUBECTL) get ns open-cluster-management-spoke ; if [ $$? -ne 0 ] ; then $(KUBECTL) create ns open-cluster-management-spoke ; fi
$(KUBECTL) get ns open-cluster-management-agent ; if [ $$? -ne 0 ] ; then $(KUBECTL) create ns open-cluster-management-agent ; fi
cp $(KUBECONFIG) dev-kubeconfig
$(KUBECTL) config set clusters.kind-kind.server https://$(CLUSTER_IP) --kubeconfig dev-kubeconfig
$(KUBECTL) delete secret bootstrap-hub-kubeconfig -n open-cluster-management-spoke --ignore-not-found
$(KUBECTL) create secret generic bootstrap-hub-kubeconfig --from-file=kubeconfig=dev-kubeconfig -n open-cluster-management-spoke
$(KUBECTL) delete secret bootstrap-hub-kubeconfig -n open-cluster-management-agent --ignore-not-found
$(KUBECTL) create secret generic bootstrap-hub-kubeconfig --from-file=kubeconfig=dev-kubeconfig -n open-cluster-management-agent
# Registration e2e expects to read bootstrap secret from open-cluster-management/e2e-bootstrap-secret
# TODO: think about how to factor this
@@ -106,12 +106,12 @@ e2e-bootstrap-secret: cluster-ip
$(KUBECTL) create secret generic e2e-bootstrap-secret --from-file=kubeconfig=e2e-kubeconfig -n open-cluster-management
deploy-spoke: install-olm munge-spoke-csv bootstrap-secret
$(OPERATOR_SDK) run --olm --operator-namespace open-cluster-management --operator-version 0.1.0 --manifests deploy/nucleus-spoke/olm-catalog/nucleus-spoke --olm-namespace $(OLM_NAMESPACE)
sed -e "s,quay.io/open-cluster-management/registration,$(REGISTRATION_IMAGE)," -e "s,quay.io/open-cluster-management/work,$(WORK_IMAGE)," deploy/nucleus-spoke/crds/nucleus_open-cluster-management_spokecores.cr.yaml | $(KUBECTL) apply -f -
$(OPERATOR_SDK) run --olm --operator-namespace open-cluster-management --operator-version 0.1.0 --manifests deploy/klusterlet/olm-catalog/klusterlet --olm-namespace $(OLM_NAMESPACE) --timeout 10m
sed -e "s,quay.io/open-cluster-management/registration,$(REGISTRATION_IMAGE)," -e "s,quay.io/open-cluster-management/work,$(WORK_IMAGE)," deploy/klusterlet/crds/operator_open-cluster-management_klusterlets.cr.yaml | $(KUBECTL) apply -f -
clean-spoke: ensure-operator-sdk
$(KUBECTL) delete -f deploy/nucleus-spoke/crds/nucleus_open-cluster-management_spokecores.cr.yaml --ignore-not-found
$(OPERATOR_SDK) cleanup --olm --operator-namespace open-cluster-management --operator-version 0.1.0 --manifests deploy/nucleus-spoke/olm-catalog/nucleus-spoke --olm-namespace $(OLM_NAMESPACE)
$(KUBECTL) delete -f deploy/klusterlet/crds/operator_open-cluster-management_klusterlets.cr.yaml --ignore-not-found
$(OPERATOR_SDK) cleanup --olm --operator-namespace open-cluster-management --operator-version 0.1.0 --manifests deploy/klusterlet/olm-catalog/klusterlet --olm-namespace $(OLM_NAMESPACE) --timeout 10m
ensure-operator-sdk:
ifeq "" "$(wildcard $(OPERATOR_SDK))"

View File

@@ -1,9 +1,9 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: nucleus-hub
name: cluster-manager
rules:
# Allow nucleus to create workload
# Allow the nucleus to create workload
- apiGroups: [""]
resources: ["configmaps", "namespaces", "serviceaccounts", "services", "secrets"]
verbs: ["create", "get", "list", "update", "watch", "patch", "delete"]
@@ -22,22 +22,22 @@ rules:
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["clusterroles", "roles"]
verbs: ["create", "get", "list", "update", "watch", "patch", "delete", "escalate", "bind"]
# Allow nucleus to create crds
# Allow the nucleus to create crds
- apiGroups: ["apiextensions.k8s.io"]
resources: ["customresourcedefinitions"]
verbs: ["create", "get", "list", "update", "watch", "patch", "delete"]
# Allow nucleus to create apiservice
# Allow the nucleus to create apiservice
- apiGroups: ["apiregistration.k8s.io"]
resources: ["apiservices"]
verbs: ["create", "get", "list", "update", "watch", "patch", "delete"]
# Allow nucleus to create validatingwebhookconfigurration
# Allow the nucleus to create validatingwebhookconfigurration
- apiGroups: ["admissionregistration.k8s.io"]
resources: ["validatingwebhookconfigurations"]
verbs: ["create", "get", "list", "update", "watch", "patch", "delete"]
# Allow nuclues to manage nucleus apis.
- apiGroups: ["nucleus.open-cluster-management.io"]
resources: ["hubcores"]
# Allow the nuclues to manage clustermanager apis.
- apiGroups: ["operator.open-cluster-management.io"]
resources: ["clustermanagers"]
verbs: ["get", "list", "watch", "update", "delete"]
- apiGroups: ["nucleus.open-cluster-management.io"]
resources: ["hubcores/status"]
- apiGroups: ["operator.open-cluster-management.io"]
resources: ["clustermanagers/status"]
verbs: ["update", "patch"]

View File

@@ -1,12 +1,12 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: nucleus-spoke
name: cluster-manager
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: nucleus-spoke
name: cluster-manager
subjects:
- kind: ServiceAccount
name: nucleus-spoke
name: cluster-manager
namespace: open-cluster-management

View File

@@ -2,21 +2,22 @@ apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
creationTimestamp: null
name: hubcores.nucleus.open-cluster-management.io
name: clustermanagers.operator.open-cluster-management.io
spec:
group: nucleus.open-cluster-management.io
group: operator.open-cluster-management.io
names:
kind: HubCore
listKind: HubCoreList
plural: hubcores
singular: hubcore
kind: ClusterManager
listKind: ClusterManagerList
plural: clustermanagers
singular: clustermanager
scope: Cluster
subresources:
status: {}
validation:
openAPIV3Schema:
description: HubCore represents a deployment of nucleus hub core component.
HubCore will be only deployed in open-cluster-management namespace.
description: ClusterManager configures the controllers on the hub that govern
registration and work distribution for attached klusterlets. ClusterManager
will be only deployed in open-cluster-management-hub namespace.
type: object
properties:
apiVersion:
@@ -32,8 +33,8 @@ spec:
metadata:
type: object
spec:
description: Spec represents a desired deployment configuration of nucleus
hub
description: Spec represents a desired deployment configuration of controllers
that govern registration and work distribution for attached klusterlets.
type: object
properties:
registrationImagePullSpec:
@@ -41,15 +42,16 @@ spec:
of registration controller installed on hub.
type: string
status:
description: Status represents the current status of nucleus hub
description: Status represents the current status of controllers that govern
the lifecycle of managed clusters.
type: object
properties:
conditions:
description: 'Conditions contain the different condition statuses for
this hubcore. Valid condition types are: Applied: components in hub
is applied. Available: components in hub are available and ready to
serve. Progressing: components in hub are in a transitioning state.
Degraded: components in hub do not match the desired configuration
this ClusterManager. Valid condition types are: Applied: components
in hub are applied. Available: components in hub are available and
ready to serve. Progressing: components in hub are in a transitioning
state. Degraded: components in hub do not match the desired configuration
and only provide degraded service.'
type: array
items:
@@ -81,6 +83,7 @@ spec:
- name: v1
served: true
storage: true
preserveUnknownFields: false
status:
acceptedNames:
kind: ""

View File

@@ -0,0 +1,6 @@
apiVersion: operator.open-cluster-management.io/v1
kind: ClusterManager
metadata:
name: cluster-manager
spec:
registrationImagePullSpec: quay.io/open-cluster-management/registration

View File

@@ -2,21 +2,22 @@ apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
creationTimestamp: null
name: hubcores.nucleus.open-cluster-management.io
name: clustermanagers.operator.open-cluster-management.io
spec:
group: nucleus.open-cluster-management.io
group: operator.open-cluster-management.io
names:
kind: HubCore
listKind: HubCoreList
plural: hubcores
singular: hubcore
kind: ClusterManager
listKind: ClusterManagerList
plural: clustermanagers
singular: clustermanager
scope: Cluster
subresources:
status: {}
validation:
openAPIV3Schema:
description: HubCore represents a deployment of nucleus hub core component.
HubCore will be only deployed in open-cluster-management namespace.
description: ClusterManager configures the controllers on the hub that govern
registration and work distribution for attached klusterlets. ClusterManager
will be only deployed in open-cluster-management-hub namespace.
type: object
properties:
apiVersion:
@@ -32,8 +33,8 @@ spec:
metadata:
type: object
spec:
description: Spec represents a desired deployment configuration of nucleus
hub
description: Spec represents a desired deployment configuration of controllers
that govern registration and work distribution for attached klusterlets.
type: object
properties:
registrationImagePullSpec:
@@ -41,15 +42,16 @@ spec:
of registration controller installed on hub.
type: string
status:
description: Status represents the current status of nucleus hub
description: Status represents the current status of controllers that govern
the lifecycle of managed clusters.
type: object
properties:
conditions:
description: 'Conditions contain the different condition statuses for
this hubcore. Valid condition types are: Applied: components in hub
is applied. Available: components in hub are available and ready to
serve. Progressing: components in hub are in a transitioning state.
Degraded: components in hub do not match the desired configuration
this ClusterManager. Valid condition types are: Applied: components
in hub are applied. Available: components in hub are available and
ready to serve. Progressing: components in hub are in a transitioning
state. Degraded: components in hub do not match the desired configuration
and only provide degraded service.'
type: array
items:
@@ -81,6 +83,7 @@ spec:
- name: v1
served: true
storage: true
preserveUnknownFields: false
status:
acceptedNames:
kind: ""

View File

@@ -5,10 +5,10 @@ metadata:
alm-examples: |-
[
{
"apiVersion": "nucleus.open-cluster-management.io/v1",
"kind": "HubCore",
"apiVersion": "operator.open-cluster-management.io/v1",
"kind": "ClusterManager",
"metadata": {
"name": "hub"
"name": "cluster-manager"
},
"spec": {
"registrationImagePullSpec": "quay.io/open-cluster-management/registration"
@@ -16,16 +16,16 @@ metadata:
}
]
capabilities: Basic Install
name: nucleus-hub.v0.1.0
name: cluster-manager.v0.1.0
namespace: placeholder
spec:
apiservicedefinitions: {}
customresourcedefinitions:
owned:
- kind: HubCore
name: hubcores.nucleus.open-cluster-management.io
- kind: ClusterManager
name: clustermanagers.operator.open-cluster-management.io
version: v1
displayName: Nucleus Hub
displayName: Cluster Manager
icon:
- base64data: ""
mediatype: ""
@@ -141,9 +141,9 @@ spec:
- patch
- delete
- apiGroups:
- nucleus.open-cluster-management.io
- operator.open-cluster-management.io
resources:
- hubcores
- clustermanagers
verbs:
- get
- list
@@ -151,25 +151,25 @@ spec:
- update
- delete
- apiGroups:
- nucleus.open-cluster-management.io
- operator.open-cluster-management.io
resources:
- hubcores/status
- clustermanagers/status
verbs:
- update
- patch
serviceAccountName: nucleus-hub
serviceAccountName: cluster-manager
deployments:
- name: nucleus-hub
- name: cluster-manager
spec:
replicas: 3
selector:
matchLabels:
app: nucleus-hub
app: cluster-manager
strategy: {}
template:
metadata:
labels:
app: nucleus-hub
app: cluster-manager
spec:
containers:
- args:
@@ -192,7 +192,7 @@ spec:
scheme: HTTPS
initialDelaySeconds: 2
resources: {}
serviceAccountName: nucleus-hub
serviceAccountName: cluster-manager
strategy: deployment
installModes:
- supported: true

View File

@@ -0,0 +1,7 @@
annotations:
operators.operatorframework.io.bundle.channel.default.v1: stable
operators.operatorframework.io.bundle.channels.v1: stable
operators.operatorframework.io.bundle.manifests.v1: manifests/
operators.operatorframework.io.bundle.mediatype.v1: registry+v1
operators.operatorframework.io.bundle.metadata.v1: metadata/
operators.operatorframework.io.bundle.package.v1: cluster-manager

View File

@@ -1,21 +1,21 @@
kind: Deployment
apiVersion: apps/v1
metadata:
name: nucleus-hub
name: cluster-manager
namespace: open-cluster-management
labels:
app: nucleus-hub
app: cluster-manager
spec:
replicas: 3
selector:
matchLabels:
app: nucleus-hub
app: cluster-manager
template:
metadata:
labels:
app: nucleus-hub
app: cluster-manager
spec:
serviceAccountName: nucleus-hub
serviceAccountName: cluster-manager
containers:
- name: nucleus-operator
image: quay.io/open-cluster-management/nucleus:latest

View File

@@ -1,5 +1,5 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: nucleus-spoke
name: cluster-manager
namespace: open-cluster-management

View File

@@ -1,9 +1,9 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: nucleus-spoke
name: klusterlet
rules:
# Allow nucleus to create workload
# Allow the nucleus to create workload
- apiGroups: [""]
resources: ["secrets", "configmaps", "serviceaccounts"]
verbs: ["create", "get", "list", "update", "watch", "patch", "delete"]
@@ -25,10 +25,10 @@ rules:
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["clusterroles", "roles"]
verbs: ["create", "get", "list", "update", "watch", "patch", "delete", "escalate", "bind"]
# Allow nucleus to manage nucleus apis.
- apiGroups: ["nucleus.open-cluster-management.io"]
resources: ["spokecores"]
# Allow the nucleus to manage klusterlet apis.
- apiGroups: ["operator.open-cluster-management.io"]
resources: ["klusterlets"]
verbs: ["get", "list", "watch", "update", "patch", "delete"]
- apiGroups: ["nucleus.open-cluster-management.io"]
resources: ["spokecores/status"]
- apiGroups: ["operator.open-cluster-management.io"]
resources: ["klusterlets/status"]
verbs: ["update", "patch"]

View File

@@ -1,12 +1,12 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: nucleus-hub
name: klusterlet
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: nucleus-hub
name: klusterlet
subjects:
- kind: ServiceAccount
name: nucleus-hub
name: klusterlet
namespace: open-cluster-management

View File

@@ -2,23 +2,23 @@ apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
creationTimestamp: null
name: spokecores.nucleus.open-cluster-management.io
name: klusterlets.operator.open-cluster-management.io
spec:
group: nucleus.open-cluster-management.io
group: operator.open-cluster-management.io
names:
kind: SpokeCore
listKind: SpokeCoreList
plural: spokecores
singular: spokecore
kind: Klusterlet
listKind: KlusterletList
plural: klusterlets
singular: klusterlet
scope: Cluster
subresources:
status: {}
validation:
openAPIV3Schema:
description: SpokeCore represents a deployment of nucleus core agent on spoke
cluster. When the deployment of spoke core agent is deployed, it will requires
a secret with the name of bootstrap-hub-kubeconfig in the namespace defined
in the spec.
description: Klusterlet represents controllers on the managed cluster. When
configured, the Klusterlet requires a secret named of bootstrap-hub-kubeconfig
in the same namespace to allow API requests to the hub for the registration
protocol.
type: object
properties:
apiVersion:
@@ -34,7 +34,7 @@ spec:
metadata:
type: object
spec:
description: Spec represents the desired deployment configuratioin of nucleus
description: Spec represents the desired deployment configuration of klusterlet
agent.
type: object
properties:
@@ -65,7 +65,7 @@ spec:
namespace:
description: Namespace is the namespace to deploy the agent. The namespace
must have a prefix of "open-cluster-management-", and if it is not
set, the namespace of "open-cluster-management" is used to deploy
set, the namespace of "open-cluster-management-spoke" is used to deploy
agent.
type: string
registrationImagePullSpec:
@@ -77,7 +77,7 @@ spec:
of work agent.
type: string
status:
description: Status represents the current status of nucleus agent.
description: Status represents the current status of klusterlet agent.
type: object
properties:
conditions:
@@ -117,6 +117,7 @@ spec:
- name: v1
served: true
storage: true
preserveUnknownFields: false
status:
acceptedNames:
kind: ""

View File

@@ -1,11 +1,11 @@
apiVersion: nucleus.open-cluster-management.io/v1
kind: SpokeCore
apiVersion: operator.open-cluster-management.io/v1
kind: Klusterlet
metadata:
name: spoke
name: klusterlet
spec:
registrationImagePullSpec: quay.io/open-cluster-management/registration
workImagePullSpec: quay.io/open-cluster-management/work
clusterName: cluster1
namespace: open-cluster-management-spoke
namespace: open-cluster-management-agent
externalServerURLs:
- url: https://localhost
- url: https://localhost

View File

@@ -2,23 +2,23 @@ apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
creationTimestamp: null
name: spokecores.nucleus.open-cluster-management.io
name: klusterlets.operator.open-cluster-management.io
spec:
group: nucleus.open-cluster-management.io
group: operator.open-cluster-management.io
names:
kind: SpokeCore
listKind: SpokeCoreList
plural: spokecores
singular: spokecore
kind: Klusterlet
listKind: KlusterletList
plural: klusterlets
singular: klusterlet
scope: Cluster
subresources:
status: {}
validation:
openAPIV3Schema:
description: SpokeCore represents a deployment of nucleus core agent on spoke
cluster. When the deployment of spoke core agent is deployed, it will requires
a secret with the name of bootstrap-hub-kubeconfig in the namespace defined
in the spec.
description: Klusterlet represents controllers on the managed cluster. When
configured, the Klusterlet requires a secret named of bootstrap-hub-kubeconfig
in the same namespace to allow API requests to the hub for the registration
protocol.
type: object
properties:
apiVersion:
@@ -34,7 +34,7 @@ spec:
metadata:
type: object
spec:
description: Spec represents the desired deployment configuratioin of nucleus
description: Spec represents the desired deployment configuration of klusterlet
agent.
type: object
properties:
@@ -65,7 +65,7 @@ spec:
namespace:
description: Namespace is the namespace to deploy the agent. The namespace
must have a prefix of "open-cluster-management-", and if it is not
set, the namespace of "open-cluster-management" is used to deploy
set, the namespace of "open-cluster-management-spoke" is used to deploy
agent.
type: string
registrationImagePullSpec:
@@ -77,7 +77,7 @@ spec:
of work agent.
type: string
status:
description: Status represents the current status of nucleus agent.
description: Status represents the current status of klusterlet agent.
type: object
properties:
conditions:
@@ -117,6 +117,7 @@ spec:
- name: v1
served: true
storage: true
preserveUnknownFields: false
status:
acceptedNames:
kind: ""

View File

@@ -5,10 +5,10 @@ metadata:
alm-examples: |-
[
{
"apiVersion": "nucleus.open-cluster-management.io/v1",
"kind": "SpokeCore",
"apiVersion": "operator.open-cluster-management.io/v1",
"kind": "Klusterlet",
"metadata": {
"name": "spoke"
"name": "klusterlet"
},
"spec": {
"clusterName": "cluster1",
@@ -17,23 +17,23 @@ metadata:
"url": "https://localhost"
}
],
"namespace": "open-cluster-management-spoke",
"namespace": "open-cluster-management-agent",
"registrationImagePullSpec": "quay.io/open-cluster-management/registration",
"workImagePullSpec": "quay.io/open-cluster-management/work"
}
}
]
capabilities: Basic Install
name: nucleus-spoke.v0.1.0
name: klusterlet.v0.1.0
namespace: placeholder
spec:
apiservicedefinitions: {}
customresourcedefinitions:
owned:
- kind: SpokeCore
name: spokecores.nucleus.open-cluster-management.io
- kind: Klusterlet
name: klusterlets.operator.open-cluster-management.io
version: v1
displayName: Nucleus Spoke
displayName: Klusterlet
icon:
- base64data: ""
mediatype: ""
@@ -120,9 +120,9 @@ spec:
- escalate
- bind
- apiGroups:
- nucleus.open-cluster-management.io
- operator.open-cluster-management.io
resources:
- spokecores
- klusterlets
verbs:
- get
- list
@@ -131,25 +131,25 @@ spec:
- patch
- delete
- apiGroups:
- nucleus.open-cluster-management.io
- operator.open-cluster-management.io
resources:
- spokecores/status
- klusterlets/status
verbs:
- update
- patch
serviceAccountName: nucleus-spoke
serviceAccountName: klusterlet
deployments:
- name: nucleus-spoke
- name: klusterlet
spec:
replicas: 3
selector:
matchLabels:
app: nucleus-spoke
app: klusterlet
strategy: {}
template:
metadata:
labels:
app: nucleus-spoke
app: klusterlet
spec:
containers:
- args:
@@ -164,7 +164,7 @@ spec:
scheme: HTTPS
initialDelaySeconds: 2
periodSeconds: 10
name: nucleus-spoke
name: klusterlet
readinessProbe:
httpGet:
path: /healthz
@@ -172,7 +172,7 @@ spec:
scheme: HTTPS
initialDelaySeconds: 2
resources: {}
serviceAccountName: nucleus-spoke
serviceAccountName: klusterlet
strategy: deployment
installModes:
- supported: true
@@ -188,6 +188,5 @@ spec:
maintainers:
- {}
maturity: alpha
provider:
name: open-cluster-management
provider: {}
version: 0.1.0

View File

@@ -0,0 +1,7 @@
annotations:
operators.operatorframework.io.bundle.channel.default.v1: stable
operators.operatorframework.io.bundle.channels.v1: stable
operators.operatorframework.io.bundle.manifests.v1: manifests/
operators.operatorframework.io.bundle.mediatype.v1: registry+v1
operators.operatorframework.io.bundle.metadata.v1: metadata/
operators.operatorframework.io.bundle.package.v1: klusterlet

View File

@@ -1,23 +1,23 @@
kind: Deployment
apiVersion: apps/v1
metadata:
name: nucleus-spoke
name: klusterlet
namespace: open-cluster-management
labels:
app: nucleus-spoke
app: klusterlet
spec:
replicas: 3
selector:
matchLabels:
app: nucleus-spoke
app: klusterlet
template:
metadata:
labels:
app: nucleus-spoke
app: klusterlet
spec:
serviceAccountName: nucleus-spoke
serviceAccountName: klusterlet
containers:
- name: nucleus-spoke
- name: klusterlet
image: quay.io/open-cluster-management/nucleus:latest
imagePullPolicy: IfNotPresent
args:

View File

@@ -1,5 +1,5 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: nucleus-hub
name: klusterlet
namespace: open-cluster-management

View File

@@ -1,6 +0,0 @@
apiVersion: nucleus.open-cluster-management.io/v1
kind: HubCore
metadata:
name: hub
spec:
registrationImagePullSpec: quay.io/open-cluster-management/registration

View File

@@ -1,7 +0,0 @@
annotations:
operators.operatorframework.io.bundle.channel.default.v1: stable
operators.operatorframework.io.bundle.channels.v1: stable
operators.operatorframework.io.bundle.manifests.v1: manifests/
operators.operatorframework.io.bundle.mediatype.v1: registry+v1
operators.operatorframework.io.bundle.metadata.v1: metadata/
operators.operatorframework.io.bundle.package.v1: nucleus-hub

View File

@@ -1,7 +0,0 @@
annotations:
operators.operatorframework.io.bundle.channel.default.v1: stable
operators.operatorframework.io.bundle.channels.v1: stable
operators.operatorframework.io.bundle.manifests.v1: manifests/
operators.operatorframework.io.bundle.mediatype.v1: registry+v1
operators.operatorframework.io.bundle.metadata.v1: metadata/
operators.operatorframework.io.bundle.package.v1: nucleus-spoke

12
go.mod
View File

@@ -4,19 +4,19 @@ go 1.13
require (
github.com/davecgh/go-spew v1.1.1
github.com/jteeuwen/go-bindata v3.0.8-0.20151023091102-a0ff2567cfb7+incompatible
github.com/go-bindata/go-bindata v3.1.2+incompatible
github.com/onsi/ginkgo v1.11.0
github.com/onsi/gomega v1.8.1
github.com/open-cluster-management/api v0.0.0-20200512175145-bed9ce79e17e
github.com/open-cluster-management/api v0.0.0-20200601153054-56b58ce890e1
github.com/openshift/api v0.0.0-20200326160804-ecb9283fe820
github.com/openshift/build-machinery-go v0.0.0-20200211121458-5e3d6e570160
github.com/openshift/build-machinery-go v0.0.0-20200424080330-082bf86082cc
github.com/openshift/library-go v0.0.0-20200414135834-ccc4bb27d032
github.com/spf13/cobra v1.0.0
github.com/spf13/pflag v1.0.5
k8s.io/api v0.18.2
k8s.io/api v0.18.3
k8s.io/apiextensions-apiserver v0.18.2
k8s.io/apimachinery v0.18.2
k8s.io/client-go v0.18.2
k8s.io/apimachinery v0.18.3
k8s.io/client-go v0.18.3
k8s.io/component-base v0.18.2
k8s.io/klog v1.0.0
k8s.io/kube-aggregator v0.18.0

53
go.sum
View File

@@ -2,6 +2,7 @@ bitbucket.org/ww/goautoneg v0.0.0-20120707110453-75cd24fc2f2c/go.mod h1:1vhO7Mn/
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
@@ -12,6 +13,7 @@ github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6L
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Microsoft/go-winio v0.4.11 h1:zoIOcVf0xPN1tnMVbTtEdI+P8OofVk3NObnwOQ6nK2Q=
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46 h1:lsxEuwrXEAokXB9qhlbKWPpo3KMLZQ5WB5WLQRW1uq0=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
@@ -44,6 +46,7 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa h1:OaNxuTZr7kxeODyLWsRMC+OD03aFUH+mW6r2d+MWa5Y=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6 h1:NmTXa/uVnDyp0TY5MKi197+3HWcnYWfnHGyaFthlnGw=
github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
github.com/coreos/bbolt v1.3.1-coreos.6/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
@@ -70,12 +73,17 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/docker/distribution v0.0.0-20180920194744-16128bbac47f h1:hYf+mPizfvpH6VgIxdntnOmQHd1F1mQUc1oG+j3Ol2g=
github.com/docker/distribution v0.0.0-20180920194744-16128bbac47f/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0 h1:w3NnFcKR5241cfmQU5ZZAsf0xcpId6mWOupTvJlUX2U=
github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.3.0 h1:3lOnM9cSzgGwx8VfK/NGOW5fLQ0GjIlCkaktF+n1M6o=
github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/libnetwork v0.0.0-20190731215715-7f13a5c99f4b h1:rACxqwRsHD075Vb7qTimAgMSKWoM5zER0Dhws/SgCVo=
github.com/docker/libnetwork v0.0.0-20190731215715-7f13a5c99f4b/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8=
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 h1:cenwrSVm+Z7QLSV/BsnenAOcDXdX4cMv4wP0B/5QbPg=
@@ -96,6 +104,7 @@ github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsouza/go-dockerclient v0.0.0-20171004212419-da3951ba2e9e h1:B94x7idrPK5yFSMWliAvakUQlTDLgO7iJyHtpbYxGGM=
github.com/fsouza/go-dockerclient v0.0.0-20171004212419-da3951ba2e9e/go.mod h1:KpcjM623fQYE9MZiTGzKhjfxXAV9wbyX2C1cyRHfhl0=
github.com/getsentry/raven-go v0.0.0-20190513200303-c977f96e1095 h1:F2m41rgyxoveZKD+Z6xwyAbtdNeVvhpi9BpQLvt5oRU=
github.com/getsentry/raven-go v0.0.0-20190513200303-c977f96e1095/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
@@ -104,6 +113,8 @@ github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
github.com/go-bindata/go-bindata v3.1.2+incompatible h1:5vjJMVhowQdPzjE1LdxyFF7YFTXg5IgGVW4gBr5IbvE=
github.com/go-bindata/go-bindata v3.1.2+incompatible/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
@@ -175,6 +186,13 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc=
github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+aosOB5+iEPoV3picfs8tUpkVd0pDo+Kg=
github.com/gonum/graph v0.0.0-20170401004347-50b27dea7ebb/go.mod h1:ye018NnX1zrbOLqwBvs2HqyyTouQgnL8C+qzYk1snPY=
@@ -188,6 +206,8 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -234,6 +254,8 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jteeuwen/go-bindata v3.0.8-0.20151023091102-a0ff2567cfb7+incompatible h1:KTM14h3AKWWcPf5IWS/pcFTZosRmoqdIYzqi0mMG7es=
github.com/jteeuwen/go-bindata v3.0.8-0.20151023091102-a0ff2567cfb7+incompatible/go.mod h1:JVvhzYOiGBnFSYRyV00iY8q7/0PThjIYav1p9h5dmKs=
@@ -272,6 +294,7 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
@@ -289,16 +312,20 @@ github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGV
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.8.1 h1:C5Dqfs/LeauYDX0jJXIe2SWmwCbGzx9yF8C8xy3Lh34=
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
github.com/open-cluster-management/api v0.0.0-20200512175145-bed9ce79e17e h1:WIzt0Bs7g0PIrVAVSobXAbDqvC2P5VjEwFTpjB4777I=
github.com/open-cluster-management/api v0.0.0-20200512175145-bed9ce79e17e/go.mod h1:RgKeB8PJ7upe2QXy/MpCejU/xm2G6/i0Y+/itWuPugs=
github.com/open-cluster-management/api v0.0.0-20200601153054-56b58ce890e1 h1:MCq109q/vwW/5YdliL++J17d/6orA6MDmt2WQOaIpWw=
github.com/open-cluster-management/api v0.0.0-20200601153054-56b58ce890e1/go.mod h1:+vUECYB7WkfCb52r0J7rxgD1mseSGAqGi8rTLLRcbgw=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v0.0.0-20191031171055-b133feaeeb2e h1:NKMVwQeEqNOp8DVM4J1HjpZHRcQO7MAVfZwFxs+Bqec=
github.com/opencontainers/runc v0.0.0-20191031171055-b133feaeeb2e/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/openshift/api v0.0.0-20200326152221-912866ddb162/go.mod h1:RKMJ5CBnljLfnej+BJ/xnOWc3kZDvJUaIAEq2oKSPtE=
github.com/openshift/api v0.0.0-20200326160804-ecb9283fe820 h1:pEmlKM0gcAPwPEOUt0JOMBd+3bDEOaSZLdvPTm2eU6E=
github.com/openshift/api v0.0.0-20200326160804-ecb9283fe820/go.mod h1:RKMJ5CBnljLfnej+BJ/xnOWc3kZDvJUaIAEq2oKSPtE=
github.com/openshift/build-machinery-go v0.0.0-20200211121458-5e3d6e570160 h1:V4E6yt4XWiBEPKnJbs/E8pgUq9AjZqzQfsL3eeT84Qs=
github.com/openshift/build-machinery-go v0.0.0-20200211121458-5e3d6e570160/go.mod h1:1CkcsT3aVebzRBzVTSbiKSkJMsC/CASqxesfqEMfJEc=
github.com/openshift/build-machinery-go v0.0.0-20200424080330-082bf86082cc h1:Bu1p7+ItPqhJhmMve7sVluKCYV+o+x1Ede0WY2/BI8Q=
github.com/openshift/build-machinery-go v0.0.0-20200424080330-082bf86082cc/go.mod h1:1CkcsT3aVebzRBzVTSbiKSkJMsC/CASqxesfqEMfJEc=
github.com/openshift/client-go v0.0.0-20200326155132-2a6cd50aedd0/go.mod h1:uUQ4LClRO+fg5MF/P6QxjMCb1C9f7Oh4RKepftDnEJE=
github.com/openshift/library-go v0.0.0-20200414135834-ccc4bb27d032 h1:DFlzobaf+Sy22sUz5oCoFcpzv4pLcjUgUEPLDSitnX0=
github.com/openshift/library-go v0.0.0-20200414135834-ccc4bb27d032/go.mod h1:CfydoH0B+RYs22uQZQ36A1mz5m5zhucpMGh8t5s71v4=
@@ -435,6 +462,8 @@ golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd h1:QPwSajcTUrFriMF1nJ3XzgoqakqQEsnZf9LdXdi2nkI=
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -464,6 +493,8 @@ golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7 h1:HmbHVPwrPEKPGLAcHSrMe6+hqSUlvZU0rab6x5EXfGU=
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -491,6 +522,8 @@ golang.org/x/tools v0.0.0-20200115044656-831fdb1e1868/go.mod h1:TB2adYChydJhpapK
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gomodules.xyz/jsonpatch/v2 v2.0.1 h1:xyiBuvkD2g5n7cYzx6u2sxQvsAy4QJsZFCzGVdzOXZ0=
gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
@@ -509,6 +542,13 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -540,20 +580,27 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
k8s.io/api v0.18.0/go.mod h1:q2HRQkfDzHMBZL9l/y9rH63PkQl4vae0xRT+8prbrK8=
k8s.io/api v0.18.2 h1:wG5g5ZmSVgm5B+eHMIbI9EGATS2L8Z72rda19RIEgY8=
k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78=
k8s.io/api v0.18.3 h1:2AJaUQdgUZLoDZHrun21PW2Nx9+ll6cUzvn3IKhSIn0=
k8s.io/api v0.18.3/go.mod h1:UOaMwERbqJMfeeeHc8XJKawj4P9TgDRnViIqqBeH2QA=
k8s.io/apiextensions-apiserver v0.18.0/go.mod h1:18Cwn1Xws4xnWQNC00FLq1E350b9lUF+aOdIWDOZxgo=
k8s.io/apiextensions-apiserver v0.18.2 h1:I4v3/jAuQC+89L3Z7dDgAiN4EOjN6sbm6iBqQwHTah8=
k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY=
k8s.io/apimachinery v0.18.0/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
k8s.io/apimachinery v0.18.2 h1:44CmtbmkzVDAhCpRVSiP2R5PPrC2RtlIv/MoB8xpdRA=
k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
k8s.io/apimachinery v0.18.3 h1:pOGcbVAhxADgUYnjS08EFXs9QMl8qaH5U4fr5LGUrSk=
k8s.io/apimachinery v0.18.3/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
k8s.io/apiserver v0.18.0/go.mod h1:3S2O6FeBBd6XTo0njUrLxiqk8GNy6wWOftjhJcXYnjw=
k8s.io/apiserver v0.18.2 h1:fwKxdTWwwYhxvtjo0UUfX+/fsitsNtfErPNegH2x9ic=
k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw=
k8s.io/client-go v0.18.0/go.mod h1:uQSYDYs4WhVZ9i6AIoEZuwUggLVEF64HOD37boKAtF8=
k8s.io/client-go v0.18.2 h1:aLB0iaD4nmwh7arT2wIn+lMnAq7OswjaejkQ8p9bBYE=
k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU=
k8s.io/client-go v0.18.3 h1:QaJzz92tsN67oorwzmoB0a9r9ZVHuD5ryjbCKP0U22k=
k8s.io/client-go v0.18.3/go.mod h1:4a/dpQEvzAhT1BbuWW09qvIaGw6Gbu1gZYiQZIi1DMw=
k8s.io/code-generator v0.18.0/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc=
k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc=
k8s.io/code-generator v0.18.3/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
k8s.io/component-base v0.18.0/go.mod h1:u3BCg0z1uskkzrnAKFzulmYaEpZF7XC9Pf/uFyb1v2c=
k8s.io/component-base v0.18.2 h1:SJweNZAGcUvsypLGNPNGeJ9UgPZQ6+bW+gEHe8uyh/Y=
k8s.io/component-base v0.18.2/go.mod h1:kqLlMuhJNHQ9lz8Z7V5bxUUtjFZnrypArGl58gmDfUM=
@@ -567,6 +614,8 @@ k8s.io/kube-aggregator v0.18.0 h1:J+wa9FDQ3SbgyA8wQBNg2m2FMSm+mMQfs2A58500hs0=
k8s.io/kube-aggregator v0.18.0/go.mod h1:ateewQ5QbjMZF/dihEFXwaEwoA4v/mayRvzfmvb6eqI=
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c h1:/KUFqjjqAcY4Us6luF5RDNZ16KJtb49HfR3ZHB9qYXM=
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6 h1:Oh3Mzx5pJ+yIumsAD0MOECPVeXsVot0UkiaCGVyfGQY=
k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20200327001022-6496210b90e8 h1:6JFbaLjRyBz8K2Jvt+pcT+N3vvwMZfg8MfVENwe9aag=
k8s.io/utils v0.0.0-20200327001022-6496210b90e8/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=

View File

@@ -4,8 +4,8 @@ source "$(dirname "${BASH_SOURCE}")/init.sh"
for f in $CRD_FILES
do
cp $f ./manifests/hub/
cp $f ./manifests/cluster-manager/
done
cp $NUCLEUS_HUB_CRD_FILE ./deploy/nucleus-hub/crds/
cp $NUCLEUS_SPOKE_CRD_FILE ./deploy/nucleus-spoke/crds/
cp $CLUSTER_MANAGER_CRD_FILE ./deploy/cluster-manager/crds/
cp $KLUSTERLET_CRD_FILE ./deploy/klusterlet/crds/

View File

@@ -8,5 +8,5 @@ CRD_FILES="./vendor/github.com/open-cluster-management/api/cluster/v1/*.crd.yaml
./vendor/github.com/open-cluster-management/api/work/v1/*.crd.yaml
"
NUCLEUS_HUB_CRD_FILE="./vendor/github.com/open-cluster-management/api/nucleus/v1/0000_01_nucleus.open-cluster-management.io_hubcores.crd.yaml"
NUCLEUS_SPOKE_CRD_FILE="./vendor/github.com/open-cluster-management/api/nucleus/v1/0000_00_nucleus.open-cluster-management.io_agentcores.crd.yaml"
CLUSTER_MANAGER_CRD_FILE="./vendor/github.com/open-cluster-management/api/operator/v1/0000_01_operator.open-cluster-management.io_clustermanagers.crd.yaml"
KLUSTERLET_CRD_FILE="./vendor/github.com/open-cluster-management/api/operator/v1/0000_00_operator.open-cluster-management.io_klusterlets.crd.yaml"

View File

@@ -4,9 +4,9 @@ source "$(dirname "${BASH_SOURCE}")/init.sh"
for f in $CRD_FILES
do
diff -N $f ./manifests/hub/$(basename $f) || ( echo 'crd content is incorrect' && false )
diff -N $f ./manifests/cluster-manager/$(basename $f) || ( echo 'crd content is incorrect' && false )
done
diff -N $NUCLEUS_HUB_CRD_FILE ./deploy/nucleus-hub/crds/$(basename $NUCLEUS_HUB_CRD_FILES) || ( echo 'crd content is incorrect' && false )
diff -N $NUCLEUS_SPOKE_CRD_FILE ./deploy/nucleus-spoke/crds/$(basename $NUCLEUS_SPOKE_CRD_FILES) || ( echo 'crd content is incorrect' && false )
diff -N $CLUSTER_MANAGER_CRD_FILE ./deploy/cluster-manager/crds/$(basename $CLUSTER_MANAGER_CRD_FILE) || ( echo 'crd content is incorrect' && false )
diff -N $KLUSTERLET_CRD_FILE ./deploy/klusterlet/crds/$(basename $KLUSTERLET_CRD_FILE) || ( echo 'crd content is incorrect' && false )

View File

@@ -54,6 +54,12 @@ spec:
to grant the permision of access from agent on spoke. When the value
is set false, the namespace representing the spoke cluster is deleted.
type: boolean
leaseDurationSeconds:
description: LeaseDurationSeconds is used to coordinate the lease update
time of spoke agents. If its value is zero, the spoke agent will update
its lease per 60s by default
type: integer
format: int32
spokeClientConfigs:
description: SpokeClientConfigs represents a list of the apiserver address
of the spoke cluster. If it is empty, spoke cluster has no accessible

View File

@@ -59,6 +59,39 @@ spec:
description: Status represents the current status of work
type: object
properties:
appliedResources:
description: AppliedResources represents a list of resources defined
within the manifestwork that are applied. Only resources with valid
GroupVersionResource, namespace, and name are suitable. An item in
this slice is deleted when there is no mapped manifest in manifestwork.Spec
or by finalizer. The resource relating to the item will also be removed
from spoke cluster. The deleted resource may still be present until
the finalizers for that resource are finished. However, the resource
will not be undeleted, so it can be removed from this list and eventual
consistency is preserved.
type: array
items:
description: AppliedManifestResourceMeta represents the gvr, name
and namespace of a resource. Since these resources have been created,
they must have valid group, version, resource, namespace, and name.
type: object
properties:
group:
description: Group is the API Group of the kubernetes resource
type: string
name:
description: Name is the name of the kubernetes resource
type: string
namespace:
description: Name is the namespace of the kubernetes resource,
empty string indicates it is a cluster scoped resource.
type: string
resource:
description: Resource is the resource name of the kubernetes resource
type: string
version:
description: Version is the version of the kubernetes resource
type: string
conditions:
description: 'Conditions contains the different condition statuses for
this work. Valid condition types are: 1. Applied represents workload

View File

@@ -0,0 +1,12 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:open-cluster-management:{{ .ClusterManagerName }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:open-cluster-management:{{ .ClusterManagerName }}
subjects:
- kind: ServiceAccount
namespace: {{ .ClusterManagerNamespace }}
name: {{ .ClusterManagerName }}-sa

View File

@@ -1,4 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: {{ .HubCoreNamespace }}
name: {{ .ClusterManagerNamespace }}

View File

@@ -1,7 +1,7 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: system:open-cluster-management:{{ .HubCoreName }}-registration-controller
name: system:open-cluster-management:{{ .ClusterManagerName }}-registration-controller
rules:
# Allow hub to monitor and update status of csr
- apiGroups: ["certificates.k8s.io"]

View File

@@ -0,0 +1,12 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:open-cluster-management:{{ .ClusterManagerName }}-registration-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:open-cluster-management:{{ .ClusterManagerName }}-registration-controller
subjects:
- kind: ServiceAccount
namespace: {{ .ClusterManagerNamespace }}
name: {{ .ClusterManagerName }}-registration-controller-sa

View File

@@ -1,21 +1,21 @@
kind: Deployment
apiVersion: apps/v1
metadata:
name: {{ .HubCoreName }}-registration-controller
namespace: {{ .HubCoreNamespace }}
name: {{ .ClusterManagerName }}-registration-controller
namespace: {{ .ClusterManagerNamespace }}
labels:
app: nucleushub-registration-controller
app: clustermanager-controller
spec:
replicas: 3
selector:
matchLabels:
app: nucleushub-registration-controller
app: clustermanager-registration-controller
template:
metadata:
labels:
app: nucleushub-registration-controller
app: clustermanager-registration-controller
spec:
serviceAccountName: {{ .HubCoreName }}-registration-controller-sa
serviceAccountName: {{ .ClusterManagerName }}-registration-controller-sa
containers:
- name: hub-registration-controller
image: {{ .RegistrationImage }}

View File

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

View File

@@ -6,8 +6,8 @@ spec:
group: admission.cluster.open-cluster-management.io
version: v1
service:
name: {{ .HubCoreWebhookRegistrationService }}
namespace: {{ .HubCoreNamespace }}
name: {{ .ClusterManagerWebhookRegistrationService }}
namespace: {{ .ClusterManagerNamespace }}
caBundle: {{ .RegistrationAPIServiceCABundle }}
groupPriorityMinimum: 10000
versionPriority: 20

View File

@@ -1,7 +1,7 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: system:open-cluster-management:{{ .HubCoreName }}-registration-webhook
name: system:open-cluster-management:{{ .ClusterManagerName }}-registration-webhook
rules:
# Allow spokecluster admission to get/list/watch configmaps
- apiGroups: [""]

View File

@@ -0,0 +1,12 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:open-cluster-management:{{ .ClusterManagerName }}-registration-webhook
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:open-cluster-management:{{ .ClusterManagerName }}-registration-webhook
subjects:
- kind: ServiceAccount
name: {{ .ClusterManagerName }}-registration-webhook-sa
namespace: {{ .ClusterManagerNamespace }}

View File

@@ -1,23 +1,23 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .HubCoreName }}-registration-webhook
namespace: {{ .HubCoreNamespace }}
name: {{ .ClusterManagerName }}-registration-webhook
namespace: {{ .ClusterManagerNamespace }}
labels:
app: {{ .HubCoreName }}-registration-webhook
app: {{ .ClusterManagerName }}-registration-webhook
spec:
replicas: 3
selector:
matchLabels:
app: {{ .HubCoreName }}-registration-webhook
app: {{ .ClusterManagerName }}-registration-webhook
template:
metadata:
labels:
app: {{ .HubCoreName }}-registration-webhook
app: {{ .ClusterManagerName }}-registration-webhook
spec:
serviceAccountName: {{ .HubCoreName }}-registration-webhook-sa
serviceAccountName: {{ .ClusterManagerName }}-registration-webhook-sa
containers:
- name: {{ .HubCoreName }}-registration-webhook-sa
- name: {{ .ClusterManagerName }}-registration-webhook-sa
image: {{ .RegistrationImage }}
imagePullPolicy: IfNotPresent
args:
@@ -46,5 +46,5 @@ spec:
volumes:
- name: webhook-secret
secret:
secretName: {{ .HubCoreWebhookSecret }}
secretName: {{ .ClusterManagerWebhookSecret }}

View File

@@ -1,8 +1,8 @@
apiVersion: v1
kind: Secret
metadata:
name: {{ .HubCoreWebhookSecret }}
namespace: {{ .HubCoreNamespace }}
name: {{ .ClusterManagerWebhookSecret }}
namespace: {{ .ClusterManagerNamespace }}
data:
tls.crt: {{ .RegistrationServingCert }}
tls.key: {{ .RegistrationServingKey }}

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: Service
metadata:
name: {{ .ClusterManagerWebhookRegistrationService }}
namespace: {{ .ClusterManagerNamespace }}
spec:
selector:
app: {{ .ClusterManagerName }}-registration-webhook
ports:
- port: 443
targetPort: 6443

View File

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

View File

@@ -1,12 +0,0 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:open-cluster-management:{{ .HubCoreName }}-registration-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:open-cluster-management:{{ .HubCoreName }}-registration-controller
subjects:
- kind: ServiceAccount
namespace: {{ .HubCoreNamespace }}
name: {{ .HubCoreName }}-registration-controller-sa

View File

@@ -1,5 +0,0 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .HubCoreName }}-registration-controller-sa
namespace: {{ .HubCoreNamespace }}

View File

@@ -1,12 +0,0 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:open-cluster-management:{{ .HubCoreName }}-registration-webhook
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ .HubCoreName }}-registration-webhook
subjects:
- kind: ServiceAccount
name: {{ .HubCoreName }}-registration-webhook-sa
namespace: {{ .HubCoreNamespace }}

View File

@@ -1,11 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: {{ .HubCoreWebhookRegistrationService }}
namespace: {{ .HubCoreNamespace }}
spec:
selector:
app: {{ .HubCoreName }}-registration-webhook
ports:
- port: 443
targetPort: 6443

View File

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

View File

@@ -2,7 +2,7 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: system:open-cluster-management:{{ .SpokeCoreName }}-registration-agent
name: system:open-cluster-management:{{ .KlusterletName }}-registration-agent
rules:
# Allow agent to get/list/watch nodes.
- apiGroups: [""]

View File

@@ -0,0 +1,12 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:open-cluster-management:{{ .KlusterletName }}-registration-agent
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:open-cluster-management:{{ .KlusterletName }}-registration-agent
subjects:
- kind: ServiceAccount
name: {{ .KlusterletName }}-registration-sa
namespace: {{ .KlusterletNamespace }}

View File

@@ -1,21 +1,21 @@
kind: Deployment
apiVersion: apps/v1
metadata:
name: {{ .SpokeCoreName }}-registration-agent
namespace: {{ .SpokeCoreNamespace }}
name: {{ .KlusterletName }}-registration-agent
namespace: {{ .KlusterletNamespace }}
labels:
app: spoke-registration-agent
app: klusterlet-registration-agent
spec:
replicas: 3
selector:
matchLabels:
app: spoke-registration-agent
app: klusterlet-registration-agent
template:
metadata:
labels:
app: spoke-registration-agent
app: klusterlet-registration-agent
spec:
serviceAccountName: {{ .SpokeCoreName }}-registration-sa
serviceAccountName: {{ .KlusterletName }}-registration-sa
containers:
- name: spoke-agent
image: {{ .RegistrationImage }}

View File

@@ -2,8 +2,8 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: system:open-cluster-management:{{ .SpokeCoreName }}-registration-agent
namespace: {{ .SpokeCoreNamespace }}
name: system:open-cluster-management:{{ .KlusterletName }}-registration-agent
namespace: {{ .KlusterletNamespace }}
rules:
- apiGroups: [""]
resources: ["configmaps", "secrets"]

View File

@@ -0,0 +1,13 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: system:open-cluster-management:{{ .KlusterletName }}-registration-agent
namespace: {{ .KlusterletNamespace }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: system:open-cluster-management:{{ .KlusterletName }}-registration-agent
subjects:
- kind: ServiceAccount
name: {{ .KlusterletName }}-registration-sa
namespace: {{ .KlusterletNamespace }}

View File

@@ -0,0 +1,5 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .KlusterletName }}-registration-sa
namespace: {{ .KlusterletNamespace }}

View File

@@ -2,7 +2,7 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: system:open-cluster-management:{{ .SpokeCoreName }}-work-agent
name: system:open-cluster-management:{{ .KlusterletName }}-work-agent
rules:
# Allow agent to get/list/watch/create/delete crds.
- apiGroups: ["apiextensions.k8s.io"]

View File

@@ -0,0 +1,12 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:open-cluster-management:{{ .KlusterletName }}-work-agent-addition
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:open-cluster-management:{{ .KlusterletName }}-work-agent
subjects:
- kind: ServiceAccount
name: {{ .KlusterletName }}-work-sa
namespace: {{ .KlusterletNamespace }}

View File

@@ -1,14 +1,14 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:open-cluster-management:{{ .SpokeCoreName }}-work-agent
name: system:open-cluster-management:{{ .KlusterletName }}-work-agent
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
# We deploy a controller that could work with permission lower than cluster-admin, the tradeoff is
# We deploy a controller that could work with permission lower than cluster-admin, the tradeoff is
# responsivity because list/watch cannot be maintained over too many namespaces.
name: admin
subjects:
- kind: ServiceAccount
name: {{ .SpokeCoreName }}-work-sa
namespace: {{ .SpokeCoreNamespace }}
name: {{ .KlusterletName }}-work-sa
namespace: {{ .KlusterletNamespace }}

View File

@@ -1,21 +1,21 @@
kind: Deployment
apiVersion: apps/v1
metadata:
name: {{ .SpokeCoreName }}-work-agent
namespace: {{ .SpokeCoreNamespace }}
name: {{ .KlusterletName }}-work-agent
namespace: {{ .KlusterletNamespace }}
labels:
app: spoke-work-agent
app: klusterlet-manifestwork-agent
spec:
replicas: 3
selector:
matchLabels:
app: spoke-work-agent
app: klusterlet-manifestwork-agent
template:
metadata:
labels:
app: spoke-work-agent
app: klusterlet-manifestwork-agent
spec:
serviceAccountName: {{ .SpokeCoreName }}-work-sa
serviceAccountName: {{ .KlusterletName }}-work-sa
containers:
- name: spoke-agent
image: {{ .WorkImage }}

View File

@@ -0,0 +1,5 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .KlusterletName }}-work-sa
namespace: {{ .KlusterletNamespace }}

View File

@@ -1,12 +0,0 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:open-cluster-management:{{ .SpokeCoreName }}-registration-agent
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:open-cluster-management:{{ .SpokeCoreName }}-registration-agent
subjects:
- kind: ServiceAccount
name: {{ .SpokeCoreName }}-registration-sa
namespace: {{ .SpokeCoreNamespace }}

View File

@@ -1,13 +0,0 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: system:open-cluster-management:{{ .SpokeCoreName }}-registration-agent
namespace: {{ .SpokeCoreNamespace }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: system:open-cluster-management:{{ .SpokeCoreName }}-registration-agent
subjects:
- kind: ServiceAccount
name: {{ .SpokeCoreName }}-registration-sa
namespace: {{ .SpokeCoreNamespace }}

View File

@@ -1,5 +0,0 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .SpokeCoreName }}-registration-sa
namespace: {{ .SpokeCoreNamespace }}

View File

@@ -1,12 +0,0 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:open-cluster-management:{{ .SpokeCoreName }}-work-agent-addition
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:open-cluster-management:{{ .SpokeCoreName }}-work-agent
subjects:
- kind: ServiceAccount
name: {{ .SpokeCoreName }}-work-sa
namespace: {{ .SpokeCoreNamespace }}

View File

@@ -1,5 +0,0 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .SpokeCoreName }}-work-sa
namespace: {{ .SpokeCoreNamespace }}

View File

@@ -12,10 +12,10 @@ import (
// NewHubOperatorCmd generatee a command to start hub operator
func NewHubOperatorCmd() *cobra.Command {
cmd := controllercmd.
NewControllerCommandConfig("nucleus-hub", version.Get(), operators.RunNucleusHubOperator).
NewControllerCommandConfig("clustermanager", version.Get(), operators.RunClusterManagerOperator).
NewCommand()
cmd.Use = "hub"
cmd.Short = "Start the nucleus hub operator"
cmd.Short = "Start the cluster manager operator"
return cmd
}

View File

@@ -12,10 +12,10 @@ import (
// NewSpokeOperatorCmd generatee a command to start spoke operator
func NewSpokeOperatorCmd() *cobra.Command {
cmd := controllercmd.
NewControllerCommandConfig("nucleus-spoke", version.Get(), operators.RunNucleusSpokeOperator).
NewControllerCommandConfig("klusterlet", version.Get(), operators.RunKlusterletOperator).
NewCommand()
cmd.Use = "spoke"
cmd.Short = "Start the nucleus hub operator"
cmd.Short = "Start the klusterlet operator"
return cmd
}

View File

@@ -5,7 +5,7 @@
package dependencymagnet
import (
_ "github.com/jteeuwen/go-bindata/go-bindata"
_ "github.com/go-bindata/go-bindata/go-bindata"
_ "github.com/open-cluster-management/api/cluster/v1"
_ "github.com/open-cluster-management/api/work/v1"
_ "github.com/openshift/build-machinery-go"

View File

@@ -5,8 +5,8 @@ import (
"fmt"
"time"
nucleusv1client "github.com/open-cluster-management/api/client/nucleus/clientset/versioned/typed/nucleus/v1"
nucleusapiv1 "github.com/open-cluster-management/api/nucleus/v1"
operatorv1client "github.com/open-cluster-management/api/client/operator/clientset/versioned/typed/operator/v1"
operatorapiv1 "github.com/open-cluster-management/api/operator/v1"
admissionv1 "k8s.io/api/admissionregistration/v1"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
@@ -45,14 +45,14 @@ func init() {
utilruntime.Must(admissionv1.AddToScheme(genericScheme))
}
func IsConditionTrue(condition *nucleusapiv1.StatusCondition) bool {
func IsConditionTrue(condition *operatorapiv1.StatusCondition) bool {
if condition == nil {
return false
}
return condition.Status == metav1.ConditionTrue
}
func FindNucleusCondition(conditions []nucleusapiv1.StatusCondition, conditionType string) *nucleusapiv1.StatusCondition {
func FindOperatorCondition(conditions []operatorapiv1.StatusCondition, conditionType string) *operatorapiv1.StatusCondition {
for i := range conditions {
if conditions[i].Type == conditionType {
return &conditions[i]
@@ -61,11 +61,11 @@ func FindNucleusCondition(conditions []nucleusapiv1.StatusCondition, conditionTy
return nil
}
func SetNucleusCondition(conditions *[]nucleusapiv1.StatusCondition, newCondition nucleusapiv1.StatusCondition) {
func SetOperatorCondition(conditions *[]operatorapiv1.StatusCondition, newCondition operatorapiv1.StatusCondition) {
if conditions == nil {
conditions = &[]nucleusapiv1.StatusCondition{}
conditions = &[]operatorapiv1.StatusCondition{}
}
existingCondition := FindNucleusCondition(*conditions, newCondition.Type)
existingCondition := FindOperatorCondition(*conditions, newCondition.Type)
if existingCondition == nil {
newCondition.LastTransitionTime = metav1.NewTime(time.Now())
*conditions = append(*conditions, newCondition)
@@ -81,21 +81,21 @@ func SetNucleusCondition(conditions *[]nucleusapiv1.StatusCondition, newConditio
existingCondition.Message = newCondition.Message
}
type UpdateNucleusHubStatusFunc func(status *nucleusapiv1.HubCoreStatus) error
type UpdateClusterManagerStatusFunc func(status *operatorapiv1.ClusterManagerStatus) error
func UpdateNucleusHubStatus(
func UpdateClusterManagerStatus(
ctx context.Context,
client nucleusv1client.HubCoreInterface,
nucleusHubCoreName string,
updateFuncs ...UpdateNucleusHubStatusFunc) (*nucleusapiv1.HubCoreStatus, bool, error) {
client operatorv1client.ClusterManagerInterface,
clusterManagerName string,
updateFuncs ...UpdateClusterManagerStatusFunc) (*operatorapiv1.ClusterManagerStatus, bool, error) {
updated := false
var updatedSpokeClusterStatus *nucleusapiv1.HubCoreStatus
var updatedClusterManagerStatus *operatorapiv1.ClusterManagerStatus
err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
hubCore, err := client.Get(ctx, nucleusHubCoreName, metav1.GetOptions{})
clusterManager, err := client.Get(ctx, clusterManagerName, metav1.GetOptions{})
if err != nil {
return err
}
oldStatus := &hubCore.Status
oldStatus := &clusterManager.Status
newStatus := oldStatus.DeepCopy()
for _, update := range updateFuncs {
@@ -105,47 +105,47 @@ func UpdateNucleusHubStatus(
}
if equality.Semantic.DeepEqual(oldStatus, newStatus) {
// We return the newStatus which is a deep copy of oldStatus but with all update funcs applied.
updatedSpokeClusterStatus = newStatus
updatedClusterManagerStatus = newStatus
return nil
}
hubCore.Status = *newStatus
updatedSpokeCluster, err := client.UpdateStatus(ctx, hubCore, metav1.UpdateOptions{})
clusterManager.Status = *newStatus
updatedClusterManager, err := client.UpdateStatus(ctx, clusterManager, metav1.UpdateOptions{})
if err != nil {
return err
}
updatedSpokeClusterStatus = &updatedSpokeCluster.Status
updatedClusterManagerStatus = &updatedClusterManager.Status
updated = err == nil
return err
})
return updatedSpokeClusterStatus, updated, err
return updatedClusterManagerStatus, updated, err
}
func UpdateNucleusHubConditionFn(conds ...nucleusapiv1.StatusCondition) UpdateNucleusHubStatusFunc {
return func(oldStatus *nucleusapiv1.HubCoreStatus) error {
func UpdateClusterManagerConditionFn(conds ...operatorapiv1.StatusCondition) UpdateClusterManagerStatusFunc {
return func(oldStatus *operatorapiv1.ClusterManagerStatus) error {
for _, cond := range conds {
SetNucleusCondition(&oldStatus.Conditions, cond)
SetOperatorCondition(&oldStatus.Conditions, cond)
}
return nil
}
}
type UpdateNucleusSpokeStatusFunc func(status *nucleusapiv1.SpokeCoreStatus) error
type UpdateKlusterletStatusFunc func(status *operatorapiv1.KlusterletStatus) error
func UpdateNucleusSpokeStatus(
func UpdateKlusterletStatus(
ctx context.Context,
client nucleusv1client.SpokeCoreInterface,
nucleusSpokeCoreName string,
updateFuncs ...UpdateNucleusSpokeStatusFunc) (*nucleusapiv1.SpokeCoreStatus, bool, error) {
client operatorv1client.KlusterletInterface,
klusterletName string,
updateFuncs ...UpdateKlusterletStatusFunc) (*operatorapiv1.KlusterletStatus, bool, error) {
updated := false
var updatedSpokeClusterStatus *nucleusapiv1.SpokeCoreStatus
var updatedKlusterletStatus *operatorapiv1.KlusterletStatus
err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
spokeCore, err := client.Get(ctx, nucleusSpokeCoreName, metav1.GetOptions{})
klusterlet, err := client.Get(ctx, klusterletName, metav1.GetOptions{})
if err != nil {
return err
}
oldStatus := &spokeCore.Status
oldStatus := &klusterlet.Status
newStatus := oldStatus.DeepCopy()
for _, update := range updateFuncs {
@@ -155,27 +155,27 @@ func UpdateNucleusSpokeStatus(
}
if equality.Semantic.DeepEqual(oldStatus, newStatus) {
// We return the newStatus which is a deep copy of oldStatus but with all update funcs applied.
updatedSpokeClusterStatus = newStatus
updatedKlusterletStatus = newStatus
return nil
}
spokeCore.Status = *newStatus
updatedSpokeCluster, err := client.UpdateStatus(ctx, spokeCore, metav1.UpdateOptions{})
klusterlet.Status = *newStatus
updatedKlusterlet, err := client.UpdateStatus(ctx, klusterlet, metav1.UpdateOptions{})
if err != nil {
return err
}
updatedSpokeClusterStatus = &updatedSpokeCluster.Status
updatedKlusterletStatus = &updatedKlusterlet.Status
updated = err == nil
return err
})
return updatedSpokeClusterStatus, updated, err
return updatedKlusterletStatus, updated, err
}
func UpdateNucleusSpokeConditionFn(conds ...nucleusapiv1.StatusCondition) UpdateNucleusSpokeStatusFunc {
return func(oldStatus *nucleusapiv1.SpokeCoreStatus) error {
func UpdateKlusterletConditionFn(conds ...operatorapiv1.StatusCondition) UpdateKlusterletStatusFunc {
return func(oldStatus *operatorapiv1.KlusterletStatus) error {
for _, cond := range conds {
SetNucleusCondition(&oldStatus.Conditions, cond)
SetOperatorCondition(&oldStatus.Conditions, cond)
}
return nil
}

View File

@@ -7,12 +7,13 @@ import (
"testing"
"time"
nucleusfake "github.com/open-cluster-management/api/client/nucleus/clientset/versioned/fake"
nucleusapiv1 "github.com/open-cluster-management/api/nucleus/v1"
opereatorfake "github.com/open-cluster-management/api/client/operator/clientset/versioned/fake"
operatorapiv1 "github.com/open-cluster-management/api/operator/v1"
"github.com/openshift/library-go/pkg/operator/events/eventstesting"
operatorhelpers "github.com/openshift/library-go/pkg/operator/v1helpers"
admissionv1 "k8s.io/api/admissionregistration/v1"
fakeapiextensions "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake"
"k8s.io/apimachinery/pkg/api/equality"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -29,52 +30,52 @@ func TestUpdateStatusCondition(t *testing.T) {
cases := []struct {
name string
startingConditions []nucleusapiv1.StatusCondition
newCondition nucleusapiv1.StatusCondition
startingConditions []operatorapiv1.StatusCondition
newCondition operatorapiv1.StatusCondition
expectedUpdated bool
expectedConditions []nucleusapiv1.StatusCondition
expectedConditions []operatorapiv1.StatusCondition
}{
{
name: "add to empty",
startingConditions: []nucleusapiv1.StatusCondition{},
startingConditions: []operatorapiv1.StatusCondition{},
newCondition: newCondition("test", "True", "my-reason", "my-message", nil),
expectedUpdated: true,
expectedConditions: []nucleusapiv1.StatusCondition{newCondition("test", "True", "my-reason", "my-message", nil)},
expectedConditions: []operatorapiv1.StatusCondition{newCondition("test", "True", "my-reason", "my-message", nil)},
},
{
name: "add to non-conflicting",
startingConditions: []nucleusapiv1.StatusCondition{
startingConditions: []operatorapiv1.StatusCondition{
newCondition("two", "True", "my-reason", "my-message", nil),
},
newCondition: newCondition("one", "True", "my-reason", "my-message", nil),
expectedUpdated: true,
expectedConditions: []nucleusapiv1.StatusCondition{
expectedConditions: []operatorapiv1.StatusCondition{
newCondition("two", "True", "my-reason", "my-message", nil),
newCondition("one", "True", "my-reason", "my-message", nil),
},
},
{
name: "change existing status",
startingConditions: []nucleusapiv1.StatusCondition{
startingConditions: []operatorapiv1.StatusCondition{
newCondition("two", "True", "my-reason", "my-message", nil),
newCondition("one", "True", "my-reason", "my-message", nil),
},
newCondition: newCondition("one", "False", "my-different-reason", "my-othermessage", nil),
expectedUpdated: true,
expectedConditions: []nucleusapiv1.StatusCondition{
expectedConditions: []operatorapiv1.StatusCondition{
newCondition("two", "True", "my-reason", "my-message", nil),
newCondition("one", "False", "my-different-reason", "my-othermessage", nil),
},
},
{
name: "leave existing transition time",
startingConditions: []nucleusapiv1.StatusCondition{
startingConditions: []operatorapiv1.StatusCondition{
newCondition("two", "True", "my-reason", "my-message", nil),
newCondition("one", "True", "my-reason", "my-message", &beforeish),
},
newCondition: newCondition("one", "True", "my-reason", "my-message", &afterish),
expectedUpdated: false,
expectedConditions: []nucleusapiv1.StatusCondition{
expectedConditions: []operatorapiv1.StatusCondition{
newCondition("two", "True", "my-reason", "my-message", nil),
newCondition("one", "True", "my-reason", "my-message", &beforeish),
},
@@ -83,26 +84,26 @@ func TestUpdateStatusCondition(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
fakeClusterClient := nucleusfake.NewSimpleClientset(
&nucleusapiv1.HubCore{
fakeOperatorClient := opereatorfake.NewSimpleClientset(
&operatorapiv1.ClusterManager{
ObjectMeta: metav1.ObjectMeta{Name: "testspokecluster"},
Status: nucleusapiv1.HubCoreStatus{
Status: operatorapiv1.ClusterManagerStatus{
Conditions: c.startingConditions,
},
},
&nucleusapiv1.SpokeCore{
&operatorapiv1.Klusterlet{
ObjectMeta: metav1.ObjectMeta{Name: "testspokecluster"},
Status: nucleusapiv1.SpokeCoreStatus{
Status: operatorapiv1.KlusterletStatus{
Conditions: c.startingConditions,
},
},
)
hubstatus, updated, err := UpdateNucleusHubStatus(
hubstatus, updated, err := UpdateClusterManagerStatus(
context.TODO(),
fakeClusterClient.NucleusV1().HubCores(),
fakeOperatorClient.OperatorV1().ClusterManagers(),
"testspokecluster",
UpdateNucleusHubConditionFn(c.newCondition),
UpdateClusterManagerConditionFn(c.newCondition),
)
if err != nil {
t.Errorf("unexpected err: %v", err)
@@ -111,11 +112,11 @@ func TestUpdateStatusCondition(t *testing.T) {
t.Errorf("expected %t, but %t", c.expectedUpdated, updated)
}
spokestatus, updated, err := UpdateNucleusSpokeStatus(
spokestatus, updated, err := UpdateKlusterletStatus(
context.TODO(),
fakeClusterClient.NucleusV1().SpokeCores(),
fakeOperatorClient.OperatorV1().Klusterlets(),
"testspokecluster",
UpdateNucleusSpokeConditionFn(c.newCondition),
UpdateKlusterletConditionFn(c.newCondition),
)
if err != nil {
t.Errorf("unexpected err: %v", err)
@@ -146,8 +147,8 @@ func TestUpdateStatusCondition(t *testing.T) {
}
}
func newCondition(name, status, reason, message string, lastTransition *metav1.Time) nucleusapiv1.StatusCondition {
ret := nucleusapiv1.StatusCondition{
func newCondition(name, status, reason, message string, lastTransition *metav1.Time) operatorapiv1.StatusCondition {
ret := operatorapiv1.StatusCondition{
Type: name,
Status: metav1.ConditionStatus(status),
Reason: reason,

View File

@@ -1,22 +1,21 @@
// Code generated by go-bindata.
// Code generated for package bindata by go-bindata DO NOT EDIT. (@generated)
// sources:
// manifests/hub/0000_00_clusters.open-cluster-management.io_spokeclusters.crd.yaml
// manifests/hub/0000_00_work.open-cluster-management.io_manifestworks.crd.yaml
// manifests/hub/hub-namespace.yaml
// manifests/hub/hub-registration-clusterrole.yaml
// manifests/hub/hub-registration-clusterrolebinding.yaml
// manifests/hub/hub-registration-deployment.yaml
// manifests/hub/hub-registration-serviceaccount.yaml
// manifests/hub/hub-registration-webhook-apiservice.yaml
// manifests/hub/hub-registration-webhook-clusterrole.yaml
// manifests/hub/hub-registration-webhook-clusterrolebinding.yaml
// manifests/hub/hub-registration-webhook-deployment.yaml
// manifests/hub/hub-registration-webhook-secret.yaml
// manifests/hub/hub-registration-webhook-service.yaml
// manifests/hub/hub-registration-webhook-serviceaccount.yaml
// manifests/hub/hub-registration-webhook-validatingconfiguration.yaml
// DO NOT EDIT!
// manifests/cluster-manager/0000_00_clusters.open-cluster-management.io_spokeclusters.crd.yaml
// manifests/cluster-manager/0000_00_work.open-cluster-management.io_manifestworks.crd.yaml
// manifests/cluster-manager/cluster-manager-clusterrolebinding.yaml
// manifests/cluster-manager/cluster-manager-namespace.yaml
// manifests/cluster-manager/cluster-manager-registration-clusterrole.yaml
// manifests/cluster-manager/cluster-manager-registration-clusterrolebinding.yaml
// manifests/cluster-manager/cluster-manager-registration-deployment.yaml
// manifests/cluster-manager/cluster-manager-registration-serviceaccount.yaml
// manifests/cluster-manager/cluster-manager-registration-webhook-apiservice.yaml
// manifests/cluster-manager/cluster-manager-registration-webhook-clusterrole.yaml
// manifests/cluster-manager/cluster-manager-registration-webhook-clusterrolebinding.yaml
// manifests/cluster-manager/cluster-manager-registration-webhook-deployment.yaml
// manifests/cluster-manager/cluster-manager-registration-webhook-secret.yaml
// manifests/cluster-manager/cluster-manager-registration-webhook-service.yaml
// manifests/cluster-manager/cluster-manager-registration-webhook-serviceaccount.yaml
// manifests/cluster-manager/cluster-manager-registration-webhook-validatingconfiguration.yaml
package bindata
import (
@@ -40,26 +39,37 @@ type bindataFileInfo struct {
modTime time.Time
}
// Name return file name
func (fi bindataFileInfo) Name() string {
return fi.name
}
// Size return file size
func (fi bindataFileInfo) Size() int64 {
return fi.size
}
// Mode return file mode
func (fi bindataFileInfo) Mode() os.FileMode {
return fi.mode
}
// Mode return file modify time
func (fi bindataFileInfo) ModTime() time.Time {
return fi.modTime
}
// IsDir return file whether a directory
func (fi bindataFileInfo) IsDir() bool {
return false
return fi.mode&os.ModeDir != 0
}
// Sys return file is sys mode
func (fi bindataFileInfo) Sys() interface{} {
return nil
}
var _manifestsHub0000_00_clustersOpenClusterManagementIo_spokeclustersCrdYaml = []byte(`apiVersion: apiextensions.k8s.io/v1beta1
var _manifestsClusterManager0000_00_clustersOpenClusterManagementIo_spokeclustersCrdYaml = []byte(`apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: spokeclusters.cluster.open-cluster-management.io
@@ -115,6 +125,12 @@ spec:
to grant the permision of access from agent on spoke. When the value
is set false, the namespace representing the spoke cluster is deleted.
type: boolean
leaseDurationSeconds:
description: LeaseDurationSeconds is used to coordinate the lease update
time of spoke agents. If its value is zero, the spoke agent will update
its lease per 60s by default
type: integer
format: int32
spokeClientConfigs:
description: SpokeClientConfigs represents a list of the apiserver address
of the spoke cluster. If it is empty, spoke cluster has no accessible
@@ -201,22 +217,22 @@ status:
storedVersions: []
`)
func manifestsHub0000_00_clustersOpenClusterManagementIo_spokeclustersCrdYamlBytes() ([]byte, error) {
return _manifestsHub0000_00_clustersOpenClusterManagementIo_spokeclustersCrdYaml, nil
func manifestsClusterManager0000_00_clustersOpenClusterManagementIo_spokeclustersCrdYamlBytes() ([]byte, error) {
return _manifestsClusterManager0000_00_clustersOpenClusterManagementIo_spokeclustersCrdYaml, nil
}
func manifestsHub0000_00_clustersOpenClusterManagementIo_spokeclustersCrdYaml() (*asset, error) {
bytes, err := manifestsHub0000_00_clustersOpenClusterManagementIo_spokeclustersCrdYamlBytes()
func manifestsClusterManager0000_00_clustersOpenClusterManagementIo_spokeclustersCrdYaml() (*asset, error) {
bytes, err := manifestsClusterManager0000_00_clustersOpenClusterManagementIo_spokeclustersCrdYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/hub/0000_00_clusters.open-cluster-management.io_spokeclusters.crd.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
info := bindataFileInfo{name: "manifests/cluster-manager/0000_00_clusters.open-cluster-management.io_spokeclusters.crd.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsHub0000_00_workOpenClusterManagementIo_manifestworksCrdYaml = []byte(`apiVersion: apiextensions.k8s.io/v1beta1
var _manifestsClusterManager0000_00_workOpenClusterManagementIo_manifestworksCrdYaml = []byte(`apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
creationTimestamp: null
@@ -277,6 +293,39 @@ spec:
description: Status represents the current status of work
type: object
properties:
appliedResources:
description: AppliedResources represents a list of resources defined
within the manifestwork that are applied. Only resources with valid
GroupVersionResource, namespace, and name are suitable. An item in
this slice is deleted when there is no mapped manifest in manifestwork.Spec
or by finalizer. The resource relating to the item will also be removed
from spoke cluster. The deleted resource may still be present until
the finalizers for that resource are finished. However, the resource
will not be undeleted, so it can be removed from this list and eventual
consistency is preserved.
type: array
items:
description: AppliedManifestResourceMeta represents the gvr, name
and namespace of a resource. Since these resources have been created,
they must have valid group, version, resource, namespace, and name.
type: object
properties:
group:
description: Group is the API Group of the kubernetes resource
type: string
name:
description: Name is the name of the kubernetes resource
type: string
namespace:
description: Name is the namespace of the kubernetes resource,
empty string indicates it is a cluster scoped resource.
type: string
resource:
description: Resource is the resource name of the kubernetes resource
type: string
version:
description: Version is the version of the kubernetes resource
type: string
conditions:
description: 'Conditions contains the different condition statuses for
this work. Valid condition types are: 1. Applied represents workload
@@ -404,46 +453,75 @@ status:
storedVersions: []
`)
func manifestsHub0000_00_workOpenClusterManagementIo_manifestworksCrdYamlBytes() ([]byte, error) {
return _manifestsHub0000_00_workOpenClusterManagementIo_manifestworksCrdYaml, nil
func manifestsClusterManager0000_00_workOpenClusterManagementIo_manifestworksCrdYamlBytes() ([]byte, error) {
return _manifestsClusterManager0000_00_workOpenClusterManagementIo_manifestworksCrdYaml, nil
}
func manifestsHub0000_00_workOpenClusterManagementIo_manifestworksCrdYaml() (*asset, error) {
bytes, err := manifestsHub0000_00_workOpenClusterManagementIo_manifestworksCrdYamlBytes()
func manifestsClusterManager0000_00_workOpenClusterManagementIo_manifestworksCrdYaml() (*asset, error) {
bytes, err := manifestsClusterManager0000_00_workOpenClusterManagementIo_manifestworksCrdYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/hub/0000_00_work.open-cluster-management.io_manifestworks.crd.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
info := bindataFileInfo{name: "manifests/cluster-manager/0000_00_work.open-cluster-management.io_manifestworks.crd.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsHubHubNamespaceYaml = []byte(`apiVersion: v1
kind: Namespace
var _manifestsClusterManagerClusterManagerClusterrolebindingYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ .HubCoreNamespace }}
name: system:open-cluster-management:{{ .ClusterManagerName }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:open-cluster-management:{{ .ClusterManagerName }}
subjects:
- kind: ServiceAccount
namespace: {{ .ClusterManagerNamespace }}
name: {{ .ClusterManagerName }}-sa
`)
func manifestsHubHubNamespaceYamlBytes() ([]byte, error) {
return _manifestsHubHubNamespaceYaml, nil
func manifestsClusterManagerClusterManagerClusterrolebindingYamlBytes() ([]byte, error) {
return _manifestsClusterManagerClusterManagerClusterrolebindingYaml, nil
}
func manifestsHubHubNamespaceYaml() (*asset, error) {
bytes, err := manifestsHubHubNamespaceYamlBytes()
func manifestsClusterManagerClusterManagerClusterrolebindingYaml() (*asset, error) {
bytes, err := manifestsClusterManagerClusterManagerClusterrolebindingYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/hub/hub-namespace.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
info := bindataFileInfo{name: "manifests/cluster-manager/cluster-manager-clusterrolebinding.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsHubHubRegistrationClusterroleYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1
var _manifestsClusterManagerClusterManagerNamespaceYaml = []byte(`apiVersion: v1
kind: Namespace
metadata:
name: {{ .ClusterManagerNamespace }}
`)
func manifestsClusterManagerClusterManagerNamespaceYamlBytes() ([]byte, error) {
return _manifestsClusterManagerClusterManagerNamespaceYaml, nil
}
func manifestsClusterManagerClusterManagerNamespaceYaml() (*asset, error) {
bytes, err := manifestsClusterManagerClusterManagerNamespaceYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/cluster-manager/cluster-manager-namespace.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsClusterManagerClusterManagerRegistrationClusterroleYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: system:open-cluster-management:{{ .HubCoreName }}-registration-controller
name: system:open-cluster-management:{{ .ClusterManagerName }}-registration-controller
rules:
# Allow hub to monitor and update status of csr
- apiGroups: ["certificates.k8s.io"]
@@ -478,68 +556,68 @@ rules:
verbs: ["update", "patch"]
`)
func manifestsHubHubRegistrationClusterroleYamlBytes() ([]byte, error) {
return _manifestsHubHubRegistrationClusterroleYaml, nil
func manifestsClusterManagerClusterManagerRegistrationClusterroleYamlBytes() ([]byte, error) {
return _manifestsClusterManagerClusterManagerRegistrationClusterroleYaml, nil
}
func manifestsHubHubRegistrationClusterroleYaml() (*asset, error) {
bytes, err := manifestsHubHubRegistrationClusterroleYamlBytes()
func manifestsClusterManagerClusterManagerRegistrationClusterroleYaml() (*asset, error) {
bytes, err := manifestsClusterManagerClusterManagerRegistrationClusterroleYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/hub/hub-registration-clusterrole.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
info := bindataFileInfo{name: "manifests/cluster-manager/cluster-manager-registration-clusterrole.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsHubHubRegistrationClusterrolebindingYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1
var _manifestsClusterManagerClusterManagerRegistrationClusterrolebindingYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:open-cluster-management:{{ .HubCoreName }}-registration-controller
name: system:open-cluster-management:{{ .ClusterManagerName }}-registration-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:open-cluster-management:{{ .HubCoreName }}-registration-controller
name: system:open-cluster-management:{{ .ClusterManagerName }}-registration-controller
subjects:
- kind: ServiceAccount
namespace: {{ .HubCoreNamespace }}
name: {{ .HubCoreName }}-registration-controller-sa
namespace: {{ .ClusterManagerNamespace }}
name: {{ .ClusterManagerName }}-registration-controller-sa
`)
func manifestsHubHubRegistrationClusterrolebindingYamlBytes() ([]byte, error) {
return _manifestsHubHubRegistrationClusterrolebindingYaml, nil
func manifestsClusterManagerClusterManagerRegistrationClusterrolebindingYamlBytes() ([]byte, error) {
return _manifestsClusterManagerClusterManagerRegistrationClusterrolebindingYaml, nil
}
func manifestsHubHubRegistrationClusterrolebindingYaml() (*asset, error) {
bytes, err := manifestsHubHubRegistrationClusterrolebindingYamlBytes()
func manifestsClusterManagerClusterManagerRegistrationClusterrolebindingYaml() (*asset, error) {
bytes, err := manifestsClusterManagerClusterManagerRegistrationClusterrolebindingYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/hub/hub-registration-clusterrolebinding.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
info := bindataFileInfo{name: "manifests/cluster-manager/cluster-manager-registration-clusterrolebinding.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsHubHubRegistrationDeploymentYaml = []byte(`kind: Deployment
var _manifestsClusterManagerClusterManagerRegistrationDeploymentYaml = []byte(`kind: Deployment
apiVersion: apps/v1
metadata:
name: {{ .HubCoreName }}-registration-controller
namespace: {{ .HubCoreNamespace }}
name: {{ .ClusterManagerName }}-registration-controller
namespace: {{ .ClusterManagerNamespace }}
labels:
app: nucleushub-registration-controller
app: clustermanager-controller
spec:
replicas: 3
selector:
matchLabels:
app: nucleushub-registration-controller
app: clustermanager-registration-controller
template:
metadata:
labels:
app: nucleushub-registration-controller
app: clustermanager-registration-controller
spec:
serviceAccountName: {{ .HubCoreName }}-registration-controller-sa
serviceAccountName: {{ .ClusterManagerName }}-registration-controller-sa
containers:
- name: hub-registration-controller
image: {{ .RegistrationImage }}
@@ -562,44 +640,44 @@ spec:
initialDelaySeconds: 2
`)
func manifestsHubHubRegistrationDeploymentYamlBytes() ([]byte, error) {
return _manifestsHubHubRegistrationDeploymentYaml, nil
func manifestsClusterManagerClusterManagerRegistrationDeploymentYamlBytes() ([]byte, error) {
return _manifestsClusterManagerClusterManagerRegistrationDeploymentYaml, nil
}
func manifestsHubHubRegistrationDeploymentYaml() (*asset, error) {
bytes, err := manifestsHubHubRegistrationDeploymentYamlBytes()
func manifestsClusterManagerClusterManagerRegistrationDeploymentYaml() (*asset, error) {
bytes, err := manifestsClusterManagerClusterManagerRegistrationDeploymentYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/hub/hub-registration-deployment.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
info := bindataFileInfo{name: "manifests/cluster-manager/cluster-manager-registration-deployment.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsHubHubRegistrationServiceaccountYaml = []byte(`apiVersion: v1
var _manifestsClusterManagerClusterManagerRegistrationServiceaccountYaml = []byte(`apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .HubCoreName }}-registration-controller-sa
namespace: {{ .HubCoreNamespace }}
name: {{ .ClusterManagerName }}-registration-controller-sa
namespace: {{ .ClusterManagerNamespace }}
`)
func manifestsHubHubRegistrationServiceaccountYamlBytes() ([]byte, error) {
return _manifestsHubHubRegistrationServiceaccountYaml, nil
func manifestsClusterManagerClusterManagerRegistrationServiceaccountYamlBytes() ([]byte, error) {
return _manifestsClusterManagerClusterManagerRegistrationServiceaccountYaml, nil
}
func manifestsHubHubRegistrationServiceaccountYaml() (*asset, error) {
bytes, err := manifestsHubHubRegistrationServiceaccountYamlBytes()
func manifestsClusterManagerClusterManagerRegistrationServiceaccountYaml() (*asset, error) {
bytes, err := manifestsClusterManagerClusterManagerRegistrationServiceaccountYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/hub/hub-registration-serviceaccount.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
info := bindataFileInfo{name: "manifests/cluster-manager/cluster-manager-registration-serviceaccount.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsHubHubRegistrationWebhookApiserviceYaml = []byte(`apiVersion: apiregistration.k8s.io/v1
var _manifestsClusterManagerClusterManagerRegistrationWebhookApiserviceYaml = []byte(`apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
name: v1.admission.cluster.open-cluster-management.io
@@ -607,32 +685,32 @@ spec:
group: admission.cluster.open-cluster-management.io
version: v1
service:
name: {{ .HubCoreWebhookRegistrationService }}
namespace: {{ .HubCoreNamespace }}
name: {{ .ClusterManagerWebhookRegistrationService }}
namespace: {{ .ClusterManagerNamespace }}
caBundle: {{ .RegistrationAPIServiceCABundle }}
groupPriorityMinimum: 10000
versionPriority: 20
`)
func manifestsHubHubRegistrationWebhookApiserviceYamlBytes() ([]byte, error) {
return _manifestsHubHubRegistrationWebhookApiserviceYaml, nil
func manifestsClusterManagerClusterManagerRegistrationWebhookApiserviceYamlBytes() ([]byte, error) {
return _manifestsClusterManagerClusterManagerRegistrationWebhookApiserviceYaml, nil
}
func manifestsHubHubRegistrationWebhookApiserviceYaml() (*asset, error) {
bytes, err := manifestsHubHubRegistrationWebhookApiserviceYamlBytes()
func manifestsClusterManagerClusterManagerRegistrationWebhookApiserviceYaml() (*asset, error) {
bytes, err := manifestsClusterManagerClusterManagerRegistrationWebhookApiserviceYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/hub/hub-registration-webhook-apiservice.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
info := bindataFileInfo{name: "manifests/cluster-manager/cluster-manager-registration-webhook-apiservice.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsHubHubRegistrationWebhookClusterroleYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1
var _manifestsClusterManagerClusterManagerRegistrationWebhookClusterroleYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: system:open-cluster-management:{{ .HubCoreName }}-registration-webhook
name: system:open-cluster-management:{{ .ClusterManagerName }}-registration-webhook
rules:
# Allow spokecluster admission to get/list/watch configmaps
- apiGroups: [""]
@@ -644,70 +722,70 @@ rules:
verbs: ["create"]
`)
func manifestsHubHubRegistrationWebhookClusterroleYamlBytes() ([]byte, error) {
return _manifestsHubHubRegistrationWebhookClusterroleYaml, nil
func manifestsClusterManagerClusterManagerRegistrationWebhookClusterroleYamlBytes() ([]byte, error) {
return _manifestsClusterManagerClusterManagerRegistrationWebhookClusterroleYaml, nil
}
func manifestsHubHubRegistrationWebhookClusterroleYaml() (*asset, error) {
bytes, err := manifestsHubHubRegistrationWebhookClusterroleYamlBytes()
func manifestsClusterManagerClusterManagerRegistrationWebhookClusterroleYaml() (*asset, error) {
bytes, err := manifestsClusterManagerClusterManagerRegistrationWebhookClusterroleYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/hub/hub-registration-webhook-clusterrole.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
info := bindataFileInfo{name: "manifests/cluster-manager/cluster-manager-registration-webhook-clusterrole.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsHubHubRegistrationWebhookClusterrolebindingYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1
var _manifestsClusterManagerClusterManagerRegistrationWebhookClusterrolebindingYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:open-cluster-management:{{ .HubCoreName }}-registration-webhook
name: system:open-cluster-management:{{ .ClusterManagerName }}-registration-webhook
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ .HubCoreName }}-registration-webhook
name: system:open-cluster-management:{{ .ClusterManagerName }}-registration-webhook
subjects:
- kind: ServiceAccount
name: {{ .HubCoreName }}-registration-webhook-sa
namespace: {{ .HubCoreNamespace }}
name: {{ .ClusterManagerName }}-registration-webhook-sa
namespace: {{ .ClusterManagerNamespace }}
`)
func manifestsHubHubRegistrationWebhookClusterrolebindingYamlBytes() ([]byte, error) {
return _manifestsHubHubRegistrationWebhookClusterrolebindingYaml, nil
func manifestsClusterManagerClusterManagerRegistrationWebhookClusterrolebindingYamlBytes() ([]byte, error) {
return _manifestsClusterManagerClusterManagerRegistrationWebhookClusterrolebindingYaml, nil
}
func manifestsHubHubRegistrationWebhookClusterrolebindingYaml() (*asset, error) {
bytes, err := manifestsHubHubRegistrationWebhookClusterrolebindingYamlBytes()
func manifestsClusterManagerClusterManagerRegistrationWebhookClusterrolebindingYaml() (*asset, error) {
bytes, err := manifestsClusterManagerClusterManagerRegistrationWebhookClusterrolebindingYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/hub/hub-registration-webhook-clusterrolebinding.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
info := bindataFileInfo{name: "manifests/cluster-manager/cluster-manager-registration-webhook-clusterrolebinding.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsHubHubRegistrationWebhookDeploymentYaml = []byte(`apiVersion: apps/v1
var _manifestsClusterManagerClusterManagerRegistrationWebhookDeploymentYaml = []byte(`apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .HubCoreName }}-registration-webhook
namespace: {{ .HubCoreNamespace }}
name: {{ .ClusterManagerName }}-registration-webhook
namespace: {{ .ClusterManagerNamespace }}
labels:
app: {{ .HubCoreName }}-registration-webhook
app: {{ .ClusterManagerName }}-registration-webhook
spec:
replicas: 3
selector:
matchLabels:
app: {{ .HubCoreName }}-registration-webhook
app: {{ .ClusterManagerName }}-registration-webhook
template:
metadata:
labels:
app: {{ .HubCoreName }}-registration-webhook
app: {{ .ClusterManagerName }}-registration-webhook
spec:
serviceAccountName: {{ .HubCoreName }}-registration-webhook-sa
serviceAccountName: {{ .ClusterManagerName }}-registration-webhook-sa
containers:
- name: {{ .HubCoreName }}-registration-webhook-sa
- name: {{ .ClusterManagerName }}-registration-webhook-sa
image: {{ .RegistrationImage }}
imagePullPolicy: IfNotPresent
args:
@@ -736,30 +814,30 @@ spec:
volumes:
- name: webhook-secret
secret:
secretName: {{ .HubCoreWebhookSecret }}
secretName: {{ .ClusterManagerWebhookSecret }}
`)
func manifestsHubHubRegistrationWebhookDeploymentYamlBytes() ([]byte, error) {
return _manifestsHubHubRegistrationWebhookDeploymentYaml, nil
func manifestsClusterManagerClusterManagerRegistrationWebhookDeploymentYamlBytes() ([]byte, error) {
return _manifestsClusterManagerClusterManagerRegistrationWebhookDeploymentYaml, nil
}
func manifestsHubHubRegistrationWebhookDeploymentYaml() (*asset, error) {
bytes, err := manifestsHubHubRegistrationWebhookDeploymentYamlBytes()
func manifestsClusterManagerClusterManagerRegistrationWebhookDeploymentYaml() (*asset, error) {
bytes, err := manifestsClusterManagerClusterManagerRegistrationWebhookDeploymentYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/hub/hub-registration-webhook-deployment.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
info := bindataFileInfo{name: "manifests/cluster-manager/cluster-manager-registration-webhook-deployment.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsHubHubRegistrationWebhookSecretYaml = []byte(`apiVersion: v1
var _manifestsClusterManagerClusterManagerRegistrationWebhookSecretYaml = []byte(`apiVersion: v1
kind: Secret
metadata:
name: {{ .HubCoreWebhookSecret }}
namespace: {{ .HubCoreNamespace }}
name: {{ .ClusterManagerWebhookSecret }}
namespace: {{ .ClusterManagerNamespace }}
data:
tls.crt: {{ .RegistrationServingCert }}
tls.key: {{ .RegistrationServingKey }}
@@ -767,72 +845,72 @@ data:
type: Opaque
`)
func manifestsHubHubRegistrationWebhookSecretYamlBytes() ([]byte, error) {
return _manifestsHubHubRegistrationWebhookSecretYaml, nil
func manifestsClusterManagerClusterManagerRegistrationWebhookSecretYamlBytes() ([]byte, error) {
return _manifestsClusterManagerClusterManagerRegistrationWebhookSecretYaml, nil
}
func manifestsHubHubRegistrationWebhookSecretYaml() (*asset, error) {
bytes, err := manifestsHubHubRegistrationWebhookSecretYamlBytes()
func manifestsClusterManagerClusterManagerRegistrationWebhookSecretYaml() (*asset, error) {
bytes, err := manifestsClusterManagerClusterManagerRegistrationWebhookSecretYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/hub/hub-registration-webhook-secret.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
info := bindataFileInfo{name: "manifests/cluster-manager/cluster-manager-registration-webhook-secret.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsHubHubRegistrationWebhookServiceYaml = []byte(`apiVersion: v1
var _manifestsClusterManagerClusterManagerRegistrationWebhookServiceYaml = []byte(`apiVersion: v1
kind: Service
metadata:
name: {{ .HubCoreWebhookRegistrationService }}
namespace: {{ .HubCoreNamespace }}
name: {{ .ClusterManagerWebhookRegistrationService }}
namespace: {{ .ClusterManagerNamespace }}
spec:
selector:
app: {{ .HubCoreName }}-registration-webhook
app: {{ .ClusterManagerName }}-registration-webhook
ports:
- port: 443
targetPort: 6443
`)
func manifestsHubHubRegistrationWebhookServiceYamlBytes() ([]byte, error) {
return _manifestsHubHubRegistrationWebhookServiceYaml, nil
func manifestsClusterManagerClusterManagerRegistrationWebhookServiceYamlBytes() ([]byte, error) {
return _manifestsClusterManagerClusterManagerRegistrationWebhookServiceYaml, nil
}
func manifestsHubHubRegistrationWebhookServiceYaml() (*asset, error) {
bytes, err := manifestsHubHubRegistrationWebhookServiceYamlBytes()
func manifestsClusterManagerClusterManagerRegistrationWebhookServiceYaml() (*asset, error) {
bytes, err := manifestsClusterManagerClusterManagerRegistrationWebhookServiceYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/hub/hub-registration-webhook-service.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
info := bindataFileInfo{name: "manifests/cluster-manager/cluster-manager-registration-webhook-service.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsHubHubRegistrationWebhookServiceaccountYaml = []byte(`apiVersion: v1
var _manifestsClusterManagerClusterManagerRegistrationWebhookServiceaccountYaml = []byte(`apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .HubCoreName }}-registration-webhook-sa
namespace: {{ .HubCoreNamespace }}
name: {{ .ClusterManagerName }}-registration-webhook-sa
namespace: {{ .ClusterManagerNamespace }}
`)
func manifestsHubHubRegistrationWebhookServiceaccountYamlBytes() ([]byte, error) {
return _manifestsHubHubRegistrationWebhookServiceaccountYaml, nil
func manifestsClusterManagerClusterManagerRegistrationWebhookServiceaccountYamlBytes() ([]byte, error) {
return _manifestsClusterManagerClusterManagerRegistrationWebhookServiceaccountYaml, nil
}
func manifestsHubHubRegistrationWebhookServiceaccountYaml() (*asset, error) {
bytes, err := manifestsHubHubRegistrationWebhookServiceaccountYamlBytes()
func manifestsClusterManagerClusterManagerRegistrationWebhookServiceaccountYaml() (*asset, error) {
bytes, err := manifestsClusterManagerClusterManagerRegistrationWebhookServiceaccountYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/hub/hub-registration-webhook-serviceaccount.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
info := bindataFileInfo{name: "manifests/cluster-manager/cluster-manager-registration-webhook-serviceaccount.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsHubHubRegistrationWebhookValidatingconfigurationYaml = []byte(`apiVersion: admissionregistration.k8s.io/v1
var _manifestsClusterManagerClusterManagerRegistrationWebhookValidatingconfigurationYaml = []byte(`apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: spokeclustervalidators.admission.cluster.open-cluster-management.io
@@ -860,17 +938,17 @@ webhooks:
timeoutSeconds: 3
`)
func manifestsHubHubRegistrationWebhookValidatingconfigurationYamlBytes() ([]byte, error) {
return _manifestsHubHubRegistrationWebhookValidatingconfigurationYaml, nil
func manifestsClusterManagerClusterManagerRegistrationWebhookValidatingconfigurationYamlBytes() ([]byte, error) {
return _manifestsClusterManagerClusterManagerRegistrationWebhookValidatingconfigurationYaml, nil
}
func manifestsHubHubRegistrationWebhookValidatingconfigurationYaml() (*asset, error) {
bytes, err := manifestsHubHubRegistrationWebhookValidatingconfigurationYamlBytes()
func manifestsClusterManagerClusterManagerRegistrationWebhookValidatingconfigurationYaml() (*asset, error) {
bytes, err := manifestsClusterManagerClusterManagerRegistrationWebhookValidatingconfigurationYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/hub/hub-registration-webhook-validatingconfiguration.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
info := bindataFileInfo{name: "manifests/cluster-manager/cluster-manager-registration-webhook-validatingconfiguration.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
@@ -927,21 +1005,22 @@ func AssetNames() []string {
// _bindata is a table, holding each asset generator, mapped to its name.
var _bindata = map[string]func() (*asset, error){
"manifests/hub/0000_00_clusters.open-cluster-management.io_spokeclusters.crd.yaml": manifestsHub0000_00_clustersOpenClusterManagementIo_spokeclustersCrdYaml,
"manifests/hub/0000_00_work.open-cluster-management.io_manifestworks.crd.yaml": manifestsHub0000_00_workOpenClusterManagementIo_manifestworksCrdYaml,
"manifests/hub/hub-namespace.yaml": manifestsHubHubNamespaceYaml,
"manifests/hub/hub-registration-clusterrole.yaml": manifestsHubHubRegistrationClusterroleYaml,
"manifests/hub/hub-registration-clusterrolebinding.yaml": manifestsHubHubRegistrationClusterrolebindingYaml,
"manifests/hub/hub-registration-deployment.yaml": manifestsHubHubRegistrationDeploymentYaml,
"manifests/hub/hub-registration-serviceaccount.yaml": manifestsHubHubRegistrationServiceaccountYaml,
"manifests/hub/hub-registration-webhook-apiservice.yaml": manifestsHubHubRegistrationWebhookApiserviceYaml,
"manifests/hub/hub-registration-webhook-clusterrole.yaml": manifestsHubHubRegistrationWebhookClusterroleYaml,
"manifests/hub/hub-registration-webhook-clusterrolebinding.yaml": manifestsHubHubRegistrationWebhookClusterrolebindingYaml,
"manifests/hub/hub-registration-webhook-deployment.yaml": manifestsHubHubRegistrationWebhookDeploymentYaml,
"manifests/hub/hub-registration-webhook-secret.yaml": manifestsHubHubRegistrationWebhookSecretYaml,
"manifests/hub/hub-registration-webhook-service.yaml": manifestsHubHubRegistrationWebhookServiceYaml,
"manifests/hub/hub-registration-webhook-serviceaccount.yaml": manifestsHubHubRegistrationWebhookServiceaccountYaml,
"manifests/hub/hub-registration-webhook-validatingconfiguration.yaml": manifestsHubHubRegistrationWebhookValidatingconfigurationYaml,
"manifests/cluster-manager/0000_00_clusters.open-cluster-management.io_spokeclusters.crd.yaml": manifestsClusterManager0000_00_clustersOpenClusterManagementIo_spokeclustersCrdYaml,
"manifests/cluster-manager/0000_00_work.open-cluster-management.io_manifestworks.crd.yaml": manifestsClusterManager0000_00_workOpenClusterManagementIo_manifestworksCrdYaml,
"manifests/cluster-manager/cluster-manager-clusterrolebinding.yaml": manifestsClusterManagerClusterManagerClusterrolebindingYaml,
"manifests/cluster-manager/cluster-manager-namespace.yaml": manifestsClusterManagerClusterManagerNamespaceYaml,
"manifests/cluster-manager/cluster-manager-registration-clusterrole.yaml": manifestsClusterManagerClusterManagerRegistrationClusterroleYaml,
"manifests/cluster-manager/cluster-manager-registration-clusterrolebinding.yaml": manifestsClusterManagerClusterManagerRegistrationClusterrolebindingYaml,
"manifests/cluster-manager/cluster-manager-registration-deployment.yaml": manifestsClusterManagerClusterManagerRegistrationDeploymentYaml,
"manifests/cluster-manager/cluster-manager-registration-serviceaccount.yaml": manifestsClusterManagerClusterManagerRegistrationServiceaccountYaml,
"manifests/cluster-manager/cluster-manager-registration-webhook-apiservice.yaml": manifestsClusterManagerClusterManagerRegistrationWebhookApiserviceYaml,
"manifests/cluster-manager/cluster-manager-registration-webhook-clusterrole.yaml": manifestsClusterManagerClusterManagerRegistrationWebhookClusterroleYaml,
"manifests/cluster-manager/cluster-manager-registration-webhook-clusterrolebinding.yaml": manifestsClusterManagerClusterManagerRegistrationWebhookClusterrolebindingYaml,
"manifests/cluster-manager/cluster-manager-registration-webhook-deployment.yaml": manifestsClusterManagerClusterManagerRegistrationWebhookDeploymentYaml,
"manifests/cluster-manager/cluster-manager-registration-webhook-secret.yaml": manifestsClusterManagerClusterManagerRegistrationWebhookSecretYaml,
"manifests/cluster-manager/cluster-manager-registration-webhook-service.yaml": manifestsClusterManagerClusterManagerRegistrationWebhookServiceYaml,
"manifests/cluster-manager/cluster-manager-registration-webhook-serviceaccount.yaml": manifestsClusterManagerClusterManagerRegistrationWebhookServiceaccountYaml,
"manifests/cluster-manager/cluster-manager-registration-webhook-validatingconfiguration.yaml": manifestsClusterManagerClusterManagerRegistrationWebhookValidatingconfigurationYaml,
}
// AssetDir returns the file names below a certain
@@ -986,22 +1065,23 @@ type bintree struct {
var _bintree = &bintree{nil, map[string]*bintree{
"manifests": {nil, map[string]*bintree{
"hub": {nil, map[string]*bintree{
"0000_00_clusters.open-cluster-management.io_spokeclusters.crd.yaml": {manifestsHub0000_00_clustersOpenClusterManagementIo_spokeclustersCrdYaml, map[string]*bintree{}},
"0000_00_work.open-cluster-management.io_manifestworks.crd.yaml": {manifestsHub0000_00_workOpenClusterManagementIo_manifestworksCrdYaml, map[string]*bintree{}},
"hub-namespace.yaml": {manifestsHubHubNamespaceYaml, map[string]*bintree{}},
"hub-registration-clusterrole.yaml": {manifestsHubHubRegistrationClusterroleYaml, map[string]*bintree{}},
"hub-registration-clusterrolebinding.yaml": {manifestsHubHubRegistrationClusterrolebindingYaml, map[string]*bintree{}},
"hub-registration-deployment.yaml": {manifestsHubHubRegistrationDeploymentYaml, map[string]*bintree{}},
"hub-registration-serviceaccount.yaml": {manifestsHubHubRegistrationServiceaccountYaml, map[string]*bintree{}},
"hub-registration-webhook-apiservice.yaml": {manifestsHubHubRegistrationWebhookApiserviceYaml, map[string]*bintree{}},
"hub-registration-webhook-clusterrole.yaml": {manifestsHubHubRegistrationWebhookClusterroleYaml, map[string]*bintree{}},
"hub-registration-webhook-clusterrolebinding.yaml": {manifestsHubHubRegistrationWebhookClusterrolebindingYaml, map[string]*bintree{}},
"hub-registration-webhook-deployment.yaml": {manifestsHubHubRegistrationWebhookDeploymentYaml, map[string]*bintree{}},
"hub-registration-webhook-secret.yaml": {manifestsHubHubRegistrationWebhookSecretYaml, map[string]*bintree{}},
"hub-registration-webhook-service.yaml": {manifestsHubHubRegistrationWebhookServiceYaml, map[string]*bintree{}},
"hub-registration-webhook-serviceaccount.yaml": {manifestsHubHubRegistrationWebhookServiceaccountYaml, map[string]*bintree{}},
"hub-registration-webhook-validatingconfiguration.yaml": {manifestsHubHubRegistrationWebhookValidatingconfigurationYaml, map[string]*bintree{}},
"cluster-manager": {nil, map[string]*bintree{
"0000_00_clusters.open-cluster-management.io_spokeclusters.crd.yaml": {manifestsClusterManager0000_00_clustersOpenClusterManagementIo_spokeclustersCrdYaml, map[string]*bintree{}},
"0000_00_work.open-cluster-management.io_manifestworks.crd.yaml": {manifestsClusterManager0000_00_workOpenClusterManagementIo_manifestworksCrdYaml, map[string]*bintree{}},
"cluster-manager-clusterrolebinding.yaml": {manifestsClusterManagerClusterManagerClusterrolebindingYaml, map[string]*bintree{}},
"cluster-manager-namespace.yaml": {manifestsClusterManagerClusterManagerNamespaceYaml, map[string]*bintree{}},
"cluster-manager-registration-clusterrole.yaml": {manifestsClusterManagerClusterManagerRegistrationClusterroleYaml, map[string]*bintree{}},
"cluster-manager-registration-clusterrolebinding.yaml": {manifestsClusterManagerClusterManagerRegistrationClusterrolebindingYaml, map[string]*bintree{}},
"cluster-manager-registration-deployment.yaml": {manifestsClusterManagerClusterManagerRegistrationDeploymentYaml, map[string]*bintree{}},
"cluster-manager-registration-serviceaccount.yaml": {manifestsClusterManagerClusterManagerRegistrationServiceaccountYaml, map[string]*bintree{}},
"cluster-manager-registration-webhook-apiservice.yaml": {manifestsClusterManagerClusterManagerRegistrationWebhookApiserviceYaml, map[string]*bintree{}},
"cluster-manager-registration-webhook-clusterrole.yaml": {manifestsClusterManagerClusterManagerRegistrationWebhookClusterroleYaml, map[string]*bintree{}},
"cluster-manager-registration-webhook-clusterrolebinding.yaml": {manifestsClusterManagerClusterManagerRegistrationWebhookClusterrolebindingYaml, map[string]*bintree{}},
"cluster-manager-registration-webhook-deployment.yaml": {manifestsClusterManagerClusterManagerRegistrationWebhookDeploymentYaml, map[string]*bintree{}},
"cluster-manager-registration-webhook-secret.yaml": {manifestsClusterManagerClusterManagerRegistrationWebhookSecretYaml, map[string]*bintree{}},
"cluster-manager-registration-webhook-service.yaml": {manifestsClusterManagerClusterManagerRegistrationWebhookServiceYaml, map[string]*bintree{}},
"cluster-manager-registration-webhook-serviceaccount.yaml": {manifestsClusterManagerClusterManagerRegistrationWebhookServiceaccountYaml, map[string]*bintree{}},
"cluster-manager-registration-webhook-validatingconfiguration.yaml": {manifestsClusterManagerClusterManagerRegistrationWebhookValidatingconfigurationYaml, map[string]*bintree{}},
}},
}},
}}

View File

@@ -1,4 +1,4 @@
package hub
package clustermanager
import (
"context"
@@ -23,12 +23,12 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
nucleusv1client "github.com/open-cluster-management/api/client/nucleus/clientset/versioned/typed/nucleus/v1"
nucleusinformer "github.com/open-cluster-management/api/client/nucleus/informers/externalversions/nucleus/v1"
nucleuslister "github.com/open-cluster-management/api/client/nucleus/listers/nucleus/v1"
nucleusapiv1 "github.com/open-cluster-management/api/nucleus/v1"
operatorv1client "github.com/open-cluster-management/api/client/operator/clientset/versioned/typed/operator/v1"
operatorinformer "github.com/open-cluster-management/api/client/operator/informers/externalversions/operator/v1"
operatorlister "github.com/open-cluster-management/api/client/operator/listers/operator/v1"
operatorapiv1 "github.com/open-cluster-management/api/operator/v1"
"github.com/open-cluster-management/nucleus/pkg/helpers"
"github.com/open-cluster-management/nucleus/pkg/operators/hub/bindata"
"github.com/open-cluster-management/nucleus/pkg/operators/clustermanager/bindata"
)
var (
@@ -37,58 +37,58 @@ var (
"spokeclusters.cluster.open-cluster-management.io",
}
staticResourceFiles = []string{
"manifests/hub/0000_00_clusters.open-cluster-management.io_spokeclusters.crd.yaml",
"manifests/hub/0000_00_work.open-cluster-management.io_manifestworks.crd.yaml",
"manifests/hub/hub-registration-clusterrole.yaml",
"manifests/hub/hub-registration-clusterrolebinding.yaml",
"manifests/hub/hub-namespace.yaml",
"manifests/hub/hub-registration-serviceaccount.yaml",
"manifests/hub/hub-registration-webhook-clusterrole.yaml",
"manifests/hub/hub-registration-webhook-clusterrolebinding.yaml",
"manifests/hub/hub-registration-webhook-service.yaml",
"manifests/hub/hub-registration-webhook-serviceaccount.yaml",
"manifests/hub/hub-registration-webhook-apiservice.yaml",
"manifests/hub/hub-registration-webhook-secret.yaml",
"manifests/hub/hub-registration-webhook-validatingconfiguration.yaml",
"manifests/cluster-manager/0000_00_clusters.open-cluster-management.io_spokeclusters.crd.yaml",
"manifests/cluster-manager/0000_00_work.open-cluster-management.io_manifestworks.crd.yaml",
"manifests/cluster-manager/cluster-manager-registration-clusterrole.yaml",
"manifests/cluster-manager/cluster-manager-registration-clusterrolebinding.yaml",
"manifests/cluster-manager/cluster-manager-namespace.yaml",
"manifests/cluster-manager/cluster-manager-registration-serviceaccount.yaml",
"manifests/cluster-manager/cluster-manager-registration-webhook-clusterrole.yaml",
"manifests/cluster-manager/cluster-manager-registration-webhook-clusterrolebinding.yaml",
"manifests/cluster-manager/cluster-manager-registration-webhook-service.yaml",
"manifests/cluster-manager/cluster-manager-registration-webhook-serviceaccount.yaml",
"manifests/cluster-manager/cluster-manager-registration-webhook-apiservice.yaml",
"manifests/cluster-manager/cluster-manager-registration-webhook-secret.yaml",
"manifests/cluster-manager/cluster-manager-registration-webhook-validatingconfiguration.yaml",
}
deploymentFiles = []string{
"manifests/hub/hub-registration-deployment.yaml",
"manifests/hub/hub-registration-webhook-deployment.yaml",
"manifests/cluster-manager/cluster-manager-registration-deployment.yaml",
"manifests/cluster-manager/cluster-manager-registration-webhook-deployment.yaml",
}
)
const (
nucleusHubFinalizer = "nucleus.open-cluster-management.io/hub-core-cleanup"
nucleusHubCoreNamespace = "open-cluster-management-hub"
nucleusHubCoreWebhookSecret = "webhook-serving-cert"
hubCoreApplied = "Applied"
hubCoreAvailable = "Available"
clusterManagerFinalizer = "operator.open-cluster-management.io/cluster-manager-cleanup"
clusterManagerNamespace = "open-cluster-management-hub"
clusterManagerWebhookSecret = "webhook-serving-cert"
clusterManagerApplied = "Applied"
clusterManagerAvailable = "Available"
)
type nucleusHubController struct {
nucleusClient nucleusv1client.HubCoreInterface
nucleusLister nucleuslister.HubCoreLister
type clusterManagerController struct {
clusterManagerClient operatorv1client.ClusterManagerInterface
clusterManagerLister operatorlister.ClusterManagerLister
kubeClient kubernetes.Interface
apiExtensionClient apiextensionsclient.Interface
apiRegistrationClient apiregistrationclient.APIServicesGetter
currentGeneration []int64
}
// NewNucleusHubController construct nucleus hub controller
func NewNucleusHubController(
// NewClusterManagerController construct cluster manager hub controller
func NewClusterManagerController(
kubeClient kubernetes.Interface,
apiExtensionClient apiextensionsclient.Interface,
apiRegistrationClient apiregistrationclient.APIServicesGetter,
nucleusClient nucleusv1client.HubCoreInterface,
nucleusInformer nucleusinformer.HubCoreInformer,
clusterManagerClient operatorv1client.ClusterManagerInterface,
clusterManagerInformer operatorinformer.ClusterManagerInformer,
recorder events.Recorder) factory.Controller {
controller := &nucleusHubController{
controller := &clusterManagerController{
kubeClient: kubeClient,
apiExtensionClient: apiExtensionClient,
apiRegistrationClient: apiRegistrationClient,
nucleusClient: nucleusClient,
nucleusLister: nucleusInformer.Lister(),
clusterManagerClient: clusterManagerClient,
clusterManagerLister: clusterManagerInformer.Lister(),
currentGeneration: make([]int64, len(deploymentFiles)),
}
@@ -97,70 +97,70 @@ func NewNucleusHubController(
WithInformersQueueKeyFunc(func(obj runtime.Object) string {
accessor, _ := meta.Accessor(obj)
return accessor.GetName()
}, nucleusInformer.Informer()).
ToController("NucleusHubController", recorder)
}, clusterManagerInformer.Informer()).
ToController("ClusterManagerController", recorder)
}
// hubConfig is used to render the template of hub manifests
type hubConfig struct {
HubCoreName string
HubCoreNamespace string
RegistrationImage string
HubCoreWebhookSecret string
HubCoreWebhookRegistrationService string
RegistrationAPIServiceCABundle string
RegistrationServingCert string
RegistrationServingKey string
ClusterManagerName string
ClusterManagerNamespace string
RegistrationImage string
ClusterManagerWebhookSecret string
ClusterManagerWebhookRegistrationService string
RegistrationAPIServiceCABundle string
RegistrationServingCert string
RegistrationServingKey string
}
func (n *nucleusHubController) sync(ctx context.Context, controllerContext factory.SyncContext) error {
hubCoreName := controllerContext.QueueKey()
klog.V(4).Infof("Reconciling HubCore %q", hubCoreName)
func (n *clusterManagerController) sync(ctx context.Context, controllerContext factory.SyncContext) error {
clusterManagerName := controllerContext.QueueKey()
klog.V(4).Infof("Reconciling ClusterManager %q", clusterManagerName)
hubCore, err := n.nucleusLister.Get(hubCoreName)
clusterManager, err := n.clusterManagerLister.Get(clusterManagerName)
if errors.IsNotFound(err) {
// HubCore not found, could have been deleted, do nothing.
// ClusterManager not found, could have been deleted, do nothing.
return nil
}
if err != nil {
return err
}
hubCore = hubCore.DeepCopy()
clusterManager = clusterManager.DeepCopy()
config := hubConfig{
HubCoreName: hubCore.Name,
HubCoreNamespace: nucleusHubCoreNamespace,
RegistrationImage: hubCore.Spec.RegistrationImagePullSpec,
HubCoreWebhookSecret: nucleusHubCoreWebhookSecret,
HubCoreWebhookRegistrationService: fmt.Sprintf("%s-registration-webhook", hubCore.Name),
ClusterManagerName: clusterManager.Name,
ClusterManagerNamespace: clusterManagerNamespace,
RegistrationImage: clusterManager.Spec.RegistrationImagePullSpec,
ClusterManagerWebhookSecret: clusterManagerWebhookSecret,
ClusterManagerWebhookRegistrationService: fmt.Sprintf("%s-registration-webhook", clusterManager.Name),
}
// Update finalizer at first
if hubCore.DeletionTimestamp.IsZero() {
if clusterManager.DeletionTimestamp.IsZero() {
hasFinalizer := false
for i := range hubCore.Finalizers {
if hubCore.Finalizers[i] == nucleusHubFinalizer {
for i := range clusterManager.Finalizers {
if clusterManager.Finalizers[i] == clusterManagerFinalizer {
hasFinalizer = true
break
}
}
if !hasFinalizer {
hubCore.Finalizers = append(hubCore.Finalizers, nucleusHubFinalizer)
_, err := n.nucleusClient.Update(ctx, hubCore, metav1.UpdateOptions{})
clusterManager.Finalizers = append(clusterManager.Finalizers, clusterManagerFinalizer)
_, err := n.clusterManagerClient.Update(ctx, clusterManager, metav1.UpdateOptions{})
return err
}
}
// HubCore is deleting, we remove its related resources on hub
if !hubCore.DeletionTimestamp.IsZero() {
// ClusterManager is deleting, we remove its related resources on hub
if !clusterManager.DeletionTimestamp.IsZero() {
if err := n.cleanUp(ctx, controllerContext, config); err != nil {
return err
}
return n.removeWorkFinalizer(ctx, hubCore)
return n.removeClusterManagerFinalizer(ctx, clusterManager)
}
ca, cert, key, err := n.ensureServingCertAndCA(
ctx, config.HubCoreNamespace, config.HubCoreWebhookSecret, config.HubCoreWebhookRegistrationService)
ctx, config.ClusterManagerNamespace, config.ClusterManagerWebhookSecret, config.ClusterManagerWebhookRegistrationService)
if err != nil {
return err
}
@@ -202,27 +202,27 @@ func (n *nucleusHubController) sync(ctx context.Context, controllerContext facto
n.currentGeneration[index] = currentGeneration
}
conditions := &hubCore.Status.Conditions
conditions := &clusterManager.Status.Conditions
if len(errs) == 0 {
helpers.SetNucleusCondition(conditions, nucleusapiv1.StatusCondition{
Type: hubCoreApplied,
helpers.SetOperatorCondition(conditions, operatorapiv1.StatusCondition{
Type: clusterManagerApplied,
Status: metav1.ConditionTrue,
Reason: "HubCoreApplied",
Message: "Components of hub core is applied",
Reason: "ClusterManagerApplied",
Message: "Components of cluster manager is applied",
})
} else {
helpers.SetNucleusCondition(conditions, nucleusapiv1.StatusCondition{
Type: hubCoreApplied,
helpers.SetOperatorCondition(conditions, operatorapiv1.StatusCondition{
Type: clusterManagerApplied,
Status: metav1.ConditionFalse,
Reason: "HubCoreApplyFailed",
Message: "Components of hub core fail to be applied",
Reason: "ClusterManagerApplyFailed",
Message: "Components of cluster manager fail to be applied",
})
}
//TODO Check if all the pods are running.
// Update status
_, _, updatedErr := helpers.UpdateNucleusHubStatus(
ctx, n.nucleusClient, hubCore.Name, helpers.UpdateNucleusHubConditionFn(*conditions...))
_, _, updatedErr := helpers.UpdateClusterManagerStatus(
ctx, n.clusterManagerClient, clusterManager.Name, helpers.UpdateClusterManagerConditionFn(*conditions...))
if updatedErr != nil {
errs = append(errs, updatedErr)
}
@@ -230,10 +230,10 @@ func (n *nucleusHubController) sync(ctx context.Context, controllerContext facto
return operatorhelpers.NewMultiLineAggregate(errs)
}
func (n *nucleusHubController) removeWorkFinalizer(ctx context.Context, deploy *nucleusapiv1.HubCore) error {
func (n *clusterManagerController) removeClusterManagerFinalizer(ctx context.Context, deploy *operatorapiv1.ClusterManager) error {
copiedFinalizers := []string{}
for i := range deploy.Finalizers {
if deploy.Finalizers[i] == nucleusHubFinalizer {
if deploy.Finalizers[i] == clusterManagerFinalizer {
continue
}
copiedFinalizers = append(copiedFinalizers, deploy.Finalizers[i])
@@ -241,7 +241,7 @@ func (n *nucleusHubController) removeWorkFinalizer(ctx context.Context, deploy *
if len(deploy.Finalizers) != len(copiedFinalizers) {
deploy.Finalizers = copiedFinalizers
_, err := n.nucleusClient.Update(ctx, deploy, metav1.UpdateOptions{})
_, err := n.clusterManagerClient.Update(ctx, deploy, metav1.UpdateOptions{})
return err
}
@@ -250,7 +250,7 @@ func (n *nucleusHubController) removeWorkFinalizer(ctx context.Context, deploy *
// removeCRD removes crd, and check if crd resource is removed. Since the related cr is still being deleted,
// it will check the crd existence after deletion, and only return nil when crd is not found.
func (n *nucleusHubController) removeCRD(ctx context.Context, name string) error {
func (n *clusterManagerController) removeCRD(ctx context.Context, name string) error {
err := n.apiExtensionClient.ApiextensionsV1().CustomResourceDefinitions().Delete(
ctx, name, metav1.DeleteOptions{})
switch {
@@ -273,7 +273,7 @@ func (n *nucleusHubController) removeCRD(ctx context.Context, name string) error
// ensureServingCertAndCA generates self signed CA and server key/cert for webhook server.
// TODO consider ca/cert renewal
func (n *nucleusHubController) ensureServingCertAndCA(
func (n *clusterManagerController) ensureServingCertAndCA(
ctx context.Context, namespace, secretName, svcName string) ([]byte, []byte, []byte, error) {
secret, err := n.kubeClient.CoreV1().Secrets(namespace).Get(ctx, secretName, metav1.GetOptions{})
switch {
@@ -285,7 +285,7 @@ func (n *nucleusHubController) ensureServingCertAndCA(
}
}
caConfig, err := crypto.MakeSelfSignedCAConfig("nucleus-webhook", 365)
caConfig, err := crypto.MakeSelfSignedCAConfig("cluster-manager-webhook", 365)
if err != nil {
return nil, nil, nil, err
}
@@ -313,7 +313,7 @@ func (n *nucleusHubController) ensureServingCertAndCA(
return caData, certData, keyData, nil
}
func (n *nucleusHubController) cleanUp(
func (n *clusterManagerController) cleanUp(
ctx context.Context, controllerContext factory.SyncContext, config hubConfig) error {
// Remove crd
for _, name := range crdNames {

View File

@@ -1,4 +1,4 @@
package hub
package clustermanager
import (
"context"
@@ -6,9 +6,9 @@ import (
"testing"
"time"
fakenucleusclient "github.com/open-cluster-management/api/client/nucleus/clientset/versioned/fake"
nucleusinformers "github.com/open-cluster-management/api/client/nucleus/informers/externalversions"
nucleusapiv1 "github.com/open-cluster-management/api/nucleus/v1"
fakeoperatorlient "github.com/open-cluster-management/api/client/operator/clientset/versioned/fake"
operatorinformers "github.com/open-cluster-management/api/client/operator/informers/externalversions"
operatorapiv1 "github.com/open-cluster-management/api/operator/v1"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
@@ -28,11 +28,11 @@ import (
)
type testController struct {
controller *nucleusHubController
controller *clusterManagerController
kubeClient *fakekube.Clientset
apiExtensionClient *fakeapiextensions.Clientset
apiRegistrationClient *fakeapiregistration.Clientset
nucleusClient *fakenucleusclient.Clientset
operatorClient *fakeoperatorlient.Clientset
}
type fakeSyncContext struct {
@@ -53,34 +53,34 @@ func newFakeSyncContext(t *testing.T, key string) *fakeSyncContext {
}
}
func newHubCore(name string) *nucleusapiv1.HubCore {
return &nucleusapiv1.HubCore{
func newClusterManager(name string) *operatorapiv1.ClusterManager {
return &operatorapiv1.ClusterManager{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Finalizers: []string{"nucleus.open-cluster-management.io/hub-core-cleanup"},
Finalizers: []string{clusterManagerFinalizer},
},
Spec: nucleusapiv1.HubCoreSpec{
Spec: operatorapiv1.ClusterManagerSpec{
RegistrationImagePullSpec: "testregistration",
},
}
}
func newTestController(hubcore *nucleusapiv1.HubCore) *testController {
fakeNucleusClient := fakenucleusclient.NewSimpleClientset(hubcore)
nucleusInformers := nucleusinformers.NewSharedInformerFactory(fakeNucleusClient, 5*time.Minute)
func newTestController(clustermanager *operatorapiv1.ClusterManager) *testController {
fakeOperatorClient := fakeoperatorlient.NewSimpleClientset(clustermanager)
operatorInformers := operatorinformers.NewSharedInformerFactory(fakeOperatorClient, 5*time.Minute)
hubController := &nucleusHubController{
nucleusClient: fakeNucleusClient.NucleusV1().HubCores(),
nucleusLister: nucleusInformers.Nucleus().V1().HubCores().Lister(),
currentGeneration: make([]int64, len(deploymentFiles)),
hubController := &clusterManagerController{
clusterManagerClient: fakeOperatorClient.OperatorV1().ClusterManagers(),
clusterManagerLister: operatorInformers.Operator().V1().ClusterManagers().Lister(),
currentGeneration: make([]int64, len(deploymentFiles)),
}
store := nucleusInformers.Nucleus().V1().HubCores().Informer().GetStore()
store.Add(hubcore)
store := operatorInformers.Operator().V1().ClusterManagers().Informer().GetStore()
store.Add(clustermanager)
return &testController{
controller: hubController,
nucleusClient: fakeNucleusClient,
controller: hubController,
operatorClient: fakeOperatorClient,
}
}
@@ -118,7 +118,7 @@ func assertEqualNumber(t *testing.T, actual, expected int) {
}
func assertCondition(t *testing.T, actual runtime.Object, expectedCondition string, expectedStatus metav1.ConditionStatus) {
hubCore := actual.(*nucleusapiv1.HubCore)
hubCore := actual.(*operatorapiv1.ClusterManager)
conditions := hubCore.Status.Conditions
if len(conditions) != 1 {
t.Errorf("expected 1 condition but got: %#v", conditions)
@@ -142,7 +142,7 @@ func ensureNameNamespace(t *testing.T, actualName, actualNamespace, name, namesp
}
}
func ensureObject(t *testing.T, object runtime.Object, hubCore *nucleusapiv1.HubCore) {
func ensureObject(t *testing.T, object runtime.Object, hubCore *operatorapiv1.ClusterManager) {
access, err := meta.Accessor(object)
if err != nil {
t.Errorf("Unable to access objectmeta: %v", err)
@@ -150,7 +150,7 @@ func ensureObject(t *testing.T, object runtime.Object, hubCore *nucleusapiv1.Hub
switch o := object.(type) {
case *corev1.Namespace:
ensureNameNamespace(t, access.GetName(), "", nucleusHubCoreNamespace, "")
ensureNameNamespace(t, access.GetName(), "", clusterManagerNamespace, "")
case *appsv1.Deployment:
if hubCore.Spec.RegistrationImagePullSpec != o.Spec.Template.Spec.Containers[0].Image {
t.Errorf("Image does not match to the expected.")
@@ -160,8 +160,8 @@ func ensureObject(t *testing.T, object runtime.Object, hubCore *nucleusapiv1.Hub
// TestSyncDeploy tests sync manifests of hub component
func TestSyncDeploy(t *testing.T) {
hubCore := newHubCore("testhub")
controller := newTestController(hubCore).withCRDObject().withKubeObject().withAPIServiceObject()
clusterManager := newClusterManager("testhub")
controller := newTestController(clusterManager).withCRDObject().withKubeObject().withAPIServiceObject()
syncContext := newFakeSyncContext(t, "testhub")
err := controller.controller.sync(nil, syncContext)
@@ -181,7 +181,7 @@ func TestSyncDeploy(t *testing.T) {
// Check if resources are created as expected
assertEqualNumber(t, len(createKubeObjects), 12)
for _, object := range createKubeObjects {
ensureObject(t, object, hubCore)
ensureObject(t, object, clusterManager)
}
createCRDObjects := []runtime.Object{}
@@ -206,18 +206,18 @@ func TestSyncDeploy(t *testing.T) {
// Check if resources are created as expected
assertEqualNumber(t, len(createAPIServiceObjects), 1)
nucleusAction := controller.nucleusClient.Actions()
assertEqualNumber(t, len(nucleusAction), 2)
assertAction(t, nucleusAction[1], "update")
assertCondition(t, nucleusAction[1].(clienttesting.UpdateActionImpl).Object, hubCoreApplied, metav1.ConditionTrue)
clusterManagerAction := controller.operatorClient.Actions()
assertEqualNumber(t, len(clusterManagerAction), 2)
assertAction(t, clusterManagerAction[1], "update")
assertCondition(t, clusterManagerAction[1].(clienttesting.UpdateActionImpl).Object, clusterManagerApplied, metav1.ConditionTrue)
}
// TestSyncDelete test cleanup hub deploy
func TestSyncDelete(t *testing.T) {
hubCore := newHubCore("testhub")
clusterManager := newClusterManager("testhub")
now := metav1.Now()
hubCore.ObjectMeta.SetDeletionTimestamp(&now)
controller := newTestController(hubCore).withCRDObject().withKubeObject().withAPIServiceObject()
clusterManager.ObjectMeta.SetDeletionTimestamp(&now)
controller := newTestController(clusterManager).withCRDObject().withKubeObject().withAPIServiceObject()
syncContext := newFakeSyncContext(t, "testhub")
err := controller.controller.sync(nil, syncContext)
@@ -260,22 +260,22 @@ func TestSyncDelete(t *testing.T) {
for _, action := range deleteKubeActions {
switch action.Resource.Resource {
case "namespaces":
ensureNameNamespace(t, action.Name, "", nucleusHubCoreNamespace, "")
ensureNameNamespace(t, action.Name, "", clusterManagerNamespace, "")
}
}
}
// TestDeleteCRD test delete crds
func TestDeleteCRD(t *testing.T) {
hubCore := newHubCore("testhub")
clusterManager := newClusterManager("testhub")
now := metav1.Now()
hubCore.ObjectMeta.SetDeletionTimestamp(&now)
clusterManager.ObjectMeta.SetDeletionTimestamp(&now)
crd := &apiextensionsv1.CustomResourceDefinition{
ObjectMeta: metav1.ObjectMeta{
Name: crdNames[0],
},
}
controller := newTestController(hubCore).withCRDObject(crd).withKubeObject().withAPIServiceObject()
controller := newTestController(clusterManager).withCRDObject(crd).withKubeObject().withAPIServiceObject()
// Return crd with the first get, and return not found with the 2nd get
getCount := 0
@@ -301,8 +301,8 @@ func TestDeleteCRD(t *testing.T) {
}
func TestEnsureServingCertAndCA(t *testing.T) {
hubCore := newHubCore("testhub")
controller := newTestController(hubCore).withCRDObject().withKubeObject().withAPIServiceObject()
clusterManager := newClusterManager("testhub")
controller := newTestController(clusterManager).withCRDObject().withKubeObject().withAPIServiceObject()
ca, certificate, key, err := controller.controller.ensureServingCertAndCA(context.TODO(), "ns1", "kubeconfig", "webhook")
if err != nil {
t.Errorf("Expect no error when generating serving cert: %v", err)
@@ -315,7 +315,7 @@ func TestEnsureServingCertAndCA(t *testing.T) {
t.Errorf("Expect 2 cert is parsed, actual %d", len(certs))
}
for _, cert := range certs {
if cert.Subject.CommonName != "webhook.ns1.svc" && cert.Subject.CommonName != "nucleus-webhook" {
if cert.Subject.CommonName != "webhook.ns1.svc" && cert.Subject.CommonName != "cluster-manager-webhook" {
t.Errorf("Common name in cert is not correct, actual %s", cert.Subject.CommonName)
}
}
@@ -331,7 +331,7 @@ func TestEnsureServingCertAndCA(t *testing.T) {
"tls.key": key,
},
}
controller = newTestController(hubCore).withCRDObject().withKubeObject(secret).withAPIServiceObject()
controller = newTestController(clusterManager).withCRDObject().withKubeObject(secret).withAPIServiceObject()
actualCA, actualCert, actualKey, err := controller.controller.ensureServingCertAndCA(context.TODO(), "ns1", "kubeconfig", "webhook")
if err != nil {
t.Errorf("Expect no error when generating serving cert: %v", err)

View File

@@ -0,0 +1,641 @@
// Code generated for package bindata by go-bindata DO NOT EDIT. (@generated)
// sources:
// manifests/klusterlet/klusterlet-registration-clusterrole.yaml
// manifests/klusterlet/klusterlet-registration-clusterrolebinding.yaml
// manifests/klusterlet/klusterlet-registration-deployment.yaml
// manifests/klusterlet/klusterlet-registration-role.yaml
// manifests/klusterlet/klusterlet-registration-rolebinding.yaml
// manifests/klusterlet/klusterlet-registration-serviceaccount.yaml
// manifests/klusterlet/klusterlet-work-clusterrole.yaml
// manifests/klusterlet/klusterlet-work-clusterrolebinding-addition.yaml
// manifests/klusterlet/klusterlet-work-clusterrolebinding.yaml
// manifests/klusterlet/klusterlet-work-deployment.yaml
// manifests/klusterlet/klusterlet-work-serviceaccount.yaml
package bindata
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"time"
)
type asset struct {
bytes []byte
info os.FileInfo
}
type bindataFileInfo struct {
name string
size int64
mode os.FileMode
modTime time.Time
}
// Name return file name
func (fi bindataFileInfo) Name() string {
return fi.name
}
// Size return file size
func (fi bindataFileInfo) Size() int64 {
return fi.size
}
// Mode return file mode
func (fi bindataFileInfo) Mode() os.FileMode {
return fi.mode
}
// Mode return file modify time
func (fi bindataFileInfo) ModTime() time.Time {
return fi.modTime
}
// IsDir return file whether a directory
func (fi bindataFileInfo) IsDir() bool {
return fi.mode&os.ModeDir != 0
}
// Sys return file is sys mode
func (fi bindataFileInfo) Sys() interface{} {
return nil
}
var _manifestsKlusterletKlusterletRegistrationClusterroleYaml = []byte(`# Clusterrole for work agent in addition to admin clusterrole.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: system:open-cluster-management:{{ .KlusterletName }}-registration-agent
rules:
# Allow agent to get/list/watch nodes.
- apiGroups: [""]
resources: ["nodes", "configmaps", "secrets"]
verbs: ["get", "list", "watch"]
- apiGroups: ["authorization.k8s.io"]
resources: ["subjectaccessreviews"]
verbs: ["create"]
`)
func manifestsKlusterletKlusterletRegistrationClusterroleYamlBytes() ([]byte, error) {
return _manifestsKlusterletKlusterletRegistrationClusterroleYaml, nil
}
func manifestsKlusterletKlusterletRegistrationClusterroleYaml() (*asset, error) {
bytes, err := manifestsKlusterletKlusterletRegistrationClusterroleYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/klusterlet/klusterlet-registration-clusterrole.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsKlusterletKlusterletRegistrationClusterrolebindingYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:open-cluster-management:{{ .KlusterletName }}-registration-agent
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:open-cluster-management:{{ .KlusterletName }}-registration-agent
subjects:
- kind: ServiceAccount
name: {{ .KlusterletName }}-registration-sa
namespace: {{ .KlusterletNamespace }}
`)
func manifestsKlusterletKlusterletRegistrationClusterrolebindingYamlBytes() ([]byte, error) {
return _manifestsKlusterletKlusterletRegistrationClusterrolebindingYaml, nil
}
func manifestsKlusterletKlusterletRegistrationClusterrolebindingYaml() (*asset, error) {
bytes, err := manifestsKlusterletKlusterletRegistrationClusterrolebindingYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/klusterlet/klusterlet-registration-clusterrolebinding.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsKlusterletKlusterletRegistrationDeploymentYaml = []byte(`kind: Deployment
apiVersion: apps/v1
metadata:
name: {{ .KlusterletName }}-registration-agent
namespace: {{ .KlusterletNamespace }}
labels:
app: klusterlet-registration-agent
spec:
replicas: 3
selector:
matchLabels:
app: klusterlet-registration-agent
template:
metadata:
labels:
app: klusterlet-registration-agent
spec:
serviceAccountName: {{ .KlusterletName }}-registration-sa
containers:
- name: spoke-agent
image: {{ .RegistrationImage }}
imagePullPolicy: IfNotPresent
args:
- "/registration"
- "agent"
- "--cluster-name={{ .ClusterName }}"
- "--bootstrap-kubeconfig=/spoke/bootstrap/kubeconfig"
- "--spoke-external-server-urls={{ .ExternalServerURL }}"
volumeMounts:
- name: bootstrap-secret
mountPath: "/spoke/bootstrap"
readOnly: true
- name: hub-kubeconfig-secret
mountPath: "/spoke/hub-kubeconfig"
readOnly: true
livenessProbe:
httpGet:
path: /healthz
scheme: HTTPS
port: 8443
initialDelaySeconds: 2
periodSeconds: 10
readinessProbe:
httpGet:
path: /healthz
scheme: HTTPS
port: 8443
initialDelaySeconds: 2
volumes:
- name: bootstrap-secret
secret:
secretName: {{ .BootStrapKubeConfigSecret }}
- name: hub-kubeconfig-secret
secret:
secretName: {{ .HubKubeConfigSecret }}
`)
func manifestsKlusterletKlusterletRegistrationDeploymentYamlBytes() ([]byte, error) {
return _manifestsKlusterletKlusterletRegistrationDeploymentYaml, nil
}
func manifestsKlusterletKlusterletRegistrationDeploymentYaml() (*asset, error) {
bytes, err := manifestsKlusterletKlusterletRegistrationDeploymentYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/klusterlet/klusterlet-registration-deployment.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsKlusterletKlusterletRegistrationRoleYaml = []byte(`# Role for registration agent.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: system:open-cluster-management:{{ .KlusterletName }}-registration-agent
namespace: {{ .KlusterletNamespace }}
rules:
- apiGroups: [""]
resources: ["configmaps", "secrets"]
verbs: ["get", "list", "watch", "create", "delete", "update", "patch"]
- apiGroups: ["", "events.k8s.io"]
resources: ["events"]
verbs: ["create", "patch", "update"]
`)
func manifestsKlusterletKlusterletRegistrationRoleYamlBytes() ([]byte, error) {
return _manifestsKlusterletKlusterletRegistrationRoleYaml, nil
}
func manifestsKlusterletKlusterletRegistrationRoleYaml() (*asset, error) {
bytes, err := manifestsKlusterletKlusterletRegistrationRoleYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/klusterlet/klusterlet-registration-role.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsKlusterletKlusterletRegistrationRolebindingYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: system:open-cluster-management:{{ .KlusterletName }}-registration-agent
namespace: {{ .KlusterletNamespace }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: system:open-cluster-management:{{ .KlusterletName }}-registration-agent
subjects:
- kind: ServiceAccount
name: {{ .KlusterletName }}-registration-sa
namespace: {{ .KlusterletNamespace }}
`)
func manifestsKlusterletKlusterletRegistrationRolebindingYamlBytes() ([]byte, error) {
return _manifestsKlusterletKlusterletRegistrationRolebindingYaml, nil
}
func manifestsKlusterletKlusterletRegistrationRolebindingYaml() (*asset, error) {
bytes, err := manifestsKlusterletKlusterletRegistrationRolebindingYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/klusterlet/klusterlet-registration-rolebinding.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsKlusterletKlusterletRegistrationServiceaccountYaml = []byte(`apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .KlusterletName }}-registration-sa
namespace: {{ .KlusterletNamespace }}
`)
func manifestsKlusterletKlusterletRegistrationServiceaccountYamlBytes() ([]byte, error) {
return _manifestsKlusterletKlusterletRegistrationServiceaccountYaml, nil
}
func manifestsKlusterletKlusterletRegistrationServiceaccountYaml() (*asset, error) {
bytes, err := manifestsKlusterletKlusterletRegistrationServiceaccountYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/klusterlet/klusterlet-registration-serviceaccount.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsKlusterletKlusterletWorkClusterroleYaml = []byte(`# Clusterrole for work agent in addition to admin clusterrole.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: system:open-cluster-management:{{ .KlusterletName }}-work-agent
rules:
# Allow agent to get/list/watch/create/delete crds.
- apiGroups: ["apiextensions.k8s.io"]
resources: ["customresourcedefinitions"]
verbs: ["get", "list", "watch", "create", "delete", "update"]
# Allow agent to create/delete namespaces, get/list are contained in admin role already
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["create", "delete"]
# Allow agent to manage role/rolebinding/clusterrole/clusterrolebinding
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["clusterrolebindings", "rolebindings"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["clusterroles", "roles"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete", "escalate", "bind"]
# Allow agent to create sar
- apiGroups: ["authorization.k8s.io"]
resources: ["subjectaccessreviews"]
verbs: ["create"]
# Allow agent to create events
- apiGroups: ["", "events.k8s.io"]
resources: ["events"]
verbs: ["create", "patch", "update"]
`)
func manifestsKlusterletKlusterletWorkClusterroleYamlBytes() ([]byte, error) {
return _manifestsKlusterletKlusterletWorkClusterroleYaml, nil
}
func manifestsKlusterletKlusterletWorkClusterroleYaml() (*asset, error) {
bytes, err := manifestsKlusterletKlusterletWorkClusterroleYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/klusterlet/klusterlet-work-clusterrole.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsKlusterletKlusterletWorkClusterrolebindingAdditionYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:open-cluster-management:{{ .KlusterletName }}-work-agent-addition
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:open-cluster-management:{{ .KlusterletName }}-work-agent
subjects:
- kind: ServiceAccount
name: {{ .KlusterletName }}-work-sa
namespace: {{ .KlusterletNamespace }}
`)
func manifestsKlusterletKlusterletWorkClusterrolebindingAdditionYamlBytes() ([]byte, error) {
return _manifestsKlusterletKlusterletWorkClusterrolebindingAdditionYaml, nil
}
func manifestsKlusterletKlusterletWorkClusterrolebindingAdditionYaml() (*asset, error) {
bytes, err := manifestsKlusterletKlusterletWorkClusterrolebindingAdditionYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/klusterlet/klusterlet-work-clusterrolebinding-addition.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsKlusterletKlusterletWorkClusterrolebindingYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:open-cluster-management:{{ .KlusterletName }}-work-agent
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
# We deploy a controller that could work with permission lower than cluster-admin, the tradeoff is
# responsivity because list/watch cannot be maintained over too many namespaces.
name: admin
subjects:
- kind: ServiceAccount
name: {{ .KlusterletName }}-work-sa
namespace: {{ .KlusterletNamespace }}
`)
func manifestsKlusterletKlusterletWorkClusterrolebindingYamlBytes() ([]byte, error) {
return _manifestsKlusterletKlusterletWorkClusterrolebindingYaml, nil
}
func manifestsKlusterletKlusterletWorkClusterrolebindingYaml() (*asset, error) {
bytes, err := manifestsKlusterletKlusterletWorkClusterrolebindingYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/klusterlet/klusterlet-work-clusterrolebinding.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsKlusterletKlusterletWorkDeploymentYaml = []byte(`kind: Deployment
apiVersion: apps/v1
metadata:
name: {{ .KlusterletName }}-work-agent
namespace: {{ .KlusterletNamespace }}
labels:
app: klusterlet-manifestwork-agent
spec:
replicas: 3
selector:
matchLabels:
app: klusterlet-manifestwork-agent
template:
metadata:
labels:
app: klusterlet-manifestwork-agent
spec:
serviceAccountName: {{ .KlusterletName }}-work-sa
containers:
- name: spoke-agent
image: {{ .WorkImage }}
imagePullPolicy: IfNotPresent
args:
- "/work"
- "agent"
- "--spoke-cluster-name={{ .ClusterName }}"
- "--hub-kubeconfig=/spoke/hub-kubeconfig/kubeconfig"
volumeMounts:
- name: hub-kubeconfig-secret
mountPath: "/spoke/hub-kubeconfig"
readOnly: true
livenessProbe:
httpGet:
path: /healthz
scheme: HTTPS
port: 8443
initialDelaySeconds: 2
periodSeconds: 10
readinessProbe:
httpGet:
path: /healthz
scheme: HTTPS
port: 8443
initialDelaySeconds: 2
volumes:
- name: hub-kubeconfig-secret
secret:
secretName: {{ .HubKubeConfigSecret }}
`)
func manifestsKlusterletKlusterletWorkDeploymentYamlBytes() ([]byte, error) {
return _manifestsKlusterletKlusterletWorkDeploymentYaml, nil
}
func manifestsKlusterletKlusterletWorkDeploymentYaml() (*asset, error) {
bytes, err := manifestsKlusterletKlusterletWorkDeploymentYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/klusterlet/klusterlet-work-deployment.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsKlusterletKlusterletWorkServiceaccountYaml = []byte(`apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .KlusterletName }}-work-sa
namespace: {{ .KlusterletNamespace }}
`)
func manifestsKlusterletKlusterletWorkServiceaccountYamlBytes() ([]byte, error) {
return _manifestsKlusterletKlusterletWorkServiceaccountYaml, nil
}
func manifestsKlusterletKlusterletWorkServiceaccountYaml() (*asset, error) {
bytes, err := manifestsKlusterletKlusterletWorkServiceaccountYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/klusterlet/klusterlet-work-serviceaccount.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
// Asset loads and returns the asset for the given name.
// It returns an error if the asset could not be found or
// could not be loaded.
func Asset(name string) ([]byte, error) {
cannonicalName := strings.Replace(name, "\\", "/", -1)
if f, ok := _bindata[cannonicalName]; ok {
a, err := f()
if err != nil {
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
}
return a.bytes, nil
}
return nil, fmt.Errorf("Asset %s not found", name)
}
// MustAsset is like Asset but panics when Asset would return an error.
// It simplifies safe initialization of global variables.
func MustAsset(name string) []byte {
a, err := Asset(name)
if err != nil {
panic("asset: Asset(" + name + "): " + err.Error())
}
return a
}
// AssetInfo loads and returns the asset info for the given name.
// It returns an error if the asset could not be found or
// could not be loaded.
func AssetInfo(name string) (os.FileInfo, error) {
cannonicalName := strings.Replace(name, "\\", "/", -1)
if f, ok := _bindata[cannonicalName]; ok {
a, err := f()
if err != nil {
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
}
return a.info, nil
}
return nil, fmt.Errorf("AssetInfo %s not found", name)
}
// AssetNames returns the names of the assets.
func AssetNames() []string {
names := make([]string, 0, len(_bindata))
for name := range _bindata {
names = append(names, name)
}
return names
}
// _bindata is a table, holding each asset generator, mapped to its name.
var _bindata = map[string]func() (*asset, error){
"manifests/klusterlet/klusterlet-registration-clusterrole.yaml": manifestsKlusterletKlusterletRegistrationClusterroleYaml,
"manifests/klusterlet/klusterlet-registration-clusterrolebinding.yaml": manifestsKlusterletKlusterletRegistrationClusterrolebindingYaml,
"manifests/klusterlet/klusterlet-registration-deployment.yaml": manifestsKlusterletKlusterletRegistrationDeploymentYaml,
"manifests/klusterlet/klusterlet-registration-role.yaml": manifestsKlusterletKlusterletRegistrationRoleYaml,
"manifests/klusterlet/klusterlet-registration-rolebinding.yaml": manifestsKlusterletKlusterletRegistrationRolebindingYaml,
"manifests/klusterlet/klusterlet-registration-serviceaccount.yaml": manifestsKlusterletKlusterletRegistrationServiceaccountYaml,
"manifests/klusterlet/klusterlet-work-clusterrole.yaml": manifestsKlusterletKlusterletWorkClusterroleYaml,
"manifests/klusterlet/klusterlet-work-clusterrolebinding-addition.yaml": manifestsKlusterletKlusterletWorkClusterrolebindingAdditionYaml,
"manifests/klusterlet/klusterlet-work-clusterrolebinding.yaml": manifestsKlusterletKlusterletWorkClusterrolebindingYaml,
"manifests/klusterlet/klusterlet-work-deployment.yaml": manifestsKlusterletKlusterletWorkDeploymentYaml,
"manifests/klusterlet/klusterlet-work-serviceaccount.yaml": manifestsKlusterletKlusterletWorkServiceaccountYaml,
}
// AssetDir returns the file names below a certain
// directory embedded in the file by go-bindata.
// For example if you run go-bindata on data/... and data contains the
// following hierarchy:
// data/
// foo.txt
// img/
// a.png
// b.png
// then AssetDir("data") would return []string{"foo.txt", "img"}
// AssetDir("data/img") would return []string{"a.png", "b.png"}
// AssetDir("foo.txt") and AssetDir("notexist") would return an error
// AssetDir("") will return []string{"data"}.
func AssetDir(name string) ([]string, error) {
node := _bintree
if len(name) != 0 {
cannonicalName := strings.Replace(name, "\\", "/", -1)
pathList := strings.Split(cannonicalName, "/")
for _, p := range pathList {
node = node.Children[p]
if node == nil {
return nil, fmt.Errorf("Asset %s not found", name)
}
}
}
if node.Func != nil {
return nil, fmt.Errorf("Asset %s not found", name)
}
rv := make([]string, 0, len(node.Children))
for childName := range node.Children {
rv = append(rv, childName)
}
return rv, nil
}
type bintree struct {
Func func() (*asset, error)
Children map[string]*bintree
}
var _bintree = &bintree{nil, map[string]*bintree{
"manifests": {nil, map[string]*bintree{
"klusterlet": {nil, map[string]*bintree{
"klusterlet-registration-clusterrole.yaml": {manifestsKlusterletKlusterletRegistrationClusterroleYaml, map[string]*bintree{}},
"klusterlet-registration-clusterrolebinding.yaml": {manifestsKlusterletKlusterletRegistrationClusterrolebindingYaml, map[string]*bintree{}},
"klusterlet-registration-deployment.yaml": {manifestsKlusterletKlusterletRegistrationDeploymentYaml, map[string]*bintree{}},
"klusterlet-registration-role.yaml": {manifestsKlusterletKlusterletRegistrationRoleYaml, map[string]*bintree{}},
"klusterlet-registration-rolebinding.yaml": {manifestsKlusterletKlusterletRegistrationRolebindingYaml, map[string]*bintree{}},
"klusterlet-registration-serviceaccount.yaml": {manifestsKlusterletKlusterletRegistrationServiceaccountYaml, map[string]*bintree{}},
"klusterlet-work-clusterrole.yaml": {manifestsKlusterletKlusterletWorkClusterroleYaml, map[string]*bintree{}},
"klusterlet-work-clusterrolebinding-addition.yaml": {manifestsKlusterletKlusterletWorkClusterrolebindingAdditionYaml, map[string]*bintree{}},
"klusterlet-work-clusterrolebinding.yaml": {manifestsKlusterletKlusterletWorkClusterrolebindingYaml, map[string]*bintree{}},
"klusterlet-work-deployment.yaml": {manifestsKlusterletKlusterletWorkDeploymentYaml, map[string]*bintree{}},
"klusterlet-work-serviceaccount.yaml": {manifestsKlusterletKlusterletWorkServiceaccountYaml, map[string]*bintree{}},
}},
}},
}}
// RestoreAsset restores an asset under the given directory
func RestoreAsset(dir, name string) error {
data, err := Asset(name)
if err != nil {
return err
}
info, err := AssetInfo(name)
if err != nil {
return err
}
err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755))
if err != nil {
return err
}
err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
if err != nil {
return err
}
err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
if err != nil {
return err
}
return nil
}
// RestoreAssets restores an asset under the given directory recursively
func RestoreAssets(dir, name string) error {
children, err := AssetDir(name)
// File
if err != nil {
return RestoreAsset(dir, name)
}
// Dir
for _, child := range children {
err = RestoreAssets(dir, filepath.Join(name, child))
if err != nil {
return err
}
}
return nil
}
func _filePath(dir, name string) string {
cannonicalName := strings.Replace(name, "\\", "/", -1)
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
}

View File

@@ -1,4 +1,4 @@
package spoke
package klusterlet
import (
"context"
@@ -21,69 +21,69 @@ import (
"github.com/openshift/library-go/pkg/operator/resource/resourceapply"
operatorhelpers "github.com/openshift/library-go/pkg/operator/v1helpers"
nucleusv1client "github.com/open-cluster-management/api/client/nucleus/clientset/versioned/typed/nucleus/v1"
nucleusinformer "github.com/open-cluster-management/api/client/nucleus/informers/externalversions/nucleus/v1"
nucleuslister "github.com/open-cluster-management/api/client/nucleus/listers/nucleus/v1"
nucleusapiv1 "github.com/open-cluster-management/api/nucleus/v1"
operatorv1client "github.com/open-cluster-management/api/client/operator/clientset/versioned/typed/operator/v1"
operatorinformer "github.com/open-cluster-management/api/client/operator/informers/externalversions/operator/v1"
operatorlister "github.com/open-cluster-management/api/client/operator/listers/operator/v1"
operatorapiv1 "github.com/open-cluster-management/api/operator/v1"
"github.com/open-cluster-management/nucleus/pkg/helpers"
"github.com/open-cluster-management/nucleus/pkg/operators/spoke/bindata"
"github.com/open-cluster-management/nucleus/pkg/operators/klusterlet/bindata"
)
const (
nucleusSpokeFinalizer = "nucleus.open-cluster-management.io/spoke-core-cleanup"
klusterletFinalizer = "operator.open-cluster-management.io/klusterlet-cleanup"
bootstrapHubKubeConfigSecret = "bootstrap-hub-kubeconfig"
hubKubeConfigSecret = "hub-kubeconfig-secret"
nucleusSpokeCoreNamespace = "open-cluster-management-spoke"
spokeCoreApplied = "Applied"
klusterletNamespace = "open-cluster-management-agent"
klusterletApplied = "Applied"
spokeRegistrationDegraded = "SpokeRegistrationDegraded"
)
var (
staticResourceFiles = []string{
"manifests/spoke/spoke-registration-serviceaccount.yaml",
"manifests/spoke/spoke-registration-clusterrole.yaml",
"manifests/spoke/spoke-registration-clusterrolebinding.yaml",
"manifests/spoke/spoke-registration-role.yaml",
"manifests/spoke/spoke-registration-rolebinding.yaml",
"manifests/spoke/spoke-work-serviceaccount.yaml",
"manifests/spoke/spoke-work-clusterrole.yaml",
"manifests/spoke/spoke-work-clusterrolebinding.yaml",
"manifests/spoke/spoke-work-clusterrolebinding-addition.yaml",
"manifests/klusterlet/klusterlet-registration-serviceaccount.yaml",
"manifests/klusterlet/klusterlet-registration-clusterrole.yaml",
"manifests/klusterlet/klusterlet-registration-clusterrolebinding.yaml",
"manifests/klusterlet/klusterlet-registration-role.yaml",
"manifests/klusterlet/klusterlet-registration-rolebinding.yaml",
"manifests/klusterlet/klusterlet-work-serviceaccount.yaml",
"manifests/klusterlet/klusterlet-work-clusterrole.yaml",
"manifests/klusterlet/klusterlet-work-clusterrolebinding.yaml",
"manifests/klusterlet/klusterlet-work-clusterrolebinding-addition.yaml",
}
)
type nucleusSpokeController struct {
nucleusClient nucleusv1client.SpokeCoreInterface
nucleusLister nucleuslister.SpokeCoreLister
type klusterletController struct {
klusterletClient operatorv1client.KlusterletInterface
klusterletLister operatorlister.KlusterletLister
kubeClient kubernetes.Interface
registrationGeneration int64
workGeneration int64
}
// NewNucleusSpokeController construct nucleus spoke controller
func NewNucleusSpokeController(
// NewKlusterletController construct klusterlet controller
func NewKlusterletController(
kubeClient kubernetes.Interface,
nucleusClient nucleusv1client.SpokeCoreInterface,
nucleusInformer nucleusinformer.SpokeCoreInformer,
klusterletClient operatorv1client.KlusterletInterface,
klusterletInformer operatorinformer.KlusterletInformer,
recorder events.Recorder) factory.Controller {
controller := &nucleusSpokeController{
kubeClient: kubeClient,
nucleusClient: nucleusClient,
nucleusLister: nucleusInformer.Lister(),
controller := &klusterletController{
kubeClient: kubeClient,
klusterletClient: klusterletClient,
klusterletLister: klusterletInformer.Lister(),
}
return factory.New().WithSync(controller.sync).
WithInformersQueueKeyFunc(func(obj runtime.Object) string {
accessor, _ := meta.Accessor(obj)
return accessor.GetName()
}, nucleusInformer.Informer()).
ToController("NucleusSpokeController", recorder)
}, klusterletInformer.Informer()).
ToController("KlusterletController", recorder)
}
// spokeConfig is used to render the template of hub manifests
type spokeConfig struct {
SpokeCoreName string
SpokeCoreNamespace string
KlusterletName string
KlusterletNamespace string
RegistrationImage string
WorkImage string
ClusterName string
@@ -92,10 +92,10 @@ type spokeConfig struct {
BootStrapKubeConfigSecret string
}
func (n *nucleusSpokeController) sync(ctx context.Context, controllerContext factory.SyncContext) error {
spokeCoreName := controllerContext.QueueKey()
klog.V(4).Infof("Reconciling SpokeCore %q", spokeCoreName)
spokeCore, err := n.nucleusLister.Get(spokeCoreName)
func (n *klusterletController) sync(ctx context.Context, controllerContext factory.SyncContext) error {
klusterletName := controllerContext.QueueKey()
klog.V(4).Infof("Reconciling Klusterlet %q", klusterletName)
klusterlet, err := n.klusterletLister.Get(klusterletName)
if errors.IsNotFound(err) {
// AgentCore not found, could have been deleted, do nothing.
return nil
@@ -103,77 +103,77 @@ func (n *nucleusSpokeController) sync(ctx context.Context, controllerContext fac
if err != nil {
return err
}
spokeCore = spokeCore.DeepCopy()
klusterlet = klusterlet.DeepCopy()
config := spokeConfig{
SpokeCoreName: spokeCore.Name,
SpokeCoreNamespace: spokeCore.Spec.Namespace,
RegistrationImage: spokeCore.Spec.RegistrationImagePullSpec,
WorkImage: spokeCore.Spec.WorkImagePullSpec,
ClusterName: spokeCore.Spec.ClusterName,
KlusterletName: klusterlet.Name,
KlusterletNamespace: klusterlet.Spec.Namespace,
RegistrationImage: klusterlet.Spec.RegistrationImagePullSpec,
WorkImage: klusterlet.Spec.WorkImagePullSpec,
ClusterName: klusterlet.Spec.ClusterName,
BootStrapKubeConfigSecret: bootstrapHubKubeConfigSecret,
HubKubeConfigSecret: hubKubeConfigSecret,
ExternalServerURL: getServersFromSpokeCore(spokeCore),
ExternalServerURL: getServersFromKlusterlet(klusterlet),
}
// If namespace is not set, use the default namespace
if config.SpokeCoreNamespace == "" {
config.SpokeCoreNamespace = nucleusSpokeCoreNamespace
if config.KlusterletNamespace == "" {
config.KlusterletNamespace = klusterletNamespace
}
// Update finalizer at first
if spokeCore.DeletionTimestamp.IsZero() {
if klusterlet.DeletionTimestamp.IsZero() {
hasFinalizer := false
for i := range spokeCore.Finalizers {
if spokeCore.Finalizers[i] == nucleusSpokeFinalizer {
for i := range klusterlet.Finalizers {
if klusterlet.Finalizers[i] == klusterletFinalizer {
hasFinalizer = true
break
}
}
if !hasFinalizer {
spokeCore.Finalizers = append(spokeCore.Finalizers, nucleusSpokeFinalizer)
_, err := n.nucleusClient.Update(ctx, spokeCore, metav1.UpdateOptions{})
klusterlet.Finalizers = append(klusterlet.Finalizers, klusterletFinalizer)
_, err := n.klusterletClient.Update(ctx, klusterlet, metav1.UpdateOptions{})
return err
}
}
// SpokeCore is deleting, we remove its related resources on spoke
if !spokeCore.DeletionTimestamp.IsZero() {
// Klusterlet is deleting, we remove its related resources on spoke
if !klusterlet.DeletionTimestamp.IsZero() {
if err := n.cleanUp(ctx, controllerContext, config); err != nil {
return err
}
return n.removeWorkFinalizer(ctx, spokeCore)
return n.removeKlusterletFinalizer(ctx, klusterlet)
}
// Start deploy spoke core components
// Check if namespace exists
_, err = n.kubeClient.CoreV1().Namespaces().Get(ctx, config.SpokeCoreNamespace, metav1.GetOptions{})
_, err = n.kubeClient.CoreV1().Namespaces().Get(ctx, config.KlusterletNamespace, metav1.GetOptions{})
switch {
case errors.IsNotFound(err):
_, createErr := n.kubeClient.CoreV1().Namespaces().Create(ctx, &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{Name: config.SpokeCoreNamespace},
ObjectMeta: metav1.ObjectMeta{Name: config.KlusterletNamespace},
}, metav1.CreateOptions{})
if createErr != nil {
helpers.UpdateNucleusSpokeStatus(ctx, n.nucleusClient, spokeCoreName, helpers.UpdateNucleusSpokeConditionFn(nucleusapiv1.StatusCondition{
Type: spokeCoreApplied, Status: metav1.ConditionFalse, Reason: "SpokeCoreApplyFailed",
Message: fmt.Sprintf("Failed to create namespace %q: %v", config.SpokeCoreNamespace, createErr),
helpers.UpdateKlusterletStatus(ctx, n.klusterletClient, klusterletName, helpers.UpdateKlusterletConditionFn(operatorapiv1.StatusCondition{
Type: klusterletApplied, Status: metav1.ConditionFalse, Reason: "KlusterletApplyFailed",
Message: fmt.Sprintf("Failed to create namespace %q: %v", config.KlusterletNamespace, createErr),
}))
return createErr
}
case err != nil:
helpers.UpdateNucleusSpokeStatus(ctx, n.nucleusClient, spokeCoreName, helpers.UpdateNucleusSpokeConditionFn(nucleusapiv1.StatusCondition{
Type: spokeCoreApplied, Status: metav1.ConditionFalse, Reason: "SpokeCoreApplyFailed",
Message: fmt.Sprintf("Failed to get namespace %q: %v", config.SpokeCoreNamespace, err),
helpers.UpdateKlusterletStatus(ctx, n.klusterletClient, klusterletName, helpers.UpdateKlusterletConditionFn(operatorapiv1.StatusCondition{
Type: klusterletApplied, Status: metav1.ConditionFalse, Reason: "KlusterletApplyFailed",
Message: fmt.Sprintf("Failed to get namespace %q: %v", config.KlusterletNamespace, err),
}))
return err
}
// Check if bootstrap secret exists
_, err = n.kubeClient.CoreV1().Secrets(config.SpokeCoreNamespace).Get(
_, err = n.kubeClient.CoreV1().Secrets(config.KlusterletNamespace).Get(
ctx, config.BootStrapKubeConfigSecret, metav1.GetOptions{})
if err != nil {
helpers.UpdateNucleusSpokeStatus(ctx, n.nucleusClient, spokeCoreName, helpers.UpdateNucleusSpokeConditionFn(nucleusapiv1.StatusCondition{
Type: spokeCoreApplied, Status: metav1.ConditionFalse, Reason: "SpokeCoreApplyFailed",
Message: fmt.Sprintf("Failed to get bootstrap secret -n %q %q: %v", config.SpokeCoreNamespace, config.BootStrapKubeConfigSecret, err),
helpers.UpdateKlusterletStatus(ctx, n.klusterletClient, klusterletName, helpers.UpdateKlusterletConditionFn(operatorapiv1.StatusCondition{
Type: klusterletApplied, Status: metav1.ConditionFalse, Reason: "KlusterletApplyFailed",
Message: fmt.Sprintf("Failed to get bootstrap secret -n %q %q: %v", config.KlusterletNamespace, config.BootStrapKubeConfigSecret, err),
}))
return err
}
@@ -197,36 +197,36 @@ func (n *nucleusSpokeController) sync(ctx context.Context, controllerContext fac
if len(errs) > 0 {
applyErrors := operatorhelpers.NewMultiLineAggregate(errs)
helpers.UpdateNucleusSpokeStatus(ctx, n.nucleusClient, spokeCoreName, helpers.UpdateNucleusSpokeConditionFn(nucleusapiv1.StatusCondition{
Type: spokeCoreApplied, Status: metav1.ConditionFalse, Reason: "SpokeCoreApplyFailed",
helpers.UpdateKlusterletStatus(ctx, n.klusterletClient, klusterletName, helpers.UpdateKlusterletConditionFn(operatorapiv1.StatusCondition{
Type: klusterletApplied, Status: metav1.ConditionFalse, Reason: "KlusterletApplyFailed",
Message: applyErrors.Error(),
}))
return applyErrors
}
// Create hub config secret
hubSecret, err := n.kubeClient.CoreV1().Secrets(config.SpokeCoreNamespace).Get(ctx, hubKubeConfigSecret, metav1.GetOptions{})
hubSecret, err := n.kubeClient.CoreV1().Secrets(config.KlusterletNamespace).Get(ctx, hubKubeConfigSecret, metav1.GetOptions{})
switch {
case errors.IsNotFound(err):
// Create an empty secret with placeholder
hubSecret = &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: hubKubeConfigSecret,
Namespace: config.SpokeCoreNamespace,
Namespace: config.KlusterletNamespace,
},
Data: map[string][]byte{"placeholder": []byte("placeholder")},
}
hubSecret, err = n.kubeClient.CoreV1().Secrets(config.SpokeCoreNamespace).Create(ctx, hubSecret, metav1.CreateOptions{})
hubSecret, err = n.kubeClient.CoreV1().Secrets(config.KlusterletNamespace).Create(ctx, hubSecret, metav1.CreateOptions{})
if err != nil {
helpers.UpdateNucleusSpokeStatus(ctx, n.nucleusClient, spokeCoreName, helpers.UpdateNucleusSpokeConditionFn(nucleusapiv1.StatusCondition{
Type: spokeCoreApplied, Status: metav1.ConditionFalse, Reason: "SpokeCoreApplyFailed",
helpers.UpdateKlusterletStatus(ctx, n.klusterletClient, klusterletName, helpers.UpdateKlusterletConditionFn(operatorapiv1.StatusCondition{
Type: klusterletApplied, Status: metav1.ConditionFalse, Reason: "KlusterletApplyFailed",
Message: fmt.Sprintf("Failed to create hub kubeconfig secret -n %q %q: %v", hubSecret.Namespace, hubSecret.Name, err),
}))
return err
}
case err != nil:
helpers.UpdateNucleusSpokeStatus(ctx, n.nucleusClient, spokeCoreName, helpers.UpdateNucleusSpokeConditionFn(nucleusapiv1.StatusCondition{
Type: spokeCoreApplied, Status: metav1.ConditionFalse, Reason: "SpokeCoreApplyFailed",
helpers.UpdateKlusterletStatus(ctx, n.klusterletClient, klusterletName, helpers.UpdateKlusterletConditionFn(operatorapiv1.StatusCondition{
Type: klusterletApplied, Status: metav1.ConditionFalse, Reason: "KlusterletApplyFailed",
Message: fmt.Sprintf("Failed to get hub kubeconfig secret with error %v", err),
}))
return err
@@ -240,10 +240,10 @@ func (n *nucleusSpokeController) sync(ctx context.Context, controllerContext fac
return assets.MustCreateAssetFromTemplate(name, bindata.MustAsset(filepath.Join("", name)), config).Data, nil
},
controllerContext.Recorder(),
"manifests/spoke/spoke-registration-deployment.yaml")
"manifests/klusterlet/klusterlet-registration-deployment.yaml")
if err != nil {
helpers.UpdateNucleusSpokeStatus(ctx, n.nucleusClient, spokeCoreName, helpers.UpdateNucleusSpokeConditionFn(nucleusapiv1.StatusCondition{
Type: spokeCoreApplied, Status: metav1.ConditionFalse, Reason: "SpokeCoreApplyFailed",
helpers.UpdateKlusterletStatus(ctx, n.klusterletClient, klusterletName, helpers.UpdateKlusterletConditionFn(operatorapiv1.StatusCondition{
Type: klusterletApplied, Status: metav1.ConditionFalse, Reason: "KlusterletApplyFailed",
Message: fmt.Sprintf("Failed to deploy registration deployment with error %v", err),
}))
return err
@@ -259,10 +259,10 @@ func (n *nucleusSpokeController) sync(ctx context.Context, controllerContext fac
return assets.MustCreateAssetFromTemplate(name, bindata.MustAsset(filepath.Join("", name)), config).Data, nil
},
controllerContext.Recorder(),
"manifests/spoke/spoke-work-deployment.yaml")
"manifests/klusterlet/klusterlet-work-deployment.yaml")
if err != nil {
helpers.UpdateNucleusSpokeStatus(ctx, n.nucleusClient, spokeCoreName, helpers.UpdateNucleusSpokeConditionFn(nucleusapiv1.StatusCondition{
Type: spokeCoreApplied, Status: metav1.ConditionFalse, Reason: "SpokeCoreApplyFailed",
helpers.UpdateKlusterletStatus(ctx, n.klusterletClient, klusterletName, helpers.UpdateKlusterletConditionFn(operatorapiv1.StatusCondition{
Type: klusterletApplied, Status: metav1.ConditionFalse, Reason: "KlusterletApplyFailed",
Message: fmt.Sprintf("Failed to deploy work deployment with error %v", err),
}))
return err
@@ -271,8 +271,8 @@ func (n *nucleusSpokeController) sync(ctx context.Context, controllerContext fac
n.workGeneration = generation
// if we get here, we have successfully applied everything and should indicate that
helpers.UpdateNucleusSpokeStatus(ctx, n.nucleusClient, spokeCoreName, helpers.UpdateNucleusSpokeConditionFn(nucleusapiv1.StatusCondition{
Type: spokeCoreApplied, Status: metav1.ConditionTrue, Reason: "SpokeCoreApplied",
helpers.UpdateKlusterletStatus(ctx, n.klusterletClient, klusterletName, helpers.UpdateKlusterletConditionFn(operatorapiv1.StatusCondition{
Type: klusterletApplied, Status: metav1.ConditionTrue, Reason: "KlusterletApplied",
Message: "Spoke Core Component Applied",
}))
@@ -285,7 +285,7 @@ func (n *nucleusSpokeController) sync(ctx context.Context, controllerContext fac
if config.ClusterName == "" {
clusterName := hubSecret.Data["cluster-name"]
if clusterName == nil {
helpers.UpdateNucleusSpokeStatus(ctx, n.nucleusClient, spokeCoreName, helpers.UpdateNucleusSpokeConditionFn(nucleusapiv1.StatusCondition{
helpers.UpdateKlusterletStatus(ctx, n.klusterletClient, klusterletName, helpers.UpdateKlusterletConditionFn(operatorapiv1.StatusCondition{
Type: spokeRegistrationDegraded, Status: metav1.ConditionTrue, Reason: "ClusterNameMissing",
Message: fmt.Sprintf("Failed to get cluster name from `kubectl get secret -n %q %q -ojsonpath='{.data.cluster-name}`. This is set by the spoke registration deployment.", hubSecret.Namespace, hubSecret.Name),
}))
@@ -296,7 +296,7 @@ func (n *nucleusSpokeController) sync(ctx context.Context, controllerContext fac
// If hub kubeconfig does not exist, return err.
if hubSecret.Data["kubeconfig"] == nil {
helpers.UpdateNucleusSpokeStatus(ctx, n.nucleusClient, spokeCoreName, helpers.UpdateNucleusSpokeConditionFn(nucleusapiv1.StatusCondition{
helpers.UpdateKlusterletStatus(ctx, n.klusterletClient, klusterletName, helpers.UpdateKlusterletConditionFn(operatorapiv1.StatusCondition{
Type: spokeRegistrationDegraded, Status: metav1.ConditionTrue, Reason: "HubKubeconfigMissing",
Message: fmt.Sprintf("Failed to get cluster name from `kubectl get secret -n %q %q -ojsonpath='{.data.kubeconfig}`. This is set by the spoke registration deployment, but the CSR must be approved by the cluster-admin on the hub.", hubSecret.Namespace, hubSecret.Name),
}))
@@ -304,29 +304,29 @@ func (n *nucleusSpokeController) sync(ctx context.Context, controllerContext fac
}
// TODO it is possible to verify the kubeconfig actually works.
helpers.UpdateNucleusSpokeStatus(ctx, n.nucleusClient, spokeCoreName, helpers.UpdateNucleusSpokeConditionFn(nucleusapiv1.StatusCondition{
helpers.UpdateKlusterletStatus(ctx, n.klusterletClient, klusterletName, helpers.UpdateKlusterletConditionFn(operatorapiv1.StatusCondition{
Type: spokeRegistrationDegraded, Status: metav1.ConditionFalse, Reason: "RegistrationFunctional",
Message: "Registration is managing credentials",
}))
return nil
}
func (n *nucleusSpokeController) cleanUp(ctx context.Context, controllerContext factory.SyncContext, config spokeConfig) error {
func (n *klusterletController) cleanUp(ctx context.Context, controllerContext factory.SyncContext, config spokeConfig) error {
// Remove deployment
registrationDeployment := fmt.Sprintf("%s-registration-agent", config.SpokeCoreName)
err := n.kubeClient.AppsV1().Deployments(config.SpokeCoreNamespace).Delete(ctx, registrationDeployment, metav1.DeleteOptions{})
registrationDeployment := fmt.Sprintf("%s-registration-agent", config.KlusterletName)
err := n.kubeClient.AppsV1().Deployments(config.KlusterletNamespace).Delete(ctx, registrationDeployment, metav1.DeleteOptions{})
if err != nil && !errors.IsNotFound(err) {
return err
}
controllerContext.Recorder().Eventf("DeploymentDeleted", "deployment %s is deleted", registrationDeployment)
workDeployment := fmt.Sprintf("%s-work-agent", config.SpokeCoreName)
err = n.kubeClient.AppsV1().Deployments(config.SpokeCoreNamespace).Delete(ctx, workDeployment, metav1.DeleteOptions{})
workDeployment := fmt.Sprintf("%s-work-agent", config.KlusterletName)
err = n.kubeClient.AppsV1().Deployments(config.KlusterletNamespace).Delete(ctx, workDeployment, metav1.DeleteOptions{})
if err != nil && !errors.IsNotFound(err) {
return err
}
// Remove secret
err = n.kubeClient.CoreV1().Secrets(config.SpokeCoreNamespace).Delete(ctx, config.HubKubeConfigSecret, metav1.DeleteOptions{})
err = n.kubeClient.CoreV1().Secrets(config.KlusterletNamespace).Delete(ctx, config.HubKubeConfigSecret, metav1.DeleteOptions{})
if err != nil && !errors.IsNotFound(err) {
return err
}
@@ -351,10 +351,10 @@ func (n *nucleusSpokeController) cleanUp(ctx context.Context, controllerContext
return nil
}
func (n *nucleusSpokeController) removeWorkFinalizer(ctx context.Context, deploy *nucleusapiv1.SpokeCore) error {
func (n *klusterletController) removeKlusterletFinalizer(ctx context.Context, deploy *operatorapiv1.Klusterlet) error {
copiedFinalizers := []string{}
for i := range deploy.Finalizers {
if deploy.Finalizers[i] == nucleusSpokeFinalizer {
if deploy.Finalizers[i] == klusterletFinalizer {
continue
}
copiedFinalizers = append(copiedFinalizers, deploy.Finalizers[i])
@@ -362,7 +362,7 @@ func (n *nucleusSpokeController) removeWorkFinalizer(ctx context.Context, deploy
if len(deploy.Finalizers) != len(copiedFinalizers) {
deploy.Finalizers = copiedFinalizers
_, err := n.nucleusClient.Update(ctx, deploy, metav1.UpdateOptions{})
_, err := n.klusterletClient.Update(ctx, deploy, metav1.UpdateOptions{})
return err
}
@@ -386,7 +386,7 @@ func readKubuConfigFromSecret(secret *corev1.Secret, config spokeConfig) (string
}
// TODO also read CABundle from ExternalServerURLs and set into registration deployment
func getServersFromSpokeCore(spokeCore *nucleusapiv1.SpokeCore) string {
func getServersFromKlusterlet(spokeCore *operatorapiv1.Klusterlet) string {
if spokeCore.Spec.ExternalServerURLs == nil {
return ""
}

View File

@@ -1,4 +1,4 @@
package spoke
package klusterlet
import (
"fmt"
@@ -7,9 +7,9 @@ import (
"time"
"github.com/davecgh/go-spew/spew"
fakenucleusclient "github.com/open-cluster-management/api/client/nucleus/clientset/versioned/fake"
nucleusinformers "github.com/open-cluster-management/api/client/nucleus/informers/externalversions"
nucleusapiv1 "github.com/open-cluster-management/api/nucleus/v1"
fakeoperatorclient "github.com/open-cluster-management/api/client/operator/clientset/versioned/fake"
operatorinformers "github.com/open-cluster-management/api/client/operator/informers/externalversions"
opratorapiv1 "github.com/open-cluster-management/api/operator/v1"
"github.com/open-cluster-management/nucleus/pkg/helpers"
"github.com/openshift/library-go/pkg/operator/events"
"github.com/openshift/library-go/pkg/operator/events/eventstesting"
@@ -26,9 +26,9 @@ import (
)
type testController struct {
controller *nucleusSpokeController
kubeClient *fakekube.Clientset
nucleusClient *fakenucleusclient.Clientset
controller *klusterletController
kubeClient *fakekube.Clientset
operatorClient *fakeoperatorclient.Clientset
}
type fakeSyncContext struct {
@@ -59,18 +59,18 @@ func newSecret(name, namespace string) *corev1.Secret {
}
}
func newSpokeCore(name, namespace, clustername string) *nucleusapiv1.SpokeCore {
return &nucleusapiv1.SpokeCore{
func newKlusterlet(name, namespace, clustername string) *opratorapiv1.Klusterlet {
return &opratorapiv1.Klusterlet{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Finalizers: []string{nucleusSpokeFinalizer},
Finalizers: []string{klusterletFinalizer},
},
Spec: nucleusapiv1.SpokeCoreSpec{
Spec: opratorapiv1.KlusterletSpec{
RegistrationImagePullSpec: "testregistration",
WorkImagePullSpec: "testwork",
ClusterName: clustername,
Namespace: namespace,
ExternalServerURLs: []nucleusapiv1.ServerURL{},
ExternalServerURLs: []opratorapiv1.ServerURL{},
},
}
}
@@ -83,24 +83,24 @@ func newNamespace(name string) *corev1.Namespace {
}
}
func newTestController(spokecore *nucleusapiv1.SpokeCore, objects ...runtime.Object) *testController {
func newTestController(klusterlet *opratorapiv1.Klusterlet, objects ...runtime.Object) *testController {
fakeKubeClient := fakekube.NewSimpleClientset(objects...)
fakeNucleusClient := fakenucleusclient.NewSimpleClientset(spokecore)
nucleusInformers := nucleusinformers.NewSharedInformerFactory(fakeNucleusClient, 5*time.Minute)
fakeOperatorClient := fakeoperatorclient.NewSimpleClientset(klusterlet)
operatorInformers := operatorinformers.NewSharedInformerFactory(fakeOperatorClient, 5*time.Minute)
hubController := &nucleusSpokeController{
nucleusClient: fakeNucleusClient.NucleusV1().SpokeCores(),
kubeClient: fakeKubeClient,
nucleusLister: nucleusInformers.Nucleus().V1().SpokeCores().Lister(),
hubController := &klusterletController{
klusterletClient: fakeOperatorClient.OperatorV1().Klusterlets(),
kubeClient: fakeKubeClient,
klusterletLister: operatorInformers.Operator().V1().Klusterlets().Lister(),
}
store := nucleusInformers.Nucleus().V1().SpokeCores().Informer().GetStore()
store.Add(spokecore)
store := operatorInformers.Operator().V1().Klusterlets().Informer().GetStore()
store.Add(klusterlet)
return &testController{
controller: hubController,
kubeClient: fakeKubeClient,
nucleusClient: fakeNucleusClient,
controller: hubController,
kubeClient: fakeKubeClient,
operatorClient: fakeOperatorClient,
}
}
@@ -120,21 +120,21 @@ func assertGet(t *testing.T, actual clienttesting.Action, group, version, resour
}
}
func namedCondition(name string, status metav1.ConditionStatus) nucleusapiv1.StatusCondition {
return nucleusapiv1.StatusCondition{Type: name, Status: status}
func namedCondition(name string, status metav1.ConditionStatus) opratorapiv1.StatusCondition {
return opratorapiv1.StatusCondition{Type: name, Status: status}
}
func assertOnlyConditions(t *testing.T, actual runtime.Object, expectedConditions ...nucleusapiv1.StatusCondition) {
func assertOnlyConditions(t *testing.T, actual runtime.Object, expectedConditions ...opratorapiv1.StatusCondition) {
t.Helper()
spokeCore := actual.(*nucleusapiv1.SpokeCore)
actualConditions := spokeCore.Status.Conditions
klusterlet := actual.(*opratorapiv1.Klusterlet)
actualConditions := klusterlet.Status.Conditions
if len(actualConditions) != len(expectedConditions) {
t.Errorf("expected %v condition but got: %v", len(expectedConditions), spew.Sdump(actualConditions))
}
for _, expectedCondition := range expectedConditions {
actual := helpers.FindNucleusCondition(actualConditions, expectedCondition.Type)
actual := helpers.FindOperatorCondition(actualConditions, expectedCondition.Type)
if actual == nil {
t.Errorf("missing %v in %v", spew.Sdump(expectedCondition), spew.Sdump(actual))
}
@@ -154,7 +154,7 @@ func ensureNameNamespace(t *testing.T, actualName, actualNamespace, name, namesp
}
}
func ensureObject(t *testing.T, object runtime.Object, spokeCore *nucleusapiv1.SpokeCore) {
func ensureObject(t *testing.T, object runtime.Object, klusterlet *opratorapiv1.Klusterlet) {
access, err := meta.Accessor(object)
if err != nil {
t.Errorf("Unable to access objectmeta: %v", err)
@@ -165,15 +165,15 @@ func ensureObject(t *testing.T, object runtime.Object, spokeCore *nucleusapiv1.S
if strings.Contains(access.GetName(), "registration") {
ensureNameNamespace(
t, access.GetName(), access.GetNamespace(),
fmt.Sprintf("%s-registration-agent", spokeCore.Name), spokeCore.Spec.Namespace)
if spokeCore.Spec.RegistrationImagePullSpec != o.Spec.Template.Spec.Containers[0].Image {
fmt.Sprintf("%s-registration-agent", klusterlet.Name), klusterlet.Spec.Namespace)
if klusterlet.Spec.RegistrationImagePullSpec != o.Spec.Template.Spec.Containers[0].Image {
t.Errorf("Image does not match to the expected.")
}
} else if strings.Contains(access.GetName(), "work") {
ensureNameNamespace(
t, access.GetName(), access.GetNamespace(),
fmt.Sprintf("%s-work-agent", spokeCore.Name), spokeCore.Spec.Namespace)
if spokeCore.Spec.WorkImagePullSpec != o.Spec.Template.Spec.Containers[0].Image {
fmt.Sprintf("%s-work-agent", klusterlet.Name), klusterlet.Spec.Namespace)
if klusterlet.Spec.WorkImagePullSpec != o.Spec.Template.Spec.Containers[0].Image {
t.Errorf("Image does not match to the expected.")
}
} else {
@@ -184,7 +184,7 @@ func ensureObject(t *testing.T, object runtime.Object, spokeCore *nucleusapiv1.S
// TestSyncDeploy test deployment of spoke components
func TestSyncDeploy(t *testing.T) {
spokeCore := newSpokeCore("testspoke", "testns", "cluster1")
spokeCore := newKlusterlet("testspoke", "testns", "cluster1")
bootStrapSecret := newSecret(bootstrapHubKubeConfigSecret, "testns")
hubKubeConfigSecret := newSecret(hubKubeConfigSecret, "testns")
hubKubeConfigSecret.Data["kubeconfig"] = []byte("dummuykubeconnfig")
@@ -214,28 +214,28 @@ func TestSyncDeploy(t *testing.T) {
ensureObject(t, object, spokeCore)
}
nucleusAction := controller.nucleusClient.Actions()
if len(nucleusAction) != 4 {
t.Errorf("Expect 4 actions in the sync loop, actual %#v", nucleusAction)
operatorAction := controller.operatorClient.Actions()
if len(operatorAction) != 4 {
t.Errorf("Expect 4 actions in the sync loop, actual %#v", operatorAction)
}
assertGet(t, nucleusAction[0], "nucleus.open-cluster-management.io", "v1", "spokecores")
assertAction(t, nucleusAction[1], "update")
assertOnlyConditions(t, nucleusAction[1].(clienttesting.UpdateActionImpl).Object,
namedCondition(spokeCoreApplied, metav1.ConditionTrue))
assertGet(t, nucleusAction[2], "nucleus.open-cluster-management.io", "v1", "spokecores")
assertAction(t, nucleusAction[3], "update")
assertOnlyConditions(t, nucleusAction[3].(clienttesting.UpdateActionImpl).Object,
namedCondition(spokeCoreApplied, metav1.ConditionTrue), namedCondition(spokeRegistrationDegraded, metav1.ConditionFalse))
assertGet(t, operatorAction[0], "operator.open-cluster-management.io", "v1", "klusterlets")
assertAction(t, operatorAction[1], "update")
assertOnlyConditions(t, operatorAction[1].(clienttesting.UpdateActionImpl).Object,
namedCondition(klusterletApplied, metav1.ConditionTrue))
assertGet(t, operatorAction[2], "operator.open-cluster-management.io", "v1", "klusterlets")
assertAction(t, operatorAction[3], "update")
assertOnlyConditions(t, operatorAction[3].(clienttesting.UpdateActionImpl).Object,
namedCondition(klusterletApplied, metav1.ConditionTrue), namedCondition(spokeRegistrationDegraded, metav1.ConditionFalse))
}
// TestSyncWithNoSecret test the scenario that bootstrap secret and hub config secret does not exist
func TestSyncWithNoSecret(t *testing.T) {
spokeCore := newSpokeCore("testspoke", "testns", "")
klusterlet := newKlusterlet("testspoke", "testns", "")
bootStrapSecret := newSecret(bootstrapHubKubeConfigSecret, "testns")
hubSecret := newSecret(hubKubeConfigSecret, "testns")
namespace := newNamespace("testns")
controller := newTestController(spokeCore, namespace)
controller := newTestController(klusterlet, namespace)
syncContext := newFakeSyncContext(t, "testspoke")
// Return err since bootstrap secret does not exist
@@ -243,17 +243,17 @@ func TestSyncWithNoSecret(t *testing.T) {
if err == nil {
t.Errorf("Expected error when sync")
}
nucleusAction := controller.nucleusClient.Actions()
if len(nucleusAction) != 2 {
t.Errorf("Expect 2 actions in the sync loop, actual %#v", nucleusAction)
operatorAction := controller.operatorClient.Actions()
if len(operatorAction) != 2 {
t.Errorf("Expect 2 actions in the sync loop, actual %#v", operatorAction)
}
assertGet(t, nucleusAction[0], "nucleus.open-cluster-management.io", "v1", "spokecores")
assertAction(t, nucleusAction[1], "update")
assertOnlyConditions(t, nucleusAction[1].(clienttesting.UpdateActionImpl).Object, namedCondition(spokeCoreApplied, metav1.ConditionFalse))
assertGet(t, operatorAction[0], "operator.open-cluster-management.io", "v1", "klusterlets")
assertAction(t, operatorAction[1], "update")
assertOnlyConditions(t, operatorAction[1].(clienttesting.UpdateActionImpl).Object, namedCondition(klusterletApplied, metav1.ConditionFalse))
// reset for round 2
controller.nucleusClient.ClearActions()
controller.operatorClient.ClearActions()
// Add bootstrap secret and sync again
controller.kubeClient.PrependReactor("get", "secrets", func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
if action.GetVerb() != "get" {
@@ -272,22 +272,22 @@ func TestSyncWithNoSecret(t *testing.T) {
if err == nil {
t.Errorf("Expected error when sync")
}
nucleusAction = controller.nucleusClient.Actions()
if len(nucleusAction) != 4 {
t.Errorf("Expect 4 actions in the sync loop, actual %#v", nucleusAction)
operatorAction = controller.operatorClient.Actions()
if len(operatorAction) != 4 {
t.Errorf("Expect 4 actions in the sync loop, actual %#v", operatorAction)
}
assertGet(t, nucleusAction[0], "nucleus.open-cluster-management.io", "v1", "spokecores")
assertAction(t, nucleusAction[1], "update")
assertOnlyConditions(t, nucleusAction[1].(clienttesting.UpdateActionImpl).Object,
namedCondition(spokeCoreApplied, metav1.ConditionTrue))
assertGet(t, nucleusAction[2], "nucleus.open-cluster-management.io", "v1", "spokecores")
assertAction(t, nucleusAction[3], "update")
assertOnlyConditions(t, nucleusAction[3].(clienttesting.UpdateActionImpl).Object,
namedCondition(spokeCoreApplied, metav1.ConditionTrue), namedCondition(spokeRegistrationDegraded, metav1.ConditionTrue))
assertGet(t, operatorAction[0], "operator.open-cluster-management.io", "v1", "klusterlets")
assertAction(t, operatorAction[1], "update")
assertOnlyConditions(t, operatorAction[1].(clienttesting.UpdateActionImpl).Object,
namedCondition(klusterletApplied, metav1.ConditionTrue))
assertGet(t, operatorAction[2], "operator.open-cluster-management.io", "v1", "klusterlets")
assertAction(t, operatorAction[3], "update")
assertOnlyConditions(t, operatorAction[3].(clienttesting.UpdateActionImpl).Object,
namedCondition(klusterletApplied, metav1.ConditionTrue), namedCondition(spokeRegistrationDegraded, metav1.ConditionTrue))
// reset for round 3
controller.nucleusClient.ClearActions()
controller.operatorClient.ClearActions()
// Add hub config secret and sync again
hubSecret.Data["kubeconfig"] = []byte("dummykubeconfig")
hubSecret.Data["cluster-name"] = []byte("cluster1")
@@ -307,21 +307,21 @@ func TestSyncWithNoSecret(t *testing.T) {
if err != nil {
t.Errorf("Expected no error when sync: %v", err)
}
nucleusAction = controller.nucleusClient.Actions()
if len(nucleusAction) != 3 {
t.Errorf("Expect 3 actions in the sync loop, actual %#v", nucleusAction)
operatorAction = controller.operatorClient.Actions()
if len(operatorAction) != 3 {
t.Errorf("Expect 3 actions in the sync loop, actual %#v", operatorAction)
}
assertGet(t, nucleusAction[0], "nucleus.open-cluster-management.io", "v1", "spokecores")
assertGet(t, nucleusAction[1], "nucleus.open-cluster-management.io", "v1", "spokecores")
assertAction(t, nucleusAction[2], "update")
assertOnlyConditions(t, nucleusAction[2].(clienttesting.UpdateActionImpl).Object,
namedCondition(spokeCoreApplied, metav1.ConditionTrue), namedCondition(spokeRegistrationDegraded, metav1.ConditionFalse))
assertGet(t, operatorAction[0], "operator.open-cluster-management.io", "v1", "klusterlets")
assertGet(t, operatorAction[1], "operator.open-cluster-management.io", "v1", "klusterlets")
assertAction(t, operatorAction[2], "update")
assertOnlyConditions(t, operatorAction[2].(clienttesting.UpdateActionImpl).Object,
namedCondition(klusterletApplied, metav1.ConditionTrue), namedCondition(spokeRegistrationDegraded, metav1.ConditionFalse))
}
// TestSyncDelete test cleanup hub deploy
func TestSyncDelete(t *testing.T) {
spokeCore := newSpokeCore("testspoke", "testns", "")
spokeCore := newKlusterlet("testspoke", "testns", "")
now := metav1.Now()
spokeCore.ObjectMeta.SetDeletionTimestamp(&now)
namespace := newNamespace("testns")
@@ -347,8 +347,8 @@ func TestSyncDelete(t *testing.T) {
}
}
// TestGetServersFromSpokeCore tests getServersFromSpokeCore func
func TestGetServersFromSpokeCore(t *testing.T) {
// TestGetServersFromKlusterlet tests getServersFromKlusterlet func
func TestGetServersFromKlusterlet(t *testing.T) {
cases := []struct {
name string
servers []string
@@ -378,12 +378,12 @@ func TestGetServersFromSpokeCore(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
spokeCore := newSpokeCore("testspoke", "testns", "")
spokeCore := newKlusterlet("testspoke", "testns", "")
for _, server := range c.servers {
spokeCore.Spec.ExternalServerURLs = append(spokeCore.Spec.ExternalServerURLs,
nucleusapiv1.ServerURL{URL: server})
opratorapiv1.ServerURL{URL: server})
}
actual := getServersFromSpokeCore(spokeCore)
actual := getServersFromKlusterlet(spokeCore)
if actual != c.expected {
t.Errorf("Expected to be same, actual %q, expected %q", actual, c.expected)
}

View File

@@ -10,14 +10,14 @@ import (
"github.com/openshift/library-go/pkg/controller/controllercmd"
nucleusclient "github.com/open-cluster-management/api/client/nucleus/clientset/versioned"
nucleusinformer "github.com/open-cluster-management/api/client/nucleus/informers/externalversions"
"github.com/open-cluster-management/nucleus/pkg/operators/hub"
"github.com/open-cluster-management/nucleus/pkg/operators/spoke"
operatorclient "github.com/open-cluster-management/api/client/operator/clientset/versioned"
operatorinformer "github.com/open-cluster-management/api/client/operator/informers/externalversions"
"github.com/open-cluster-management/nucleus/pkg/operators/clustermanager"
"github.com/open-cluster-management/nucleus/pkg/operators/klusterlet"
)
// RunNucleusHubOperator starts a new nucleus hub operator
func RunNucleusHubOperator(ctx context.Context, controllerContext *controllercmd.ControllerContext) error {
// RunClusterManagerOperator starts a new cluster manager operator
func RunClusterManagerOperator(ctx context.Context, controllerContext *controllercmd.ControllerContext) error {
// Build kubclient client and informer for spoke cluster
kubeClient, err := kubernetes.NewForConfig(controllerContext.KubeConfig)
if err != nil {
@@ -32,50 +32,50 @@ func RunNucleusHubOperator(ctx context.Context, controllerContext *controllercmd
return err
}
// Build nucleus client and informer
nucleusClient, err := nucleusclient.NewForConfig(controllerContext.KubeConfig)
// Build operator client and informer
operatorClient, err := operatorclient.NewForConfig(controllerContext.KubeConfig)
if err != nil {
return err
}
nucleusInformer := nucleusinformer.NewSharedInformerFactory(nucleusClient, 5*time.Minute)
operatorInformer := operatorinformer.NewSharedInformerFactory(operatorClient, 5*time.Minute)
hubcontroller := hub.NewNucleusHubController(
clusterManagerController := clustermanager.NewClusterManagerController(
kubeClient,
apiExtensionClient,
apiRegistrationClient.ApiregistrationV1(),
nucleusClient.NucleusV1().HubCores(),
nucleusInformer.Nucleus().V1().HubCores(),
operatorClient.OperatorV1().ClusterManagers(),
operatorInformer.Operator().V1().ClusterManagers(),
controllerContext.EventRecorder)
go nucleusInformer.Start(ctx.Done())
go hubcontroller.Run(ctx, 1)
go operatorInformer.Start(ctx.Done())
go clusterManagerController.Run(ctx, 1)
<-ctx.Done()
return nil
}
// RunNucleusSpokeOperator starts a new nucleus spoke operator
func RunNucleusSpokeOperator(ctx context.Context, controllerContext *controllercmd.ControllerContext) error {
// RunKlusterletOperator starts a new klusterlet operator
func RunKlusterletOperator(ctx context.Context, controllerContext *controllercmd.ControllerContext) error {
// Build kubclient client and informer for spoke cluster
kubeClient, err := kubernetes.NewForConfig(controllerContext.KubeConfig)
if err != nil {
return err
}
// Build nucleus client and informer
nucleusClient, err := nucleusclient.NewForConfig(controllerContext.KubeConfig)
// Build operator client and informer
operatorClient, err := operatorclient.NewForConfig(controllerContext.KubeConfig)
if err != nil {
return err
}
nucleusInformer := nucleusinformer.NewSharedInformerFactory(nucleusClient, 5*time.Minute)
operatorInformer := operatorinformer.NewSharedInformerFactory(operatorClient, 5*time.Minute)
spokeController := spoke.NewNucleusSpokeController(
klusterletController := klusterlet.NewKlusterletController(
kubeClient,
nucleusClient.NucleusV1().SpokeCores(),
nucleusInformer.Nucleus().V1().SpokeCores(),
operatorClient.OperatorV1().Klusterlets(),
operatorInformer.Operator().V1().Klusterlets(),
controllerContext.EventRecorder)
go nucleusInformer.Start(ctx.Done())
go spokeController.Run(ctx, 1)
go operatorInformer.Start(ctx.Done())
go klusterletController.Run(ctx, 1)
<-ctx.Done()
return nil
}

View File

@@ -1,632 +0,0 @@
// Code generated by go-bindata.
// sources:
// manifests/spoke/spoke-registration-clusterrole.yaml
// manifests/spoke/spoke-registration-clusterrolebinding.yaml
// manifests/spoke/spoke-registration-deployment.yaml
// manifests/spoke/spoke-registration-role.yaml
// manifests/spoke/spoke-registration-rolebinding.yaml
// manifests/spoke/spoke-registration-serviceaccount.yaml
// manifests/spoke/spoke-work-clusterrole.yaml
// manifests/spoke/spoke-work-clusterrolebinding-addition.yaml
// manifests/spoke/spoke-work-clusterrolebinding.yaml
// manifests/spoke/spoke-work-deployment.yaml
// manifests/spoke/spoke-work-serviceaccount.yaml
// DO NOT EDIT!
package bindata
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"time"
)
type asset struct {
bytes []byte
info os.FileInfo
}
type bindataFileInfo struct {
name string
size int64
mode os.FileMode
modTime time.Time
}
func (fi bindataFileInfo) Name() string {
return fi.name
}
func (fi bindataFileInfo) Size() int64 {
return fi.size
}
func (fi bindataFileInfo) Mode() os.FileMode {
return fi.mode
}
func (fi bindataFileInfo) ModTime() time.Time {
return fi.modTime
}
func (fi bindataFileInfo) IsDir() bool {
return false
}
func (fi bindataFileInfo) Sys() interface{} {
return nil
}
var _manifestsSpokeSpokeRegistrationClusterroleYaml = []byte(`# Clusterrole for work agent in addition to admin clusterrole.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: system:open-cluster-management:{{ .SpokeCoreName }}-registration-agent
rules:
# Allow agent to get/list/watch nodes.
- apiGroups: [""]
resources: ["nodes", "configmaps", "secrets"]
verbs: ["get", "list", "watch"]
- apiGroups: ["authorization.k8s.io"]
resources: ["subjectaccessreviews"]
verbs: ["create"]
`)
func manifestsSpokeSpokeRegistrationClusterroleYamlBytes() ([]byte, error) {
return _manifestsSpokeSpokeRegistrationClusterroleYaml, nil
}
func manifestsSpokeSpokeRegistrationClusterroleYaml() (*asset, error) {
bytes, err := manifestsSpokeSpokeRegistrationClusterroleYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/spoke/spoke-registration-clusterrole.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsSpokeSpokeRegistrationClusterrolebindingYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:open-cluster-management:{{ .SpokeCoreName }}-registration-agent
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:open-cluster-management:{{ .SpokeCoreName }}-registration-agent
subjects:
- kind: ServiceAccount
name: {{ .SpokeCoreName }}-registration-sa
namespace: {{ .SpokeCoreNamespace }}
`)
func manifestsSpokeSpokeRegistrationClusterrolebindingYamlBytes() ([]byte, error) {
return _manifestsSpokeSpokeRegistrationClusterrolebindingYaml, nil
}
func manifestsSpokeSpokeRegistrationClusterrolebindingYaml() (*asset, error) {
bytes, err := manifestsSpokeSpokeRegistrationClusterrolebindingYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/spoke/spoke-registration-clusterrolebinding.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsSpokeSpokeRegistrationDeploymentYaml = []byte(`kind: Deployment
apiVersion: apps/v1
metadata:
name: {{ .SpokeCoreName }}-registration-agent
namespace: {{ .SpokeCoreNamespace }}
labels:
app: spoke-registration-agent
spec:
replicas: 3
selector:
matchLabels:
app: spoke-registration-agent
template:
metadata:
labels:
app: spoke-registration-agent
spec:
serviceAccountName: {{ .SpokeCoreName }}-registration-sa
containers:
- name: spoke-agent
image: {{ .RegistrationImage }}
imagePullPolicy: IfNotPresent
args:
- "/registration"
- "agent"
- "--cluster-name={{ .ClusterName }}"
- "--bootstrap-kubeconfig=/spoke/bootstrap/kubeconfig"
- "--spoke-external-server-urls={{ .ExternalServerURL }}"
volumeMounts:
- name: bootstrap-secret
mountPath: "/spoke/bootstrap"
readOnly: true
- name: hub-kubeconfig-secret
mountPath: "/spoke/hub-kubeconfig"
readOnly: true
livenessProbe:
httpGet:
path: /healthz
scheme: HTTPS
port: 8443
initialDelaySeconds: 2
periodSeconds: 10
readinessProbe:
httpGet:
path: /healthz
scheme: HTTPS
port: 8443
initialDelaySeconds: 2
volumes:
- name: bootstrap-secret
secret:
secretName: {{ .BootStrapKubeConfigSecret }}
- name: hub-kubeconfig-secret
secret:
secretName: {{ .HubKubeConfigSecret }}
`)
func manifestsSpokeSpokeRegistrationDeploymentYamlBytes() ([]byte, error) {
return _manifestsSpokeSpokeRegistrationDeploymentYaml, nil
}
func manifestsSpokeSpokeRegistrationDeploymentYaml() (*asset, error) {
bytes, err := manifestsSpokeSpokeRegistrationDeploymentYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/spoke/spoke-registration-deployment.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsSpokeSpokeRegistrationRoleYaml = []byte(`# Role for registration agent.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: system:open-cluster-management:{{ .SpokeCoreName }}-registration-agent
namespace: {{ .SpokeCoreNamespace }}
rules:
- apiGroups: [""]
resources: ["configmaps", "secrets"]
verbs: ["get", "list", "watch", "create", "delete", "update", "patch"]
- apiGroups: ["", "events.k8s.io"]
resources: ["events"]
verbs: ["create", "patch", "update"]
`)
func manifestsSpokeSpokeRegistrationRoleYamlBytes() ([]byte, error) {
return _manifestsSpokeSpokeRegistrationRoleYaml, nil
}
func manifestsSpokeSpokeRegistrationRoleYaml() (*asset, error) {
bytes, err := manifestsSpokeSpokeRegistrationRoleYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/spoke/spoke-registration-role.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsSpokeSpokeRegistrationRolebindingYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: system:open-cluster-management:{{ .SpokeCoreName }}-registration-agent
namespace: {{ .SpokeCoreNamespace }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: system:open-cluster-management:{{ .SpokeCoreName }}-registration-agent
subjects:
- kind: ServiceAccount
name: {{ .SpokeCoreName }}-registration-sa
namespace: {{ .SpokeCoreNamespace }}
`)
func manifestsSpokeSpokeRegistrationRolebindingYamlBytes() ([]byte, error) {
return _manifestsSpokeSpokeRegistrationRolebindingYaml, nil
}
func manifestsSpokeSpokeRegistrationRolebindingYaml() (*asset, error) {
bytes, err := manifestsSpokeSpokeRegistrationRolebindingYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/spoke/spoke-registration-rolebinding.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsSpokeSpokeRegistrationServiceaccountYaml = []byte(`apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .SpokeCoreName }}-registration-sa
namespace: {{ .SpokeCoreNamespace }}
`)
func manifestsSpokeSpokeRegistrationServiceaccountYamlBytes() ([]byte, error) {
return _manifestsSpokeSpokeRegistrationServiceaccountYaml, nil
}
func manifestsSpokeSpokeRegistrationServiceaccountYaml() (*asset, error) {
bytes, err := manifestsSpokeSpokeRegistrationServiceaccountYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/spoke/spoke-registration-serviceaccount.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsSpokeSpokeWorkClusterroleYaml = []byte(`# Clusterrole for work agent in addition to admin clusterrole.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: system:open-cluster-management:{{ .SpokeCoreName }}-work-agent
rules:
# Allow agent to get/list/watch/create/delete crds.
- apiGroups: ["apiextensions.k8s.io"]
resources: ["customresourcedefinitions"]
verbs: ["get", "list", "watch", "create", "delete", "update"]
# Allow agent to create/delete namespaces, get/list are contained in admin role already
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["create", "delete"]
# Allow agent to manage role/rolebinding/clusterrole/clusterrolebinding
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["clusterrolebindings", "rolebindings"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["clusterroles", "roles"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete", "escalate", "bind"]
# Allow agent to create sar
- apiGroups: ["authorization.k8s.io"]
resources: ["subjectaccessreviews"]
verbs: ["create"]
# Allow agent to create events
- apiGroups: ["", "events.k8s.io"]
resources: ["events"]
verbs: ["create", "patch", "update"]
`)
func manifestsSpokeSpokeWorkClusterroleYamlBytes() ([]byte, error) {
return _manifestsSpokeSpokeWorkClusterroleYaml, nil
}
func manifestsSpokeSpokeWorkClusterroleYaml() (*asset, error) {
bytes, err := manifestsSpokeSpokeWorkClusterroleYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/spoke/spoke-work-clusterrole.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsSpokeSpokeWorkClusterrolebindingAdditionYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:open-cluster-management:{{ .SpokeCoreName }}-work-agent-addition
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:open-cluster-management:{{ .SpokeCoreName }}-work-agent
subjects:
- kind: ServiceAccount
name: {{ .SpokeCoreName }}-work-sa
namespace: {{ .SpokeCoreNamespace }}
`)
func manifestsSpokeSpokeWorkClusterrolebindingAdditionYamlBytes() ([]byte, error) {
return _manifestsSpokeSpokeWorkClusterrolebindingAdditionYaml, nil
}
func manifestsSpokeSpokeWorkClusterrolebindingAdditionYaml() (*asset, error) {
bytes, err := manifestsSpokeSpokeWorkClusterrolebindingAdditionYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/spoke/spoke-work-clusterrolebinding-addition.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsSpokeSpokeWorkClusterrolebindingYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:open-cluster-management:{{ .SpokeCoreName }}-work-agent
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
# We deploy a controller that could work with permission lower than cluster-admin, the tradeoff is
# responsivity because list/watch cannot be maintained over too many namespaces.
name: admin
subjects:
- kind: ServiceAccount
name: {{ .SpokeCoreName }}-work-sa
namespace: {{ .SpokeCoreNamespace }}
`)
func manifestsSpokeSpokeWorkClusterrolebindingYamlBytes() ([]byte, error) {
return _manifestsSpokeSpokeWorkClusterrolebindingYaml, nil
}
func manifestsSpokeSpokeWorkClusterrolebindingYaml() (*asset, error) {
bytes, err := manifestsSpokeSpokeWorkClusterrolebindingYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/spoke/spoke-work-clusterrolebinding.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsSpokeSpokeWorkDeploymentYaml = []byte(`kind: Deployment
apiVersion: apps/v1
metadata:
name: {{ .SpokeCoreName }}-work-agent
namespace: {{ .SpokeCoreNamespace }}
labels:
app: spoke-work-agent
spec:
replicas: 3
selector:
matchLabels:
app: spoke-work-agent
template:
metadata:
labels:
app: spoke-work-agent
spec:
serviceAccountName: {{ .SpokeCoreName }}-work-sa
containers:
- name: spoke-agent
image: {{ .WorkImage }}
imagePullPolicy: IfNotPresent
args:
- "/work"
- "agent"
- "--spoke-cluster-name={{ .ClusterName }}"
- "--hub-kubeconfig=/spoke/hub-kubeconfig/kubeconfig"
volumeMounts:
- name: hub-kubeconfig-secret
mountPath: "/spoke/hub-kubeconfig"
readOnly: true
livenessProbe:
httpGet:
path: /healthz
scheme: HTTPS
port: 8443
initialDelaySeconds: 2
periodSeconds: 10
readinessProbe:
httpGet:
path: /healthz
scheme: HTTPS
port: 8443
initialDelaySeconds: 2
volumes:
- name: hub-kubeconfig-secret
secret:
secretName: {{ .HubKubeConfigSecret }}
`)
func manifestsSpokeSpokeWorkDeploymentYamlBytes() ([]byte, error) {
return _manifestsSpokeSpokeWorkDeploymentYaml, nil
}
func manifestsSpokeSpokeWorkDeploymentYaml() (*asset, error) {
bytes, err := manifestsSpokeSpokeWorkDeploymentYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/spoke/spoke-work-deployment.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
var _manifestsSpokeSpokeWorkServiceaccountYaml = []byte(`apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .SpokeCoreName }}-work-sa
namespace: {{ .SpokeCoreNamespace }}
`)
func manifestsSpokeSpokeWorkServiceaccountYamlBytes() ([]byte, error) {
return _manifestsSpokeSpokeWorkServiceaccountYaml, nil
}
func manifestsSpokeSpokeWorkServiceaccountYaml() (*asset, error) {
bytes, err := manifestsSpokeSpokeWorkServiceaccountYamlBytes()
if err != nil {
return nil, err
}
info := bindataFileInfo{name: "manifests/spoke/spoke-work-serviceaccount.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
// Asset loads and returns the asset for the given name.
// It returns an error if the asset could not be found or
// could not be loaded.
func Asset(name string) ([]byte, error) {
cannonicalName := strings.Replace(name, "\\", "/", -1)
if f, ok := _bindata[cannonicalName]; ok {
a, err := f()
if err != nil {
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
}
return a.bytes, nil
}
return nil, fmt.Errorf("Asset %s not found", name)
}
// MustAsset is like Asset but panics when Asset would return an error.
// It simplifies safe initialization of global variables.
func MustAsset(name string) []byte {
a, err := Asset(name)
if err != nil {
panic("asset: Asset(" + name + "): " + err.Error())
}
return a
}
// AssetInfo loads and returns the asset info for the given name.
// It returns an error if the asset could not be found or
// could not be loaded.
func AssetInfo(name string) (os.FileInfo, error) {
cannonicalName := strings.Replace(name, "\\", "/", -1)
if f, ok := _bindata[cannonicalName]; ok {
a, err := f()
if err != nil {
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
}
return a.info, nil
}
return nil, fmt.Errorf("AssetInfo %s not found", name)
}
// AssetNames returns the names of the assets.
func AssetNames() []string {
names := make([]string, 0, len(_bindata))
for name := range _bindata {
names = append(names, name)
}
return names
}
// _bindata is a table, holding each asset generator, mapped to its name.
var _bindata = map[string]func() (*asset, error){
"manifests/spoke/spoke-registration-clusterrole.yaml": manifestsSpokeSpokeRegistrationClusterroleYaml,
"manifests/spoke/spoke-registration-clusterrolebinding.yaml": manifestsSpokeSpokeRegistrationClusterrolebindingYaml,
"manifests/spoke/spoke-registration-deployment.yaml": manifestsSpokeSpokeRegistrationDeploymentYaml,
"manifests/spoke/spoke-registration-role.yaml": manifestsSpokeSpokeRegistrationRoleYaml,
"manifests/spoke/spoke-registration-rolebinding.yaml": manifestsSpokeSpokeRegistrationRolebindingYaml,
"manifests/spoke/spoke-registration-serviceaccount.yaml": manifestsSpokeSpokeRegistrationServiceaccountYaml,
"manifests/spoke/spoke-work-clusterrole.yaml": manifestsSpokeSpokeWorkClusterroleYaml,
"manifests/spoke/spoke-work-clusterrolebinding-addition.yaml": manifestsSpokeSpokeWorkClusterrolebindingAdditionYaml,
"manifests/spoke/spoke-work-clusterrolebinding.yaml": manifestsSpokeSpokeWorkClusterrolebindingYaml,
"manifests/spoke/spoke-work-deployment.yaml": manifestsSpokeSpokeWorkDeploymentYaml,
"manifests/spoke/spoke-work-serviceaccount.yaml": manifestsSpokeSpokeWorkServiceaccountYaml,
}
// AssetDir returns the file names below a certain
// directory embedded in the file by go-bindata.
// For example if you run go-bindata on data/... and data contains the
// following hierarchy:
// data/
// foo.txt
// img/
// a.png
// b.png
// then AssetDir("data") would return []string{"foo.txt", "img"}
// AssetDir("data/img") would return []string{"a.png", "b.png"}
// AssetDir("foo.txt") and AssetDir("notexist") would return an error
// AssetDir("") will return []string{"data"}.
func AssetDir(name string) ([]string, error) {
node := _bintree
if len(name) != 0 {
cannonicalName := strings.Replace(name, "\\", "/", -1)
pathList := strings.Split(cannonicalName, "/")
for _, p := range pathList {
node = node.Children[p]
if node == nil {
return nil, fmt.Errorf("Asset %s not found", name)
}
}
}
if node.Func != nil {
return nil, fmt.Errorf("Asset %s not found", name)
}
rv := make([]string, 0, len(node.Children))
for childName := range node.Children {
rv = append(rv, childName)
}
return rv, nil
}
type bintree struct {
Func func() (*asset, error)
Children map[string]*bintree
}
var _bintree = &bintree{nil, map[string]*bintree{
"manifests": {nil, map[string]*bintree{
"spoke": {nil, map[string]*bintree{
"spoke-registration-clusterrole.yaml": {manifestsSpokeSpokeRegistrationClusterroleYaml, map[string]*bintree{}},
"spoke-registration-clusterrolebinding.yaml": {manifestsSpokeSpokeRegistrationClusterrolebindingYaml, map[string]*bintree{}},
"spoke-registration-deployment.yaml": {manifestsSpokeSpokeRegistrationDeploymentYaml, map[string]*bintree{}},
"spoke-registration-role.yaml": {manifestsSpokeSpokeRegistrationRoleYaml, map[string]*bintree{}},
"spoke-registration-rolebinding.yaml": {manifestsSpokeSpokeRegistrationRolebindingYaml, map[string]*bintree{}},
"spoke-registration-serviceaccount.yaml": {manifestsSpokeSpokeRegistrationServiceaccountYaml, map[string]*bintree{}},
"spoke-work-clusterrole.yaml": {manifestsSpokeSpokeWorkClusterroleYaml, map[string]*bintree{}},
"spoke-work-clusterrolebinding-addition.yaml": {manifestsSpokeSpokeWorkClusterrolebindingAdditionYaml, map[string]*bintree{}},
"spoke-work-clusterrolebinding.yaml": {manifestsSpokeSpokeWorkClusterrolebindingYaml, map[string]*bintree{}},
"spoke-work-deployment.yaml": {manifestsSpokeSpokeWorkDeploymentYaml, map[string]*bintree{}},
"spoke-work-serviceaccount.yaml": {manifestsSpokeSpokeWorkServiceaccountYaml, map[string]*bintree{}},
}},
}},
}}
// RestoreAsset restores an asset under the given directory
func RestoreAsset(dir, name string) error {
data, err := Asset(name)
if err != nil {
return err
}
info, err := AssetInfo(name)
if err != nil {
return err
}
err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755))
if err != nil {
return err
}
err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
if err != nil {
return err
}
err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
if err != nil {
return err
}
return nil
}
// RestoreAssets restores an asset under the given directory recursively
func RestoreAssets(dir, name string) error {
children, err := AssetDir(name)
// File
if err != nil {
return RestoreAsset(dir, name)
}
// Dir
for _, child := range children {
err = RestoreAssets(dir, filepath.Join(name, child))
if err != nil {
return err
}
}
return nil
}
func _filePath(dir, name string) string {
cannonicalName := strings.Replace(name, "\\", "/", -1)
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
}

View File

@@ -1,4 +1,4 @@
// Package integration provides integration tests for open-cluster-management nucleus, the test cases include
// - TODO deploy/update/remvoe the hub core
// - TODO deploy/update/remvoe the cluster manager
// - TODO deploy/update/remvoe the spoke agents
package integration

View File

@@ -15,11 +15,11 @@ import (
"github.com/open-cluster-management/nucleus/pkg/operators"
"github.com/open-cluster-management/nucleus/test/integration/util"
nucleusapiv1 "github.com/open-cluster-management/api/nucleus/v1"
operatorapiv1 "github.com/open-cluster-management/api/operator/v1"
)
func startHubOperator(ctx context.Context) {
err := operators.RunNucleusHubOperator(ctx, &controllercmd.ControllerContext{
err := operators.RunClusterManagerOperator(ctx, &controllercmd.ControllerContext{
KubeConfig: restConfig,
EventRecorder: util.NewIntegrationTestEventRecorder("integration"),
})
@@ -29,7 +29,7 @@ func startHubOperator(ctx context.Context) {
var _ = ginkgo.Describe("HubCore", func() {
var cancel context.CancelFunc
var err error
var hubCoreName string
var clusterManagerName string
var hubRegistrationClusterRole string
var hubWebhookClusterRole string
var hubRegistrationSA string
@@ -46,15 +46,15 @@ var _ = ginkgo.Describe("HubCore", func() {
})
ginkgo.JustBeforeEach(func() {
hubcore := &nucleusapiv1.HubCore{
clusterManager := &operatorapiv1.ClusterManager{
ObjectMeta: metav1.ObjectMeta{
Name: hubCoreName,
Name: clusterManagerName,
},
Spec: nucleusapiv1.HubCoreSpec{
Spec: operatorapiv1.ClusterManagerSpec{
RegistrationImagePullSpec: "quay.io/open-cluster-management/registration",
},
}
hubcore, err = nucleusClient.NucleusV1().HubCores().Create(context.Background(), hubcore, metav1.CreateOptions{})
_, err = operatorClient.OperatorV1().ClusterManagers().Create(context.Background(), clusterManager, metav1.CreateOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
})
@@ -66,13 +66,13 @@ var _ = ginkgo.Describe("HubCore", func() {
ginkgo.Context("Deploy and clean hub component", func() {
ginkgo.BeforeEach(func() {
hubCoreName = "hub"
hubRegistrationClusterRole = fmt.Sprintf("system:open-cluster-management:%s-registration-controller", hubCoreName)
hubWebhookClusterRole = fmt.Sprintf("system:open-cluster-management:%s-registration-webhook", hubCoreName)
hubRegistrationSA = fmt.Sprintf("%s-registration-controller-sa", hubCoreName)
hubWebhookSA = fmt.Sprintf("%s-registration-webhook-sa", hubCoreName)
hubRegistrationDeployment = fmt.Sprintf("%s-registration-controller", hubCoreName)
hubWebhookDeployment = fmt.Sprintf("%s-registration-webhook", hubCoreName)
clusterManagerName = "hub"
hubRegistrationClusterRole = fmt.Sprintf("system:open-cluster-management:%s-registration-controller", clusterManagerName)
hubWebhookClusterRole = fmt.Sprintf("system:open-cluster-management:%s-registration-webhook", clusterManagerName)
hubRegistrationSA = fmt.Sprintf("%s-registration-controller-sa", clusterManagerName)
hubWebhookSA = fmt.Sprintf("%s-registration-webhook-sa", clusterManagerName)
hubRegistrationDeployment = fmt.Sprintf("%s-registration-controller", clusterManagerName)
hubWebhookDeployment = fmt.Sprintf("%s-registration-webhook", clusterManagerName)
webhookSecret = "webhook-serving-cert"
validtingWebhook = "spokeclustervalidators.admission.cluster.open-cluster-management.io"
})
@@ -168,7 +168,7 @@ var _ = ginkgo.Describe("HubCore", func() {
return true
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue())
err := nucleusClient.NucleusV1().HubCores().Delete(context.Background(), hubCoreName, metav1.DeleteOptions{})
err := operatorClient.OperatorV1().ClusterManagers().Delete(context.Background(), clusterManagerName, metav1.DeleteOptions{})
gomega.Expect(err).NotTo(gomega.HaveOccurred())
// Check namespace deletion

View File

@@ -15,7 +15,7 @@ import (
logf "sigs.k8s.io/controller-runtime/pkg/log"
nucleusclient "github.com/open-cluster-management/api/client/nucleus/clientset/versioned"
operatorclient "github.com/open-cluster-management/api/client/operator/clientset/versioned"
)
func TestIntegration(t *testing.T) {
@@ -36,7 +36,7 @@ var kubeClient kubernetes.Interface
var restConfig *rest.Config
var nucleusClient nucleusclient.Interface
var operatorClient operatorclient.Interface
var _ = ginkgo.BeforeSuite(func(done ginkgo.Done) {
logf.SetLogger(zap.LoggerTo(ginkgo.GinkgoWriter, true))
@@ -49,7 +49,7 @@ var _ = ginkgo.BeforeSuite(func(done ginkgo.Done) {
testEnv = &envtest.Environment{
ErrorIfCRDPathMissing: true,
CRDDirectoryPaths: []string{
filepath.Join(".", "vendor", "github.com", "open-cluster-management", "api", "nucleus", "v1"),
filepath.Join(".", "vendor", "github.com", "open-cluster-management", "api", "operator", "v1"),
},
}
cfg, err := testEnv.Start()
@@ -60,7 +60,7 @@ var _ = ginkgo.BeforeSuite(func(done ginkgo.Done) {
kubeClient, err = kubernetes.NewForConfig(cfg)
gomega.Expect(err).ToNot(gomega.HaveOccurred())
gomega.Expect(kubeClient).ToNot(gomega.BeNil())
nucleusClient, err = nucleusclient.NewForConfig(cfg)
operatorClient, err = operatorclient.NewForConfig(cfg)
gomega.Expect(err).ToNot(gomega.HaveOccurred())
gomega.Expect(kubeClient).ToNot(gomega.BeNil())

16
vendor/github.com/go-bindata/go-bindata/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,16 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Goland project files
.idea/
*.iml

View File

@@ -1,5 +1,7 @@
## bindata
[![Go Report Card](https://goreportcard.com/badge/github.com/go-bindata/bindata)](https://goreportcard.com/report/github.com/go-bindata/bindata)
This package converts any file into managable Go source code. Useful for
embedding binary data into a go program. The file data is optionally gzip
compressed before being converted to a raw byte slice.
@@ -13,7 +15,7 @@ output being generated.
To install the library and command line program, use the following:
go get -u github.com/jteeuwen/go-bindata/...
go get -u github.com/go-bindata/go-bindata/...
### Usage
@@ -182,8 +184,16 @@ format is specified at build time with the appropriate tags.
The tags are appended to a `// +build` line in the beginning of the output file
and must follow the build tags syntax specified by the go tool.
### Related projects
### Serve assets with `net/http`
[go-bindata-assetfs](https://github.com/elazarl/go-bindata-assetfs#readme) -
implements `http.FileSystem` interface. Allows you to serve assets with `net/http`.
With the `-fs` flag, `go-bindata` will add an `AssetFile()` method returning an `http.FileSystem` interface:
$ go-bindata -fs -prefix "static/" static/
Use `-prefix` flag to strip first level dir, then in your `net/http` router, you can use `AssetFile()` with `http.FileServer()` like:
```go
mux := http.NewServeMux()
mux.Handle("/static", http.FileServer(AssetFile()))
http.ListenAndServe(":8080", mux)
```

1
vendor/github.com/go-bindata/go-bindata/_config.yml generated vendored Normal file
View File

@@ -0,0 +1 @@
theme: jekyll-theme-cayman

View File

@@ -106,6 +106,10 @@ type Config struct {
// the file data when called. Defaults to false.
NoCompress bool
// HttpFileSystem means whether generate return http.FileSystem interface
// instance's function.When true,will generate relate code.
HttpFileSystem bool
// Perform a debug build. This generates an asset file, which
// loads the asset contents directly from disk at their original
// location, instead of embedding the contents in the code.
@@ -148,6 +152,7 @@ func NewConfig() *Config {
c.Package = "main"
c.NoMemCopy = false
c.NoCompress = false
c.HttpFileSystem = false
c.Debug = false
c.Output = "./bindata.go"
c.Ignore = make([]*regexp.Regexp, 0)

View File

@@ -50,7 +50,7 @@ func Translate(c *Config) error {
defer bfd.Flush()
// Write the header. This makes e.g. Github ignore diffs in generated files.
if _, err = fmt.Fprint(bfd, "// Code generated by go-bindata.\n"); err != nil {
if _, err = fmt.Fprintf(bfd, "// Code generated for package %s by go-bindata DO NOT EDIT. (@generated)\n", c.Package); err != nil {
return err
}
if _, err = fmt.Fprint(bfd, "// sources:\n"); err != nil {
@@ -68,9 +68,9 @@ func Translate(c *Config) error {
return err
}
}
if _, err = fmt.Fprint(bfd, "// DO NOT EDIT!\n\n"); err != nil {
return err
}
//if _, err = fmt.Fprint(bfd, "// DO NOT EDIT!\n\n"); err != nil {
// return err
//}
// Write build tags, if applicable.
if len(c.Tags) > 0 {
@@ -109,7 +109,7 @@ func Translate(c *Config) error {
return writeRestore(bfd)
}
// Implement sort.Interface for []os.FileInfo based on Name()
// ByName implements sort.Interface for []os.FileInfo based on Name()
type ByName []os.FileInfo
func (v ByName) Len() int { return len(v) }

View File

@@ -11,7 +11,12 @@ import (
// writeDebug writes the debug code file.
func writeDebug(w io.Writer, c *Config, toc []Asset) error {
err := writeDebugHeader(w)
err := writeDebugHeader(w, c)
if err != nil {
return err
}
err = writeAssetFS(w, c)
if err != nil {
return err
}
@@ -28,13 +33,29 @@ func writeDebug(w io.Writer, c *Config, toc []Asset) error {
// writeDebugHeader writes output file headers.
// This targets debug builds.
func writeDebugHeader(w io.Writer) error {
_, err := fmt.Fprintf(w, `import (
func writeDebugHeader(w io.Writer, c *Config) error {
var header string
if c.HttpFileSystem {
header = `import (
"bytes"
"net/http"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"time"`
} else {
header = `import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"`
}
_, err := fmt.Fprintf(w, `%s
)
// bindataRead reads the given file from disk. It returns an error on failure.
@@ -51,7 +72,7 @@ type asset struct {
info os.FileInfo
}
`)
`, header)
return err
}

102
vendor/github.com/go-bindata/go-bindata/file.go generated vendored Normal file
View File

@@ -0,0 +1,102 @@
package bindata
import (
"fmt"
"io"
)
func writeAssetFS(w io.Writer, c *Config) error {
if !c.HttpFileSystem {
return nil
}
_, err := fmt.Fprintf(w, `
type assetFile struct {
*bytes.Reader
name string
childInfos []os.FileInfo
childInfoOffset int
}
type assetOperator struct{}
// Open implement http.FileSystem interface
func (f *assetOperator) Open(name string) (http.File, error) {
var err error
if len(name) > 0 && name[0] == '/' {
name = name[1:]
}
content, err := Asset(name)
if err == nil {
return &assetFile{name: name, Reader: bytes.NewReader(content)}, nil
}
children, err := AssetDir(name)
if err == nil {
childInfos := make([]os.FileInfo, 0, len(children))
for _, child := range children {
childPath := filepath.Join(name, child)
info, errInfo := AssetInfo(filepath.Join(name, child))
if errInfo == nil {
childInfos = append(childInfos, info)
} else {
childInfos = append(childInfos, newDirFileInfo(childPath))
}
}
return &assetFile{name: name, childInfos: childInfos}, nil
} else {
// If the error is not found, return an error that will
// result in a 404 error. Otherwise the server returns
// a 500 error for files not found.
if strings.Contains(err.Error(), "not found") {
return nil, os.ErrNotExist
}
return nil, err
}
}
// Close no need do anything
func (f *assetFile) Close() error {
return nil
}
// Readdir read dir's children file info
func (f *assetFile) Readdir(count int) ([]os.FileInfo, error) {
if len(f.childInfos) == 0 {
return nil, os.ErrNotExist
}
if count <= 0 {
return f.childInfos, nil
}
if f.childInfoOffset+count > len(f.childInfos) {
count = len(f.childInfos) - f.childInfoOffset
}
offset := f.childInfoOffset
f.childInfoOffset += count
return f.childInfos[offset : offset+count], nil
}
// Stat read file info from asset item
func (f *assetFile) Stat() (os.FileInfo, error) {
if len(f.childInfos) != 0 {
return newDirFileInfo(f.name), nil
}
return AssetInfo(f.name)
}
// newDirFileInfo return default dir file info
func newDirFileInfo(name string) os.FileInfo {
return &bindataFileInfo{
name: name,
size: 0,
mode: os.FileMode(2147484068), // equal os.FileMode(0644)|os.ModeDir
modTime: time.Time{}}
}
// AssetFile return a http.FileSystem instance that data backend by asset
func AssetFile() http.FileSystem {
return &assetOperator{}
}
`)
return err
}

View File

@@ -0,0 +1 @@
go-bindata

View File

@@ -12,7 +12,7 @@ import (
"regexp"
"strings"
"github.com/jteeuwen/go-bindata"
"github.com/go-bindata/go-bindata"
)
func main() {
@@ -48,6 +48,7 @@ func parseArgs() *bindata.Config {
flag.BoolVar(&c.NoMemCopy, "nomemcopy", c.NoMemCopy, "Use a .rodata hack to get rid of unnecessary memcopies. Refer to the documentation to see what implications this carries.")
flag.BoolVar(&c.NoCompress, "nocompress", c.NoCompress, "Assets will *not* be GZIP compressed when this flag is specified.")
flag.BoolVar(&c.NoMetadata, "nometadata", c.NoMetadata, "Assets will not preserve size, mode, and modtime info.")
flag.BoolVar(&c.HttpFileSystem, "fs", c.HttpFileSystem, "Whether generate instance http.FileSystem interface code.")
flag.UintVar(&c.Mode, "mode", c.Mode, "Optional file mode override for all files.")
flag.Int64Var(&c.ModTime, "modtime", c.ModTime, "Optional modification unix timestamp override for all files.")
flag.StringVar(&c.Output, "o", c.Output, "Optional name of the output file to be generated.")

View File

@@ -23,7 +23,7 @@ var AppVersionRev string
func Version() string {
if len(AppVersionRev) == 0 {
AppVersionRev = "0"
AppVersionRev = "2"
}
return fmt.Sprintf("%s %d.%d.%s (Go runtime %s).\nCopyright (c) 2010-2013, Jim Teeuwen.",

View File

@@ -21,6 +21,11 @@ func writeRelease(w io.Writer, c *Config, toc []Asset) error {
return err
}
err = writeAssetFS(w, c)
if err != nil {
return err
}
for i := range toc {
err = writeReleaseAsset(w, c, &toc[i])
if err != nil {
@@ -37,15 +42,15 @@ func writeReleaseHeader(w io.Writer, c *Config) error {
var err error
if c.NoCompress {
if c.NoMemCopy {
err = header_uncompressed_nomemcopy(w)
err = header_uncompressed_nomemcopy(w, c)
} else {
err = header_uncompressed_memcopy(w)
err = header_uncompressed_memcopy(w, c)
}
} else {
if c.NoMemCopy {
err = header_compressed_nomemcopy(w)
err = header_compressed_nomemcopy(w, c)
} else {
err = header_compressed_memcopy(w)
err = header_compressed_memcopy(w, c)
}
}
if err != nil {
@@ -97,8 +102,23 @@ func sanitize(b []byte) []byte {
return bytes.Replace(b, []byte("\xEF\xBB\xBF"), []byte("`+\"\\xEF\\xBB\\xBF\"+`"), -1)
}
func header_compressed_nomemcopy(w io.Writer) error {
_, err := fmt.Fprintf(w, `import (
func header_compressed_nomemcopy(w io.Writer, c *Config) error {
var header string
if c.HttpFileSystem {
header = `import (
"bytes"
"compress/gzip"
"fmt"
"net/http"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
"time"`
} else {
header = `import (
"bytes"
"compress/gzip"
"fmt"
@@ -107,7 +127,10 @@ func header_compressed_nomemcopy(w io.Writer) error {
"os"
"path/filepath"
"strings"
"time"
"time"`
}
_, err := fmt.Fprintf(w, `%s
)
func bindataRead(data, name string) ([]byte, error) {
@@ -130,12 +153,27 @@ func bindataRead(data, name string) ([]byte, error) {
return buf.Bytes(), nil
}
`)
`, header)
return err
}
func header_compressed_memcopy(w io.Writer) error {
_, err := fmt.Fprintf(w, `import (
func header_compressed_memcopy(w io.Writer, c *Config) error {
var header string
if c.HttpFileSystem {
header = `import (
"bytes"
"compress/gzip"
"fmt"
"net/http"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
"time"`
} else {
header = `import (
"bytes"
"compress/gzip"
"fmt"
@@ -144,7 +182,10 @@ func header_compressed_memcopy(w io.Writer) error {
"os"
"path/filepath"
"strings"
"time"
"time"`
}
_, err := fmt.Fprintf(w, `%s
)
func bindataRead(data []byte, name string) ([]byte, error) {
@@ -167,12 +208,27 @@ func bindataRead(data []byte, name string) ([]byte, error) {
return buf.Bytes(), nil
}
`)
`, header)
return err
}
func header_uncompressed_nomemcopy(w io.Writer) error {
_, err := fmt.Fprintf(w, `import (
func header_uncompressed_nomemcopy(w io.Writer, c *Config) error {
var header string
if c.HttpFileSystem {
header = `import (
"bytes"
"fmt"
"net/http"
"io/ioutil"
"os"
"path/filepath"
"reflect"
"strings"
"time"
"unsafe"`
} else {
header = `import (
"fmt"
"io/ioutil"
"os"
@@ -180,7 +236,10 @@ func header_uncompressed_nomemcopy(w io.Writer) error {
"reflect"
"strings"
"time"
"unsafe"
"unsafe"`
}
_, err := fmt.Fprintf(w, `%s
)
func bindataRead(data, name string) ([]byte, error) {
@@ -194,20 +253,36 @@ func bindataRead(data, name string) ([]byte, error) {
return b, nil
}
`)
`, header)
return err
}
func header_uncompressed_memcopy(w io.Writer) error {
_, err := fmt.Fprintf(w, `import (
func header_uncompressed_memcopy(w io.Writer, c *Config) error {
var header string
if c.HttpFileSystem {
header = `import (
"bytes"
"fmt"
"net/http"
"io/ioutil"
"os"
"path/filepath"
"strings"
"time"`
} else {
header = `import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"time"
"time"`
}
_, err := fmt.Fprintf(w, `%s
)
`)
`, header)
return err
}
@@ -224,21 +299,32 @@ type bindataFileInfo struct {
modTime time.Time
}
// Name return file name
func (fi bindataFileInfo) Name() string {
return fi.name
}
// Size return file size
func (fi bindataFileInfo) Size() int64 {
return fi.size
}
// Mode return file mode
func (fi bindataFileInfo) Mode() os.FileMode {
return fi.mode
}
// Mode return file modify time
func (fi bindataFileInfo) ModTime() time.Time {
return fi.modTime
}
// IsDir return file whether a directory
func (fi bindataFileInfo) IsDir() bool {
return false
return fi.mode&os.ModeDir != 0
}
// Sys return file is sys mode
func (fi bindataFileInfo) Sys() interface{} {
return nil
}

View File

@@ -57,7 +57,6 @@ func _filePath(dir, name string) string {
cannonicalName := strings.Replace(name, "\\", "/", -1)
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
}
`)
return err
}

Some files were not shown because too many files have changed in this diff Show More