diff --git a/deploy/cluster-manager/crds/0000_01_operator.open-cluster-management.io_clustermanagers.crd.yaml b/deploy/cluster-manager/crds/0000_01_operator.open-cluster-management.io_clustermanagers.crd.yaml index b330faea7..88f5a55c7 100644 --- a/deploy/cluster-manager/crds/0000_01_operator.open-cluster-management.io_clustermanagers.crd.yaml +++ b/deploy/cluster-manager/crds/0000_01_operator.open-cluster-management.io_clustermanagers.crd.yaml @@ -39,7 +39,11 @@ spec: properties: registrationImagePullSpec: description: RegistrationImagePullSpec represents the desired image - of registration controller installed on hub. + of registration controller/webhook installed on hub. + type: string + workImagePullSpec: + description: WorkImagePullSpec represents the desired image configuration + of work controller/webhook installed on hub. type: string status: description: Status represents the current status of controllers that govern diff --git a/deploy/cluster-manager/crds/operator_open-cluster-management_clustermanagers.cr.yaml b/deploy/cluster-manager/crds/operator_open-cluster-management_clustermanagers.cr.yaml index e2c3c714f..3b12effab 100644 --- a/deploy/cluster-manager/crds/operator_open-cluster-management_clustermanagers.cr.yaml +++ b/deploy/cluster-manager/crds/operator_open-cluster-management_clustermanagers.cr.yaml @@ -4,3 +4,4 @@ metadata: name: cluster-manager spec: registrationImagePullSpec: quay.io/open-cluster-management/registration + workImagePullSpec: quay.io/open-cluster-management/work diff --git a/deploy/cluster-manager/olm-catalog/cluster-manager/manifests/0000_01_operator.open-cluster-management.io_clustermanagers.crd.yaml b/deploy/cluster-manager/olm-catalog/cluster-manager/manifests/0000_01_operator.open-cluster-management.io_clustermanagers.crd.yaml index b330faea7..88f5a55c7 100644 --- a/deploy/cluster-manager/olm-catalog/cluster-manager/manifests/0000_01_operator.open-cluster-management.io_clustermanagers.crd.yaml +++ b/deploy/cluster-manager/olm-catalog/cluster-manager/manifests/0000_01_operator.open-cluster-management.io_clustermanagers.crd.yaml @@ -39,7 +39,11 @@ spec: properties: registrationImagePullSpec: description: RegistrationImagePullSpec represents the desired image - of registration controller installed on hub. + of registration controller/webhook installed on hub. + type: string + workImagePullSpec: + description: WorkImagePullSpec represents the desired image configuration + of work controller/webhook installed on hub. type: string status: description: Status represents the current status of controllers that govern diff --git a/deploy/cluster-manager/olm-catalog/cluster-manager/manifests/cluster-manager.clusterserviceversion.yaml b/deploy/cluster-manager/olm-catalog/cluster-manager/manifests/cluster-manager.clusterserviceversion.yaml index a963eb604..9fc2f861b 100644 --- a/deploy/cluster-manager/olm-catalog/cluster-manager/manifests/cluster-manager.clusterserviceversion.yaml +++ b/deploy/cluster-manager/olm-catalog/cluster-manager/manifests/cluster-manager.clusterserviceversion.yaml @@ -11,7 +11,8 @@ metadata: "name": "cluster-manager" }, "spec": { - "registrationImagePullSpec": "quay.io/open-cluster-management/registration" + "registrationImagePullSpec": "quay.io/open-cluster-management/registration", + "workImagePullSpec": "quay.io/open-cluster-management/work" } } ] diff --git a/go.mod b/go.mod index 93073bef7..28a1d52c3 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( 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-20200715201722-3c3c076bf062 + github.com/open-cluster-management/api v0.0.0-20200806152638-5caae08712f5 github.com/openshift/api v0.0.0-20200521101457-60c476765272 github.com/openshift/build-machinery-go v0.0.0-20200424080330-082bf86082cc github.com/openshift/library-go v0.0.0-20200617154932-eaf8c138def4 diff --git a/go.sum b/go.sum index f49a501db..e6162a2bc 100644 --- a/go.sum +++ b/go.sum @@ -310,8 +310,8 @@ 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-20200715201722-3c3c076bf062 h1:sYKu/XTeGrYCjO7x6/r6CfM/R8/Lr2kX7IG1DOC+wW0= -github.com/open-cluster-management/api v0.0.0-20200715201722-3c3c076bf062/go.mod h1:+vUECYB7WkfCb52r0J7rxgD1mseSGAqGi8rTLLRcbgw= +github.com/open-cluster-management/api v0.0.0-20200806152638-5caae08712f5 h1:N9FdbViKsIDcd6Ak4LOlk3U1d7RQDA6imBeMzilUN4E= +github.com/open-cluster-management/api v0.0.0-20200806152638-5caae08712f5/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= diff --git a/manifests/cluster-manager/cluster-manager-namespace.yaml b/manifests/cluster-manager/cluster-manager-namespace.yaml index 4dfe3be65..d52206eab 100644 --- a/manifests/cluster-manager/cluster-manager-namespace.yaml +++ b/manifests/cluster-manager/cluster-manager-namespace.yaml @@ -1,4 +1,4 @@ apiVersion: v1 kind: Namespace metadata: - name: {{ .ClusterManagerNamespace }} + name: open-cluster-management-hub diff --git a/manifests/cluster-manager/cluster-manager-registration-clusterrolebinding.yaml b/manifests/cluster-manager/cluster-manager-registration-clusterrolebinding.yaml index 3d06e737e..5ac11dd51 100644 --- a/manifests/cluster-manager/cluster-manager-registration-clusterrolebinding.yaml +++ b/manifests/cluster-manager/cluster-manager-registration-clusterrolebinding.yaml @@ -8,5 +8,5 @@ roleRef: name: open-cluster-management:{{ .ClusterManagerName }}-registration:controller subjects: - kind: ServiceAccount - namespace: {{ .ClusterManagerNamespace }} + namespace: open-cluster-management-hub name: {{ .ClusterManagerName }}-registration-controller-sa diff --git a/manifests/cluster-manager/cluster-manager-registration-deployment.yaml b/manifests/cluster-manager/cluster-manager-registration-deployment.yaml index 215864a10..fb95178cb 100644 --- a/manifests/cluster-manager/cluster-manager-registration-deployment.yaml +++ b/manifests/cluster-manager/cluster-manager-registration-deployment.yaml @@ -2,7 +2,7 @@ kind: Deployment apiVersion: apps/v1 metadata: name: {{ .ClusterManagerName }}-registration-controller - namespace: {{ .ClusterManagerNamespace }} + namespace: open-cluster-management-hub labels: app: clustermanager-controller spec: diff --git a/manifests/cluster-manager/cluster-manager-registration-serviceaccount.yaml b/manifests/cluster-manager/cluster-manager-registration-serviceaccount.yaml index ac1ae4042..3ba5dc721 100644 --- a/manifests/cluster-manager/cluster-manager-registration-serviceaccount.yaml +++ b/manifests/cluster-manager/cluster-manager-registration-serviceaccount.yaml @@ -2,4 +2,4 @@ apiVersion: v1 kind: ServiceAccount metadata: name: {{ .ClusterManagerName }}-registration-controller-sa - namespace: {{ .ClusterManagerNamespace }} + namespace: open-cluster-management-hub diff --git a/manifests/cluster-manager/cluster-manager-registration-webhook-apiservice.yaml b/manifests/cluster-manager/cluster-manager-registration-webhook-apiservice.yaml index 5b2a4d6ba..46b5a6727 100644 --- a/manifests/cluster-manager/cluster-manager-registration-webhook-apiservice.yaml +++ b/manifests/cluster-manager/cluster-manager-registration-webhook-apiservice.yaml @@ -6,8 +6,8 @@ spec: group: admission.cluster.open-cluster-management.io version: v1 service: - name: {{ .ClusterManagerWebhookRegistrationService }} - namespace: {{ .ClusterManagerNamespace }} + name: cluster-manager-registration-webhook + namespace: open-cluster-management-hub caBundle: {{ .RegistrationAPIServiceCABundle }} groupPriorityMinimum: 10000 versionPriority: 20 diff --git a/manifests/cluster-manager/cluster-manager-registration-webhook-clusterrolebinding.yaml b/manifests/cluster-manager/cluster-manager-registration-webhook-clusterrolebinding.yaml index 8377e39f5..881c95c6c 100644 --- a/manifests/cluster-manager/cluster-manager-registration-webhook-clusterrolebinding.yaml +++ b/manifests/cluster-manager/cluster-manager-registration-webhook-clusterrolebinding.yaml @@ -9,4 +9,4 @@ roleRef: subjects: - kind: ServiceAccount name: {{ .ClusterManagerName }}-registration-webhook-sa - namespace: {{ .ClusterManagerNamespace }} + namespace: open-cluster-management-hub diff --git a/manifests/cluster-manager/cluster-manager-registration-webhook-deployment.yaml b/manifests/cluster-manager/cluster-manager-registration-webhook-deployment.yaml index f1da6b159..088559b79 100644 --- a/manifests/cluster-manager/cluster-manager-registration-webhook-deployment.yaml +++ b/manifests/cluster-manager/cluster-manager-registration-webhook-deployment.yaml @@ -2,7 +2,7 @@ apiVersion: apps/v1 kind: Deployment metadata: name: {{ .ClusterManagerName }}-registration-webhook - namespace: {{ .ClusterManagerNamespace }} + namespace: open-cluster-management-hub labels: app: {{ .ClusterManagerName }}-registration-webhook spec: @@ -71,5 +71,5 @@ spec: volumes: - name: webhook-secret secret: - secretName: {{ .ClusterManagerWebhookSecret }} + secretName: registration-webhook-serving-cert diff --git a/manifests/cluster-manager/cluster-manager-registration-webhook-secret.yaml b/manifests/cluster-manager/cluster-manager-registration-webhook-secret.yaml index 2220433fd..5e1a3d1e7 100644 --- a/manifests/cluster-manager/cluster-manager-registration-webhook-secret.yaml +++ b/manifests/cluster-manager/cluster-manager-registration-webhook-secret.yaml @@ -1,8 +1,8 @@ apiVersion: v1 kind: Secret metadata: - name: {{ .ClusterManagerWebhookSecret }} - namespace: {{ .ClusterManagerNamespace }} + name: registration-webhook-serving-cert + namespace: open-cluster-management-hub data: tls.crt: {{ .RegistrationServingCert }} tls.key: {{ .RegistrationServingKey }} diff --git a/manifests/cluster-manager/cluster-manager-registration-webhook-service.yaml b/manifests/cluster-manager/cluster-manager-registration-webhook-service.yaml index ff7dc0c3f..19727b6ae 100644 --- a/manifests/cluster-manager/cluster-manager-registration-webhook-service.yaml +++ b/manifests/cluster-manager/cluster-manager-registration-webhook-service.yaml @@ -1,8 +1,8 @@ apiVersion: v1 kind: Service metadata: - name: {{ .ClusterManagerWebhookRegistrationService }} - namespace: {{ .ClusterManagerNamespace }} + name: cluster-manager-registration-webhook + namespace: open-cluster-management-hub spec: selector: app: {{ .ClusterManagerName }}-registration-webhook diff --git a/manifests/cluster-manager/cluster-manager-registration-webhook-serviceaccount.yaml b/manifests/cluster-manager/cluster-manager-registration-webhook-serviceaccount.yaml index 780c8e828..8f1074fd9 100644 --- a/manifests/cluster-manager/cluster-manager-registration-webhook-serviceaccount.yaml +++ b/manifests/cluster-manager/cluster-manager-registration-webhook-serviceaccount.yaml @@ -2,4 +2,4 @@ apiVersion: v1 kind: ServiceAccount metadata: name: {{ .ClusterManagerName }}-registration-webhook-sa - namespace: {{ .ClusterManagerNamespace }} + namespace: open-cluster-management-hub diff --git a/manifests/cluster-manager/cluster-manager-work-webhook-apiservice.yaml b/manifests/cluster-manager/cluster-manager-work-webhook-apiservice.yaml new file mode 100644 index 000000000..70c02a82c --- /dev/null +++ b/manifests/cluster-manager/cluster-manager-work-webhook-apiservice.yaml @@ -0,0 +1,13 @@ +apiVersion: apiregistration.k8s.io/v1 +kind: APIService +metadata: + name: v1.admission.work.open-cluster-management.io +spec: + group: admission.work.open-cluster-management.io + version: v1 + service: + name: cluster-manager-work-webhook + namespace: open-cluster-management-hub + caBundle: {{ .WorkAPIServiceCABundle }} + groupPriorityMinimum: 10000 + versionPriority: 20 diff --git a/manifests/cluster-manager/cluster-manager-work-webhook-clusterrole.yaml b/manifests/cluster-manager/cluster-manager-work-webhook-clusterrole.yaml new file mode 100644 index 000000000..fdd9c3414 --- /dev/null +++ b/manifests/cluster-manager/cluster-manager-work-webhook-clusterrole.yaml @@ -0,0 +1,13 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: open-cluster-management:{{ .ClusterManagerName }}-work:webhook +rules: +# Allow managedcluster admission to get/list/watch configmaps +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "list", "watch"] +# Allow managedcluster admission to create subjectaccessreviews +- apiGroups: ["authorization.k8s.io"] + resources: ["subjectaccessreviews"] + verbs: ["create"] diff --git a/manifests/cluster-manager/cluster-manager-work-webhook-clusterrolebinding.yaml b/manifests/cluster-manager/cluster-manager-work-webhook-clusterrolebinding.yaml new file mode 100644 index 000000000..03d2d1235 --- /dev/null +++ b/manifests/cluster-manager/cluster-manager-work-webhook-clusterrolebinding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: open-cluster-management:{{ .ClusterManagerName }}-work:webhook +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: open-cluster-management:{{ .ClusterManagerName }}-work:webhook +subjects: + - kind: ServiceAccount + name: {{ .ClusterManagerName }}-work-webhook-sa + namespace: open-cluster-management-hub diff --git a/manifests/cluster-manager/cluster-manager-work-webhook-deployment.yaml b/manifests/cluster-manager/cluster-manager-work-webhook-deployment.yaml new file mode 100644 index 000000000..c915b76f4 --- /dev/null +++ b/manifests/cluster-manager/cluster-manager-work-webhook-deployment.yaml @@ -0,0 +1,75 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .ClusterManagerName }}-work-webhook + namespace: open-cluster-management-hub + labels: + app: {{ .ClusterManagerName }}-work-webhook +spec: + replicas: 3 + selector: + matchLabels: + app: {{ .ClusterManagerName }}-work-webhook + template: + metadata: + labels: + app: {{ .ClusterManagerName }}-work-webhook + spec: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 70 + podAffinityTerm: + topologyKey: failure-domain.beta.kubernetes.io/zone + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - {{ .ClusterManagerName }}-work-webhook + - weight: 30 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - {{ .ClusterManagerName }}-work-webhook + serviceAccountName: {{ .ClusterManagerName }}-work-webhook-sa + containers: + - name: {{ .ClusterManagerName }}-work-webhook-sa + image: {{ .WorkImage }} + imagePullPolicy: IfNotPresent + args: + - "/work" + - "webhook" + - "--secure-port=6443" + - "--tls-cert-file=/serving-cert/tls.crt" + - "--tls-private-key-file=/serving-cert/tls.key" + livenessProbe: + httpGet: + path: /healthz + scheme: HTTPS + port: 6443 + initialDelaySeconds: 2 + periodSeconds: 10 + readinessProbe: + httpGet: + path: /healthz + scheme: HTTPS + port: 6443 + initialDelaySeconds: 2 + resources: + requests: + cpu: 100m + memory: 128Mi + volumeMounts: + - name: webhook-secret + mountPath: "/serving-cert" + readOnly: true + volumes: + - name: webhook-secret + secret: + secretName: work-webhook-serving-cert + diff --git a/manifests/cluster-manager/cluster-manager-work-webhook-secret.yaml b/manifests/cluster-manager/cluster-manager-work-webhook-secret.yaml new file mode 100644 index 000000000..bc2a89715 --- /dev/null +++ b/manifests/cluster-manager/cluster-manager-work-webhook-secret.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Secret +metadata: + name: work-webhook-serving-cert + namespace: open-cluster-management-hub +data: + tls.crt: {{ .WorkServingCert }} + tls.key: {{ .WorkServingKey }} + ca.crt: {{ .WorkAPIServiceCABundle }} +type: Opaque diff --git a/manifests/cluster-manager/cluster-manager-work-webhook-service.yaml b/manifests/cluster-manager/cluster-manager-work-webhook-service.yaml new file mode 100644 index 000000000..41a2ce6a4 --- /dev/null +++ b/manifests/cluster-manager/cluster-manager-work-webhook-service.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Service +metadata: + name: cluster-manager-work-webhook + namespace: open-cluster-management-hub +spec: + selector: + app: {{ .ClusterManagerName }}-work-webhook + ports: + - port: 443 + targetPort: 6443 diff --git a/manifests/cluster-manager/cluster-manager-work-webhook-serviceaccount.yaml b/manifests/cluster-manager/cluster-manager-work-webhook-serviceaccount.yaml new file mode 100644 index 000000000..1151685be --- /dev/null +++ b/manifests/cluster-manager/cluster-manager-work-webhook-serviceaccount.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .ClusterManagerName }}-work-webhook-sa + namespace: open-cluster-management-hub diff --git a/manifests/cluster-manager/cluster-manager-work-webhook-validatingconfiguration.yaml b/manifests/cluster-manager/cluster-manager-work-webhook-validatingconfiguration.yaml new file mode 100644 index 000000000..9b6ee39fe --- /dev/null +++ b/manifests/cluster-manager/cluster-manager-work-webhook-validatingconfiguration.yaml @@ -0,0 +1,26 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: manifestworkvalidators.admission.work.open-cluster-management.io +webhooks: +- name: manifestworkvalidators.admission.work.open-cluster-management.io + failurePolicy: Fail + clientConfig: + service: + # reach the webhook via the registered aggregated API + namespace: default + name: kubernetes + path: /apis/admission.work.open-cluster-management.io/v1/manifestworkvalidators + rules: + - operations: + - CREATE + - UPDATE + apiGroups: + - work.open-cluster-management.io + apiVersions: + - "*" + resources: + - manifestworks + admissionReviewVersions: ["v1beta1"] + sideEffects: None + timeoutSeconds: 3 diff --git a/pkg/operators/clustermanager/bindata/bindata.go b/pkg/operators/clustermanager/bindata/bindata.go index 194a1ae89..3ae490acb 100644 --- a/pkg/operators/clustermanager/bindata/bindata.go +++ b/pkg/operators/clustermanager/bindata/bindata.go @@ -16,6 +16,14 @@ // 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 +// manifests/cluster-manager/cluster-manager-work-webhook-apiservice.yaml +// manifests/cluster-manager/cluster-manager-work-webhook-clusterrole.yaml +// manifests/cluster-manager/cluster-manager-work-webhook-clusterrolebinding.yaml +// manifests/cluster-manager/cluster-manager-work-webhook-deployment.yaml +// manifests/cluster-manager/cluster-manager-work-webhook-secret.yaml +// manifests/cluster-manager/cluster-manager-work-webhook-service.yaml +// manifests/cluster-manager/cluster-manager-work-webhook-serviceaccount.yaml +// manifests/cluster-manager/cluster-manager-work-webhook-validatingconfiguration.yaml package bindata import ( @@ -456,7 +464,7 @@ func manifestsClusterManager0000_00_workOpenClusterManagementIo_manifestworksCrd var _manifestsClusterManagerClusterManagerNamespaceYaml = []byte(`apiVersion: v1 kind: Namespace metadata: - name: {{ .ClusterManagerNamespace }} + name: open-cluster-management-hub `) func manifestsClusterManagerClusterManagerNamespaceYamlBytes() ([]byte, error) { @@ -550,7 +558,7 @@ roleRef: name: open-cluster-management:{{ .ClusterManagerName }}-registration:controller subjects: - kind: ServiceAccount - namespace: {{ .ClusterManagerNamespace }} + namespace: open-cluster-management-hub name: {{ .ClusterManagerName }}-registration-controller-sa `) @@ -573,7 +581,7 @@ var _manifestsClusterManagerClusterManagerRegistrationDeploymentYaml = []byte(`k apiVersion: apps/v1 metadata: name: {{ .ClusterManagerName }}-registration-controller - namespace: {{ .ClusterManagerNamespace }} + namespace: open-cluster-management-hub labels: app: clustermanager-controller spec: @@ -653,7 +661,7 @@ var _manifestsClusterManagerClusterManagerRegistrationServiceaccountYaml = []byt kind: ServiceAccount metadata: name: {{ .ClusterManagerName }}-registration-controller-sa - namespace: {{ .ClusterManagerNamespace }} + namespace: open-cluster-management-hub `) func manifestsClusterManagerClusterManagerRegistrationServiceaccountYamlBytes() ([]byte, error) { @@ -679,8 +687,8 @@ spec: group: admission.cluster.open-cluster-management.io version: v1 service: - name: {{ .ClusterManagerWebhookRegistrationService }} - namespace: {{ .ClusterManagerNamespace }} + name: cluster-manager-registration-webhook + namespace: open-cluster-management-hub caBundle: {{ .RegistrationAPIServiceCABundle }} groupPriorityMinimum: 10000 versionPriority: 20 @@ -742,7 +750,7 @@ roleRef: subjects: - kind: ServiceAccount name: {{ .ClusterManagerName }}-registration-webhook-sa - namespace: {{ .ClusterManagerNamespace }} + namespace: open-cluster-management-hub `) func manifestsClusterManagerClusterManagerRegistrationWebhookClusterrolebindingYamlBytes() ([]byte, error) { @@ -764,7 +772,7 @@ var _manifestsClusterManagerClusterManagerRegistrationWebhookDeploymentYaml = [] kind: Deployment metadata: name: {{ .ClusterManagerName }}-registration-webhook - namespace: {{ .ClusterManagerNamespace }} + namespace: open-cluster-management-hub labels: app: {{ .ClusterManagerName }}-registration-webhook spec: @@ -833,7 +841,7 @@ spec: volumes: - name: webhook-secret secret: - secretName: {{ .ClusterManagerWebhookSecret }} + secretName: registration-webhook-serving-cert `) @@ -898,8 +906,8 @@ func manifestsClusterManagerClusterManagerRegistrationWebhookMutatingconfigurati var _manifestsClusterManagerClusterManagerRegistrationWebhookSecretYaml = []byte(`apiVersion: v1 kind: Secret metadata: - name: {{ .ClusterManagerWebhookSecret }} - namespace: {{ .ClusterManagerNamespace }} + name: registration-webhook-serving-cert + namespace: open-cluster-management-hub data: tls.crt: {{ .RegistrationServingCert }} tls.key: {{ .RegistrationServingKey }} @@ -925,8 +933,8 @@ func manifestsClusterManagerClusterManagerRegistrationWebhookSecretYaml() (*asse var _manifestsClusterManagerClusterManagerRegistrationWebhookServiceYaml = []byte(`apiVersion: v1 kind: Service metadata: - name: {{ .ClusterManagerWebhookRegistrationService }} - namespace: {{ .ClusterManagerNamespace }} + name: cluster-manager-registration-webhook + namespace: open-cluster-management-hub spec: selector: app: {{ .ClusterManagerName }}-registration-webhook @@ -954,7 +962,7 @@ var _manifestsClusterManagerClusterManagerRegistrationWebhookServiceaccountYaml kind: ServiceAccount metadata: name: {{ .ClusterManagerName }}-registration-webhook-sa - namespace: {{ .ClusterManagerNamespace }} + namespace: open-cluster-management-hub `) func manifestsClusterManagerClusterManagerRegistrationWebhookServiceaccountYamlBytes() ([]byte, error) { @@ -1015,6 +1023,307 @@ func manifestsClusterManagerClusterManagerRegistrationWebhookValidatingconfigura return a, nil } +var _manifestsClusterManagerClusterManagerWorkWebhookApiserviceYaml = []byte(`apiVersion: apiregistration.k8s.io/v1 +kind: APIService +metadata: + name: v1.admission.work.open-cluster-management.io +spec: + group: admission.work.open-cluster-management.io + version: v1 + service: + name: cluster-manager-work-webhook + namespace: open-cluster-management-hub + caBundle: {{ .WorkAPIServiceCABundle }} + groupPriorityMinimum: 10000 + versionPriority: 20 +`) + +func manifestsClusterManagerClusterManagerWorkWebhookApiserviceYamlBytes() ([]byte, error) { + return _manifestsClusterManagerClusterManagerWorkWebhookApiserviceYaml, nil +} + +func manifestsClusterManagerClusterManagerWorkWebhookApiserviceYaml() (*asset, error) { + bytes, err := manifestsClusterManagerClusterManagerWorkWebhookApiserviceYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "manifests/cluster-manager/cluster-manager-work-webhook-apiservice.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _manifestsClusterManagerClusterManagerWorkWebhookClusterroleYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: open-cluster-management:{{ .ClusterManagerName }}-work:webhook +rules: +# Allow managedcluster admission to get/list/watch configmaps +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "list", "watch"] +# Allow managedcluster admission to create subjectaccessreviews +- apiGroups: ["authorization.k8s.io"] + resources: ["subjectaccessreviews"] + verbs: ["create"] +`) + +func manifestsClusterManagerClusterManagerWorkWebhookClusterroleYamlBytes() ([]byte, error) { + return _manifestsClusterManagerClusterManagerWorkWebhookClusterroleYaml, nil +} + +func manifestsClusterManagerClusterManagerWorkWebhookClusterroleYaml() (*asset, error) { + bytes, err := manifestsClusterManagerClusterManagerWorkWebhookClusterroleYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "manifests/cluster-manager/cluster-manager-work-webhook-clusterrole.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _manifestsClusterManagerClusterManagerWorkWebhookClusterrolebindingYaml = []byte(`apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: open-cluster-management:{{ .ClusterManagerName }}-work:webhook +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: open-cluster-management:{{ .ClusterManagerName }}-work:webhook +subjects: + - kind: ServiceAccount + name: {{ .ClusterManagerName }}-work-webhook-sa + namespace: open-cluster-management-hub +`) + +func manifestsClusterManagerClusterManagerWorkWebhookClusterrolebindingYamlBytes() ([]byte, error) { + return _manifestsClusterManagerClusterManagerWorkWebhookClusterrolebindingYaml, nil +} + +func manifestsClusterManagerClusterManagerWorkWebhookClusterrolebindingYaml() (*asset, error) { + bytes, err := manifestsClusterManagerClusterManagerWorkWebhookClusterrolebindingYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "manifests/cluster-manager/cluster-manager-work-webhook-clusterrolebinding.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _manifestsClusterManagerClusterManagerWorkWebhookDeploymentYaml = []byte(`apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .ClusterManagerName }}-work-webhook + namespace: open-cluster-management-hub + labels: + app: {{ .ClusterManagerName }}-work-webhook +spec: + replicas: 3 + selector: + matchLabels: + app: {{ .ClusterManagerName }}-work-webhook + template: + metadata: + labels: + app: {{ .ClusterManagerName }}-work-webhook + spec: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 70 + podAffinityTerm: + topologyKey: failure-domain.beta.kubernetes.io/zone + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - {{ .ClusterManagerName }}-work-webhook + - weight: 30 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - {{ .ClusterManagerName }}-work-webhook + serviceAccountName: {{ .ClusterManagerName }}-work-webhook-sa + containers: + - name: {{ .ClusterManagerName }}-work-webhook-sa + image: {{ .WorkImage }} + imagePullPolicy: IfNotPresent + args: + - "/work" + - "webhook" + - "--secure-port=6443" + - "--tls-cert-file=/serving-cert/tls.crt" + - "--tls-private-key-file=/serving-cert/tls.key" + livenessProbe: + httpGet: + path: /healthz + scheme: HTTPS + port: 6443 + initialDelaySeconds: 2 + periodSeconds: 10 + readinessProbe: + httpGet: + path: /healthz + scheme: HTTPS + port: 6443 + initialDelaySeconds: 2 + resources: + requests: + cpu: 100m + memory: 128Mi + volumeMounts: + - name: webhook-secret + mountPath: "/serving-cert" + readOnly: true + volumes: + - name: webhook-secret + secret: + secretName: work-webhook-serving-cert + +`) + +func manifestsClusterManagerClusterManagerWorkWebhookDeploymentYamlBytes() ([]byte, error) { + return _manifestsClusterManagerClusterManagerWorkWebhookDeploymentYaml, nil +} + +func manifestsClusterManagerClusterManagerWorkWebhookDeploymentYaml() (*asset, error) { + bytes, err := manifestsClusterManagerClusterManagerWorkWebhookDeploymentYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "manifests/cluster-manager/cluster-manager-work-webhook-deployment.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _manifestsClusterManagerClusterManagerWorkWebhookSecretYaml = []byte(`apiVersion: v1 +kind: Secret +metadata: + name: work-webhook-serving-cert + namespace: open-cluster-management-hub +data: + tls.crt: {{ .WorkServingCert }} + tls.key: {{ .WorkServingKey }} + ca.crt: {{ .WorkAPIServiceCABundle }} +type: Opaque +`) + +func manifestsClusterManagerClusterManagerWorkWebhookSecretYamlBytes() ([]byte, error) { + return _manifestsClusterManagerClusterManagerWorkWebhookSecretYaml, nil +} + +func manifestsClusterManagerClusterManagerWorkWebhookSecretYaml() (*asset, error) { + bytes, err := manifestsClusterManagerClusterManagerWorkWebhookSecretYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "manifests/cluster-manager/cluster-manager-work-webhook-secret.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _manifestsClusterManagerClusterManagerWorkWebhookServiceYaml = []byte(`apiVersion: v1 +kind: Service +metadata: + name: cluster-manager-work-webhook + namespace: open-cluster-management-hub +spec: + selector: + app: {{ .ClusterManagerName }}-work-webhook + ports: + - port: 443 + targetPort: 6443 +`) + +func manifestsClusterManagerClusterManagerWorkWebhookServiceYamlBytes() ([]byte, error) { + return _manifestsClusterManagerClusterManagerWorkWebhookServiceYaml, nil +} + +func manifestsClusterManagerClusterManagerWorkWebhookServiceYaml() (*asset, error) { + bytes, err := manifestsClusterManagerClusterManagerWorkWebhookServiceYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "manifests/cluster-manager/cluster-manager-work-webhook-service.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _manifestsClusterManagerClusterManagerWorkWebhookServiceaccountYaml = []byte(`apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .ClusterManagerName }}-work-webhook-sa + namespace: open-cluster-management-hub +`) + +func manifestsClusterManagerClusterManagerWorkWebhookServiceaccountYamlBytes() ([]byte, error) { + return _manifestsClusterManagerClusterManagerWorkWebhookServiceaccountYaml, nil +} + +func manifestsClusterManagerClusterManagerWorkWebhookServiceaccountYaml() (*asset, error) { + bytes, err := manifestsClusterManagerClusterManagerWorkWebhookServiceaccountYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "manifests/cluster-manager/cluster-manager-work-webhook-serviceaccount.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _manifestsClusterManagerClusterManagerWorkWebhookValidatingconfigurationYaml = []byte(`apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: manifestworkvalidators.admission.work.open-cluster-management.io +webhooks: +- name: manifestworkvalidators.admission.work.open-cluster-management.io + failurePolicy: Fail + clientConfig: + service: + # reach the webhook via the registered aggregated API + namespace: default + name: kubernetes + path: /apis/admission.work.open-cluster-management.io/v1/manifestworkvalidators + rules: + - operations: + - CREATE + - UPDATE + apiGroups: + - work.open-cluster-management.io + apiVersions: + - "*" + resources: + - manifestworks + admissionReviewVersions: ["v1beta1"] + sideEffects: None + timeoutSeconds: 3 +`) + +func manifestsClusterManagerClusterManagerWorkWebhookValidatingconfigurationYamlBytes() ([]byte, error) { + return _manifestsClusterManagerClusterManagerWorkWebhookValidatingconfigurationYaml, nil +} + +func manifestsClusterManagerClusterManagerWorkWebhookValidatingconfigurationYaml() (*asset, error) { + bytes, err := manifestsClusterManagerClusterManagerWorkWebhookValidatingconfigurationYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "manifests/cluster-manager/cluster-manager-work-webhook-validatingconfiguration.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. @@ -1083,6 +1392,14 @@ var _bindata = map[string]func() (*asset, error){ "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, + "manifests/cluster-manager/cluster-manager-work-webhook-apiservice.yaml": manifestsClusterManagerClusterManagerWorkWebhookApiserviceYaml, + "manifests/cluster-manager/cluster-manager-work-webhook-clusterrole.yaml": manifestsClusterManagerClusterManagerWorkWebhookClusterroleYaml, + "manifests/cluster-manager/cluster-manager-work-webhook-clusterrolebinding.yaml": manifestsClusterManagerClusterManagerWorkWebhookClusterrolebindingYaml, + "manifests/cluster-manager/cluster-manager-work-webhook-deployment.yaml": manifestsClusterManagerClusterManagerWorkWebhookDeploymentYaml, + "manifests/cluster-manager/cluster-manager-work-webhook-secret.yaml": manifestsClusterManagerClusterManagerWorkWebhookSecretYaml, + "manifests/cluster-manager/cluster-manager-work-webhook-service.yaml": manifestsClusterManagerClusterManagerWorkWebhookServiceYaml, + "manifests/cluster-manager/cluster-manager-work-webhook-serviceaccount.yaml": manifestsClusterManagerClusterManagerWorkWebhookServiceaccountYaml, + "manifests/cluster-manager/cluster-manager-work-webhook-validatingconfiguration.yaml": manifestsClusterManagerClusterManagerWorkWebhookValidatingconfigurationYaml, } // AssetDir returns the file names below a certain @@ -1144,6 +1461,14 @@ var _bintree = &bintree{nil, 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{}}, + "cluster-manager-work-webhook-apiservice.yaml": {manifestsClusterManagerClusterManagerWorkWebhookApiserviceYaml, map[string]*bintree{}}, + "cluster-manager-work-webhook-clusterrole.yaml": {manifestsClusterManagerClusterManagerWorkWebhookClusterroleYaml, map[string]*bintree{}}, + "cluster-manager-work-webhook-clusterrolebinding.yaml": {manifestsClusterManagerClusterManagerWorkWebhookClusterrolebindingYaml, map[string]*bintree{}}, + "cluster-manager-work-webhook-deployment.yaml": {manifestsClusterManagerClusterManagerWorkWebhookDeploymentYaml, map[string]*bintree{}}, + "cluster-manager-work-webhook-secret.yaml": {manifestsClusterManagerClusterManagerWorkWebhookSecretYaml, map[string]*bintree{}}, + "cluster-manager-work-webhook-service.yaml": {manifestsClusterManagerClusterManagerWorkWebhookServiceYaml, map[string]*bintree{}}, + "cluster-manager-work-webhook-serviceaccount.yaml": {manifestsClusterManagerClusterManagerWorkWebhookServiceaccountYaml, map[string]*bintree{}}, + "cluster-manager-work-webhook-validatingconfiguration.yaml": {manifestsClusterManagerClusterManagerWorkWebhookValidatingconfigurationYaml, map[string]*bintree{}}, }}, }}, }} diff --git a/pkg/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_controller.go b/pkg/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_controller.go index 87e583616..2d1ef7a9d 100644 --- a/pkg/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_controller.go +++ b/pkg/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_controller.go @@ -52,19 +52,30 @@ var ( "manifests/cluster-manager/cluster-manager-registration-webhook-secret.yaml", "manifests/cluster-manager/cluster-manager-registration-webhook-validatingconfiguration.yaml", "manifests/cluster-manager/cluster-manager-registration-webhook-mutatingconfiguration.yaml", + "manifests/cluster-manager/cluster-manager-work-webhook-clusterrole.yaml", + "manifests/cluster-manager/cluster-manager-work-webhook-clusterrolebinding.yaml", + "manifests/cluster-manager/cluster-manager-work-webhook-service.yaml", + "manifests/cluster-manager/cluster-manager-work-webhook-serviceaccount.yaml", + "manifests/cluster-manager/cluster-manager-work-webhook-apiservice.yaml", + "manifests/cluster-manager/cluster-manager-work-webhook-secret.yaml", + "manifests/cluster-manager/cluster-manager-work-webhook-validatingconfiguration.yaml", } deploymentFiles = []string{ "manifests/cluster-manager/cluster-manager-registration-deployment.yaml", "manifests/cluster-manager/cluster-manager-registration-webhook-deployment.yaml", + "manifests/cluster-manager/cluster-manager-work-webhook-deployment.yaml", } ) const ( - clusterManagerFinalizer = "operator.open-cluster-management.io/cluster-manager-cleanup" - clusterManagerWebhookSecret = "webhook-serving-cert" - clusterManagerApplied = "Applied" - clusterManagerAvailable = "Available" + clusterManagerFinalizer = "operator.open-cluster-management.io/cluster-manager-cleanup" + registrationWebhookSecret = "registration-webhook-serving-cert" + registrationWebhookService = "cluster-manager-registration-webhook" + workWebhookSecret = "work-webhook-serving-cert" + workWebhookService = "cluster-manager-work-webhook" + clusterManagerApplied = "Applied" + clusterManagerAvailable = "Available" ) type clusterManagerController struct { @@ -106,14 +117,15 @@ func NewClusterManagerController( // hubConfig is used to render the template of hub manifests type hubConfig struct { - ClusterManagerName string - ClusterManagerNamespace string - RegistrationImage string - ClusterManagerWebhookSecret string - ClusterManagerWebhookRegistrationService string - RegistrationAPIServiceCABundle string - RegistrationServingCert string - RegistrationServingKey string + ClusterManagerName string + RegistrationImage string + RegistrationAPIServiceCABundle string + RegistrationServingCert string + RegistrationServingKey string + WorkImage string + WorkAPIServiceCABundle string + WorkServingCert string + WorkServingKey string } func (n *clusterManagerController) sync(ctx context.Context, controllerContext factory.SyncContext) error { @@ -131,11 +143,9 @@ func (n *clusterManagerController) sync(ctx context.Context, controllerContext f clusterManager = clusterManager.DeepCopy() config := hubConfig{ - ClusterManagerName: clusterManager.Name, - ClusterManagerNamespace: helpers.ClusterManagerNamespace, - RegistrationImage: clusterManager.Spec.RegistrationImagePullSpec, - ClusterManagerWebhookSecret: clusterManagerWebhookSecret, - ClusterManagerWebhookRegistrationService: fmt.Sprintf("%s-registration-webhook", clusterManager.Name), + ClusterManagerName: clusterManager.Name, + RegistrationImage: clusterManager.Spec.RegistrationImagePullSpec, + WorkImage: clusterManager.Spec.WorkImagePullSpec, } // Update finalizer at first @@ -162,8 +172,9 @@ func (n *clusterManagerController) sync(ctx context.Context, controllerContext f return n.removeClusterManagerFinalizer(ctx, clusterManager) } + // Ensure serving cert for webhooks ca, cert, key, err := n.ensureServingCertAndCA( - ctx, config.ClusterManagerNamespace, config.ClusterManagerWebhookSecret, config.ClusterManagerWebhookRegistrationService) + ctx, helpers.ClusterManagerNamespace, registrationWebhookSecret, registrationWebhookService) if err != nil { return err } @@ -171,6 +182,15 @@ func (n *clusterManagerController) sync(ctx context.Context, controllerContext f config.RegistrationServingCert = base64.StdEncoding.EncodeToString(cert) config.RegistrationServingKey = base64.StdEncoding.EncodeToString(key) + ca, cert, key, err = n.ensureServingCertAndCA( + ctx, helpers.ClusterManagerNamespace, workWebhookSecret, workWebhookService) + if err != nil { + return err + } + config.WorkAPIServiceCABundle = base64.StdEncoding.EncodeToString(ca) + config.WorkServingCert = base64.StdEncoding.EncodeToString(cert) + config.WorkServingKey = base64.StdEncoding.EncodeToString(key) + // Apply static files resourceResults := helpers.ApplyDirectly( n.kubeClient, diff --git a/pkg/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_controller_test.go b/pkg/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_controller_test.go index cce359099..021075716 100644 --- a/pkg/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_controller_test.go +++ b/pkg/operators/clustermanager/controllers/clustermanagercontroller/clustermanager_controller_test.go @@ -3,6 +3,7 @@ package clustermanagercontroller import ( "context" "reflect" + "strings" "testing" "time" @@ -96,7 +97,7 @@ func ensureObject(t *testing.T, object runtime.Object, hubCore *operatorapiv1.Cl case *corev1.Namespace: testinghelper.AssertEqualNameNamespace(t, access.GetName(), "", helpers.ClusterManagerNamespace, "") case *appsv1.Deployment: - if hubCore.Spec.RegistrationImagePullSpec != o.Spec.Template.Spec.Containers[0].Image { + if strings.Contains(o.Name, "registration") && hubCore.Spec.RegistrationImagePullSpec != o.Spec.Template.Spec.Containers[0].Image { t.Errorf("Image does not match to the expected.") } } @@ -123,7 +124,7 @@ func TestSyncDeploy(t *testing.T) { } // Check if resources are created as expected - testinghelper.AssertEqualNumber(t, len(createKubeObjects), 13) + testinghelper.AssertEqualNumber(t, len(createKubeObjects), 20) for _, object := range createKubeObjects { ensureObject(t, object, clusterManager) } @@ -148,7 +149,7 @@ func TestSyncDeploy(t *testing.T) { } } // Check if resources are created as expected - testinghelper.AssertEqualNumber(t, len(createAPIServiceObjects), 1) + testinghelper.AssertEqualNumber(t, len(createAPIServiceObjects), 2) clusterManagerAction := controller.operatorClient.Actions() testinghelper.AssertEqualNumber(t, len(clusterManagerAction), 2) @@ -179,7 +180,7 @@ func TestSyncDelete(t *testing.T) { deleteKubeActions = append(deleteKubeActions, deleteKubeAction) } } - testinghelper.AssertEqualNumber(t, len(deleteKubeActions), 11) + testinghelper.AssertEqualNumber(t, len(deleteKubeActions), 17) deleteCRDActions := []clienttesting.DeleteActionImpl{} crdActions := controller.apiExtensionClient.Actions() @@ -201,7 +202,7 @@ func TestSyncDelete(t *testing.T) { } } // Check if resources are created as expected - testinghelper.AssertEqualNumber(t, len(deleteAPIServiceActions), 1) + testinghelper.AssertEqualNumber(t, len(deleteAPIServiceActions), 2) for _, action := range deleteKubeActions { switch action.Resource.Resource { diff --git a/test/e2e/common.go b/test/e2e/common.go index 0ee81a5fe..f07223680 100644 --- a/test/e2e/common.go +++ b/test/e2e/common.go @@ -30,20 +30,21 @@ import ( ) type Tester struct { - KubeClient kubernetes.Interface - ClusterCfg *rest.Config - OperatorClient operatorclient.Interface - ClusterClient clusterclient.Interface - WorkClient workv1client.Interface - bootstrapHubSecret *corev1.Secret - EventuallyTimeout time.Duration - EventuallyInterval time.Duration - clusterManagerNamespace string - klusterletDefaultNamespace string - hubRegistrationDeployment string - hubWebhookDeployment string - operatorNamespace string - klusterletOperator string + KubeClient kubernetes.Interface + ClusterCfg *rest.Config + OperatorClient operatorclient.Interface + ClusterClient clusterclient.Interface + WorkClient workv1client.Interface + bootstrapHubSecret *corev1.Secret + EventuallyTimeout time.Duration + EventuallyInterval time.Duration + clusterManagerNamespace string + klusterletDefaultNamespace string + hubRegistrationDeployment string + hubRegistrationWebhookDeployment string + hubWorkWebhookDeployment string + operatorNamespace string + klusterletOperator string } // kubeconfigPath is the path of kubeconfig file, will be get from env "KUBECONFIG" by default. @@ -52,14 +53,15 @@ type Tester struct { func NewTester(kubeconfigPath string) (*Tester, error) { var err error var tester = Tester{ - EventuallyTimeout: 60 * time.Second, // seconds - EventuallyInterval: 1 * time.Second, // seconds - clusterManagerNamespace: helpers.ClusterManagerNamespace, - klusterletDefaultNamespace: helpers.KlusterletDefaultNamespace, - hubRegistrationDeployment: "cluster-manager-registration-controller", - hubWebhookDeployment: "cluster-manager-registration-webhook", - operatorNamespace: "open-cluster-management", - klusterletOperator: "klusterlet", + EventuallyTimeout: 60 * time.Second, // seconds + EventuallyInterval: 1 * time.Second, // seconds + clusterManagerNamespace: helpers.ClusterManagerNamespace, + klusterletDefaultNamespace: helpers.KlusterletDefaultNamespace, + hubRegistrationDeployment: "cluster-manager-registration-controller", + hubRegistrationWebhookDeployment: "cluster-manager-registration-webhook", + hubWorkWebhookDeployment: "cluster-manager-work-webhook", + operatorNamespace: "open-cluster-management", + klusterletOperator: "klusterlet", } if kubeconfigPath == "" { @@ -378,7 +380,12 @@ func (t *Tester) CheckHubReady() error { } if _, err := t.KubeClient.AppsV1().Deployments(t.clusterManagerNamespace). - Get(context.TODO(), t.hubWebhookDeployment, metav1.GetOptions{}); err != nil { + Get(context.TODO(), t.hubRegistrationWebhookDeployment, metav1.GetOptions{}); err != nil { + return err + } + + if _, err := t.KubeClient.AppsV1().Deployments(t.clusterManagerNamespace). + Get(context.TODO(), t.hubWorkWebhookDeployment, metav1.GetOptions{}); err != nil { return err } return nil diff --git a/test/integration/clustermanager_test.go b/test/integration/clustermanager_test.go index 7f76f3a56..91f6b81de 100644 --- a/test/integration/clustermanager_test.go +++ b/test/integration/clustermanager_test.go @@ -53,7 +53,8 @@ var _ = ginkgo.Describe("ClusterManager", func() { // Check clusterrole/clusterrolebinding hubRegistrationClusterRole := fmt.Sprintf("open-cluster-management:%s-registration:controller", clusterManagerName) - hubWebhookClusterRole := fmt.Sprintf("open-cluster-management:%s-registration:webhook", clusterManagerName) + hubRegistrationWebhookClusterRole := fmt.Sprintf("open-cluster-management:%s-registration:webhook", clusterManagerName) + hubWorkWebhookClusterRole := fmt.Sprintf("open-cluster-management:%s-registration:webhook", clusterManagerName) gomega.Eventually(func() bool { if _, err := kubeClient.RbacV1().ClusterRoles().Get(context.Background(), hubRegistrationClusterRole, metav1.GetOptions{}); err != nil { return false @@ -61,7 +62,13 @@ var _ = ginkgo.Describe("ClusterManager", func() { return true }, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue()) gomega.Eventually(func() bool { - if _, err := kubeClient.RbacV1().ClusterRoles().Get(context.Background(), hubWebhookClusterRole, metav1.GetOptions{}); err != nil { + if _, err := kubeClient.RbacV1().ClusterRoles().Get(context.Background(), hubRegistrationWebhookClusterRole, metav1.GetOptions{}); err != nil { + return false + } + return true + }, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue()) + gomega.Eventually(func() bool { + if _, err := kubeClient.RbacV1().ClusterRoles().Get(context.Background(), hubWorkWebhookClusterRole, metav1.GetOptions{}); err != nil { return false } return true @@ -73,7 +80,13 @@ var _ = ginkgo.Describe("ClusterManager", func() { return true }, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue()) gomega.Eventually(func() bool { - if _, err := kubeClient.RbacV1().ClusterRoleBindings().Get(context.Background(), hubWebhookClusterRole, metav1.GetOptions{}); err != nil { + if _, err := kubeClient.RbacV1().ClusterRoleBindings().Get(context.Background(), hubRegistrationWebhookClusterRole, metav1.GetOptions{}); err != nil { + return false + } + return true + }, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue()) + gomega.Eventually(func() bool { + if _, err := kubeClient.RbacV1().ClusterRoleBindings().Get(context.Background(), hubWorkWebhookClusterRole, metav1.GetOptions{}); err != nil { return false } return true @@ -81,7 +94,8 @@ var _ = ginkgo.Describe("ClusterManager", func() { // Check service account hubRegistrationSA := fmt.Sprintf("%s-registration-controller-sa", clusterManagerName) - hubWebhookSA := fmt.Sprintf("%s-registration-webhook-sa", clusterManagerName) + hubRegistrationWebhookSA := fmt.Sprintf("%s-registration-webhook-sa", clusterManagerName) + hubWorkWebhookSA := fmt.Sprintf("%s-work-webhook-sa", clusterManagerName) gomega.Eventually(func() bool { if _, err := kubeClient.CoreV1().ServiceAccounts(hubNamespace).Get(context.Background(), hubRegistrationSA, metav1.GetOptions{}); err != nil { return false @@ -89,7 +103,13 @@ var _ = ginkgo.Describe("ClusterManager", func() { return true }, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue()) gomega.Eventually(func() bool { - if _, err := kubeClient.CoreV1().ServiceAccounts(hubNamespace).Get(context.Background(), hubWebhookSA, metav1.GetOptions{}); err != nil { + if _, err := kubeClient.CoreV1().ServiceAccounts(hubNamespace).Get(context.Background(), hubRegistrationWebhookSA, metav1.GetOptions{}); err != nil { + return false + } + return true + }, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue()) + gomega.Eventually(func() bool { + if _, err := kubeClient.CoreV1().ServiceAccounts(hubNamespace).Get(context.Background(), hubWorkWebhookSA, metav1.GetOptions{}); err != nil { return false } return true @@ -103,9 +123,17 @@ var _ = ginkgo.Describe("ClusterManager", func() { return true }, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue()) - hubWebhookDeployment := fmt.Sprintf("%s-registration-webhook", clusterManagerName) + hubRegistrationWebhookDeployment := fmt.Sprintf("%s-registration-webhook", clusterManagerName) gomega.Eventually(func() bool { - if _, err := kubeClient.AppsV1().Deployments(hubNamespace).Get(context.Background(), hubWebhookDeployment, metav1.GetOptions{}); err != nil { + if _, err := kubeClient.AppsV1().Deployments(hubNamespace).Get(context.Background(), hubRegistrationWebhookDeployment, metav1.GetOptions{}); err != nil { + return false + } + return true + }, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue()) + + hubWorkWebhookDeployment := fmt.Sprintf("%s-work-webhook", clusterManagerName) + gomega.Eventually(func() bool { + if _, err := kubeClient.AppsV1().Deployments(hubNamespace).Get(context.Background(), hubWorkWebhookDeployment, metav1.GetOptions{}); err != nil { return false } return true @@ -113,16 +141,35 @@ var _ = ginkgo.Describe("ClusterManager", func() { // Check service gomega.Eventually(func() bool { - if _, err := kubeClient.CoreV1().Services(hubNamespace).Get(context.Background(), hubWebhookDeployment, metav1.GetOptions{}); err != nil { + if _, err := kubeClient.CoreV1().Services(hubNamespace).Get(context.Background(), "cluster-manager-registration-webhook", metav1.GetOptions{}); err != nil { + return false + } + return true + }, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue()) + + gomega.Eventually(func() bool { + if _, err := kubeClient.CoreV1().Services(hubNamespace).Get(context.Background(), "cluster-manager-work-webhook", metav1.GetOptions{}); err != nil { return false } return true }, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue()) // Check webhook secret - webhookSecret := "webhook-serving-cert" + registrationWebhookSecret := "registration-webhook-serving-cert" gomega.Eventually(func() bool { - s, err := kubeClient.CoreV1().Secrets(hubNamespace).Get(context.Background(), webhookSecret, metav1.GetOptions{}) + s, err := kubeClient.CoreV1().Secrets(hubNamespace).Get(context.Background(), registrationWebhookSecret, metav1.GetOptions{}) + if err != nil { + return false + } + if s.Data == nil || s.Data["ca.crt"] == nil || s.Data["tls.crt"] == nil || s.Data["tls.key"] == nil { + return false + } + return true + }, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue()) + + workWebhookSecret := "work-webhook-serving-cert" + gomega.Eventually(func() bool { + s, err := kubeClient.CoreV1().Secrets(hubNamespace).Get(context.Background(), workWebhookSecret, metav1.GetOptions{}) if err != nil { return false } @@ -133,9 +180,17 @@ var _ = ginkgo.Describe("ClusterManager", func() { }, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue()) // Check validating webhook - validtingWebhook := "managedclustervalidators.admission.cluster.open-cluster-management.io" + registrationValidtingWebhook := "managedclustervalidators.admission.cluster.open-cluster-management.io" gomega.Eventually(func() bool { - if _, err := kubeClient.AdmissionregistrationV1().ValidatingWebhookConfigurations().Get(context.Background(), validtingWebhook, metav1.GetOptions{}); err != nil { + if _, err := kubeClient.AdmissionregistrationV1().ValidatingWebhookConfigurations().Get(context.Background(), registrationValidtingWebhook, metav1.GetOptions{}); err != nil { + return false + } + return true + }, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue()) + + workValidtingWebhook := "manifestworkvalidators.admission.work.open-cluster-management.io" + gomega.Eventually(func() bool { + if _, err := kubeClient.AdmissionregistrationV1().ValidatingWebhookConfigurations().Get(context.Background(), workValidtingWebhook, metav1.GetOptions{}); err != nil { return false } return true diff --git a/test/integration/integration_suite_test.go b/test/integration/integration_suite_test.go index 2dc3c3165..c9b71c24d 100644 --- a/test/integration/integration_suite_test.go +++ b/test/integration/integration_suite_test.go @@ -76,6 +76,7 @@ var _ = ginkgo.BeforeSuite(func(done ginkgo.Done) { }, Spec: operatorapiv1.ClusterManagerSpec{ RegistrationImagePullSpec: "quay.io/open-cluster-management/registration", + WorkImagePullSpec: "quay.io/open-cluster-management/work", }, } _, err = operatorClient.OperatorV1().ClusterManagers().Create(context.Background(), clusterManager, metav1.CreateOptions{}) diff --git a/vendor/github.com/open-cluster-management/api/operator/v1/0000_01_operator.open-cluster-management.io_clustermanagers.crd.yaml b/vendor/github.com/open-cluster-management/api/operator/v1/0000_01_operator.open-cluster-management.io_clustermanagers.crd.yaml index b330faea7..88f5a55c7 100644 --- a/vendor/github.com/open-cluster-management/api/operator/v1/0000_01_operator.open-cluster-management.io_clustermanagers.crd.yaml +++ b/vendor/github.com/open-cluster-management/api/operator/v1/0000_01_operator.open-cluster-management.io_clustermanagers.crd.yaml @@ -39,7 +39,11 @@ spec: properties: registrationImagePullSpec: description: RegistrationImagePullSpec represents the desired image - of registration controller installed on hub. + of registration controller/webhook installed on hub. + type: string + workImagePullSpec: + description: WorkImagePullSpec represents the desired image configuration + of work controller/webhook installed on hub. type: string status: description: Status represents the current status of controllers that govern diff --git a/vendor/github.com/open-cluster-management/api/operator/v1/types.go b/vendor/github.com/open-cluster-management/api/operator/v1/types.go index 1ab608e60..00ce95f98 100644 --- a/vendor/github.com/open-cluster-management/api/operator/v1/types.go +++ b/vendor/github.com/open-cluster-management/api/operator/v1/types.go @@ -26,9 +26,13 @@ type ClusterManager struct { // ClusterManagerSpec represents a desired deployment configuration of controllers that govern registration and work distribution for attached Klusterlets. type ClusterManagerSpec struct { - // RegistrationImagePullSpec represents the desired image of registration controller installed on hub. + // RegistrationImagePullSpec represents the desired image of registration controller/webhook installed on hub. // +required RegistrationImagePullSpec string `json:"registrationImagePullSpec"` + + // WorkImagePullSpec represents the desired image configuration of work controller/webhook installed on hub. + // +required + WorkImagePullSpec string `json:"workImagePullSpec,omitempty"` } // ClusterManagerStatus represents the current status of the registration and work distribution controllers running on the hub. diff --git a/vendor/github.com/open-cluster-management/api/operator/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/open-cluster-management/api/operator/v1/zz_generated.swagger_doc_generated.go index 811bba3e8..cffd533f6 100644 --- a/vendor/github.com/open-cluster-management/api/operator/v1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/open-cluster-management/api/operator/v1/zz_generated.swagger_doc_generated.go @@ -33,7 +33,8 @@ func (ClusterManagerList) SwaggerDoc() map[string]string { var map_ClusterManagerSpec = map[string]string{ "": "ClusterManagerSpec represents a desired deployment configuration of controllers that govern registration and work distribution for attached Klusterlets.", - "registrationImagePullSpec": "RegistrationImagePullSpec represents the desired image of registration controller installed on hub.", + "registrationImagePullSpec": "RegistrationImagePullSpec represents the desired image of registration controller/webhook installed on hub.", + "workImagePullSpec": "WorkImagePullSpec represents the desired image configuration of work controller/webhook installed on hub.", } func (ClusterManagerSpec) SwaggerDoc() map[string]string { diff --git a/vendor/modules.txt b/vendor/modules.txt index 1bd61bbb5..1ac4c8fb2 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -133,7 +133,7 @@ github.com/onsi/gomega/matchers/support/goraph/edge github.com/onsi/gomega/matchers/support/goraph/node github.com/onsi/gomega/matchers/support/goraph/util github.com/onsi/gomega/types -# github.com/open-cluster-management/api v0.0.0-20200715201722-3c3c076bf062 +# github.com/open-cluster-management/api v0.0.0-20200806152638-5caae08712f5 github.com/open-cluster-management/api/client/cluster/clientset/versioned github.com/open-cluster-management/api/client/cluster/clientset/versioned/scheme github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1