From 4204a24d43fea670c67817b23c8fdcafabc1deeb Mon Sep 17 00:00:00 2001 From: Jon Jackson Date: Tue, 7 Sep 2021 09:50:16 -0400 Subject: [PATCH 1/3] Add multicluster API server config to console operator. - Still need feature gate and oauth work for multicluster to be fully implmented - Add managed cluster controller that watches ACM ManagedCluster resources and builds a config file that can be consumed by the console backend - Update console deployment sync with new volumes and volume mounts for managed cluster config and CA bundles. - Add managed cluster and API server CA bundle ConfigMaps to subresources - Update informer event filter utils - Add github.com/open-cluster-management/api dependency --- examples/cvo-unmanage-operator.yaml | 10 +- go.mod | 1 + go.sum | 3 + manifests/03-rbac-role-cluster.yaml | 200 +++---- pkg/api/api.go | 8 + .../controllers/clidownloads/controller.go | 4 +- .../downloadsdeployment/controller.go | 4 +- .../controllers/healthcheck/controller.go | 4 +- .../controllers/managedclusters/controller.go | 265 +++++++++ pkg/console/controllers/route/controller.go | 4 +- pkg/console/controllers/service/controller.go | 4 +- pkg/console/controllers/util/util.go | 28 +- pkg/console/operator/operator.go | 10 +- pkg/console/operator/sync_v400.go | 41 +- pkg/console/starter/starter.go | 32 ++ .../subresource/configmap/api_server_ca.go | 45 ++ .../configmap/api_server_ca_test.go | 107 ++++ .../subresource/configmap/configmap.go | 1 + .../subresource/configmap/configmap_test.go | 19 +- .../subresource/configmap/managed_clusters.go | 41 ++ .../configmap/managed_clusters_test.go | 124 ++++ .../consoleserver/config_builder.go | 23 +- .../subresource/consoleserver/types.go | 37 +- .../subresource/deployment/deployment.go | 33 +- .../subresource/deployment/deployment_test.go | 32 +- .../open-cluster-management/api/LICENSE | 201 +++++++ .../cluster/clientset/versioned/clientset.go | 95 ++++ .../client/cluster/clientset/versioned/doc.go | 4 + .../cluster/clientset/versioned/scheme/doc.go | 4 + .../clientset/versioned/scheme/register.go | 42 ++ .../typed/cluster/v1/cluster_client.go | 73 +++ .../versioned/typed/cluster/v1/doc.go | 4 + .../typed/cluster/v1/generated_expansion.go | 5 + .../typed/cluster/v1/managedcluster.go | 168 ++++++ .../typed/cluster/v1alpha1/cluster_client.go | 93 +++ .../typed/cluster/v1alpha1/clusterclaim.go | 152 +++++ .../versioned/typed/cluster/v1alpha1/doc.go | 4 + .../cluster/v1alpha1/generated_expansion.go | 13 + .../cluster/v1alpha1/managedclusterset.go | 168 ++++++ .../v1alpha1/managedclustersetbinding.go | 162 ++++++ .../typed/cluster/v1alpha1/placement.go | 179 ++++++ .../cluster/v1alpha1/placementdecision.go | 179 ++++++ .../externalversions/cluster/interface.go | 38 ++ .../externalversions/cluster/v1/interface.go | 29 + .../cluster/v1/managedcluster.go | 73 +++ .../cluster/v1alpha1/clusterclaim.go | 73 +++ .../cluster/v1alpha1/interface.go | 57 ++ .../cluster/v1alpha1/managedclusterset.go | 73 +++ .../v1alpha1/managedclustersetbinding.go | 74 +++ .../cluster/v1alpha1/placement.go | 74 +++ .../cluster/v1alpha1/placementdecision.go | 74 +++ .../informers/externalversions/factory.go | 164 ++++++ .../informers/externalversions/generic.go | 59 ++ .../internalinterfaces/factory_interfaces.go | 24 + .../listers/cluster/v1/expansion_generated.go | 7 + .../listers/cluster/v1/managedcluster.go | 52 ++ .../listers/cluster/v1alpha1/clusterclaim.go | 52 ++ .../cluster/v1alpha1/expansion_generated.go | 35 ++ .../cluster/v1alpha1/managedclusterset.go | 52 ++ .../v1alpha1/managedclustersetbinding.go | 83 +++ .../listers/cluster/v1alpha1/placement.go | 83 +++ .../cluster/v1alpha1/placementdecision.go | 83 +++ ...ter-management.io_managedclusters.crd.yaml | 244 ++++++++ .../api/cluster/v1/doc.go | 9 + .../api/cluster/v1/register.go | 38 ++ .../api/cluster/v1/types.go | 171 ++++++ .../api/cluster/v1/zz_generated.deepcopy.go | 212 +++++++ .../v1/zz_generated.swagger_doc_generated.go | 87 +++ ...-management.io_managedclustersets.crd.yaml | 134 +++++ ...ment.io_managedclustersetbindings.crd.yaml | 60 ++ ...uster-management.io_clusterclaims.crd.yaml | 54 ++ ...-cluster-management.io_placements.crd.yaml | 274 +++++++++ ...-management.io_placementdecisions.crd.yaml | 76 +++ ...uster-management.io_clusterclaims.crd.yaml | 55 ++ .../api/cluster/v1alpha1/doc.go | 9 + .../api/cluster/v1alpha1/register.go | 46 ++ .../api/cluster/v1alpha1/types.go | 358 ++++++++++++ .../cluster/v1alpha1/zz_generated.deepcopy.go | 534 ++++++++++++++++++ .../zz_generated.swagger_doc_generated.go | 212 +++++++ vendor/modules.txt | 15 + 80 files changed, 6314 insertions(+), 159 deletions(-) create mode 100644 pkg/console/controllers/managedclusters/controller.go create mode 100644 pkg/console/subresource/configmap/api_server_ca.go create mode 100644 pkg/console/subresource/configmap/api_server_ca_test.go create mode 100644 pkg/console/subresource/configmap/managed_clusters.go create mode 100644 pkg/console/subresource/configmap/managed_clusters_test.go create mode 100644 vendor/github.com/open-cluster-management/api/LICENSE create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/clientset.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/doc.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/scheme/doc.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/scheme/register.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1/cluster_client.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1/doc.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1/generated_expansion.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1/managedcluster.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/cluster_client.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/clusterclaim.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/doc.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/generated_expansion.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/managedclusterset.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/managedclustersetbinding.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/placement.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/placementdecision.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/interface.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1/interface.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1/managedcluster.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/clusterclaim.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/interface.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/managedclusterset.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/managedclustersetbinding.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/placement.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/placementdecision.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/factory.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/generic.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/internalinterfaces/factory_interfaces.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1/expansion_generated.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1/managedcluster.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/clusterclaim.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/expansion_generated.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/managedclusterset.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/managedclustersetbinding.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/placement.go create mode 100644 vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/placementdecision.go create mode 100644 vendor/github.com/open-cluster-management/api/cluster/v1/0000_00_clusters.open-cluster-management.io_managedclusters.crd.yaml create mode 100644 vendor/github.com/open-cluster-management/api/cluster/v1/doc.go create mode 100644 vendor/github.com/open-cluster-management/api/cluster/v1/register.go create mode 100644 vendor/github.com/open-cluster-management/api/cluster/v1/types.go create mode 100644 vendor/github.com/open-cluster-management/api/cluster/v1/zz_generated.deepcopy.go create mode 100644 vendor/github.com/open-cluster-management/api/cluster/v1/zz_generated.swagger_doc_generated.go create mode 100644 vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0000_00_clusters.open-cluster-management.io_managedclustersets.crd.yaml create mode 100644 vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0000_01_clusters.open-cluster-management.io_managedclustersetbindings.crd.yaml create mode 100644 vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0000_02_clusters.open-cluster-management.io_clusterclaims.crd.yaml create mode 100644 vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0000_03_clusters.open-cluster-management.io_placements.crd.yaml create mode 100644 vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0000_04_clusters.open-cluster-management.io_placementdecisions.crd.yaml create mode 100644 vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0001_02_clusters.open-cluster-management.io_clusterclaims.crd.yaml create mode 100644 vendor/github.com/open-cluster-management/api/cluster/v1alpha1/doc.go create mode 100644 vendor/github.com/open-cluster-management/api/cluster/v1alpha1/register.go create mode 100644 vendor/github.com/open-cluster-management/api/cluster/v1alpha1/types.go create mode 100644 vendor/github.com/open-cluster-management/api/cluster/v1alpha1/zz_generated.deepcopy.go create mode 100644 vendor/github.com/open-cluster-management/api/cluster/v1alpha1/zz_generated.swagger_doc_generated.go diff --git a/examples/cvo-unmanage-operator.yaml b/examples/cvo-unmanage-operator.yaml index 95908a2677..bd6deb98ad 100644 --- a/examples/cvo-unmanage-operator.yaml +++ b/examples/cvo-unmanage-operator.yaml @@ -5,8 +5,8 @@ metadata: name: version spec: overrides: - - kind: Deployment - name: console-operator - namespace: openshift-console-operator - unmanaged: true - group: apps/v1 + - kind: Deployment + name: console-operator + namespace: openshift-console-operator + unmanaged: true + group: apps/v1 diff --git a/go.mod b/go.mod index 6b44c09339..781dfb9ac1 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/go-bindata/go-bindata v3.1.2+incompatible github.com/go-test/deep v1.0.5 github.com/google/gofuzz v1.2.0 // indirect + github.com/open-cluster-management/api v0.0.0-20210527013639-a6845f2ebcb1 github.com/openshift/api v0.0.0-20210729103544-e4a0474d1519 github.com/openshift/build-machinery-go v0.0.0-20210712174854-1bb7fd1518d3 github.com/openshift/client-go v0.0.0-20210112160336-8889f8b15bd6 diff --git a/go.sum b/go.sum index 7a48108ee6..6e12e09cdf 100644 --- a/go.sum +++ b/go.sum @@ -410,6 +410,8 @@ github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/open-cluster-management/api v0.0.0-20210527013639-a6845f2ebcb1 h1:AaFycHD9YOfFXe9C5VsYxKf4LKCXKSLZgK2DnFdHY4M= +github.com/open-cluster-management/api v0.0.0-20210527013639-a6845f2ebcb1/go.mod h1:ot+A1DWq+v1IV+e1S7nhIteYAmNByFgtazvzpoeAfRQ= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/openshift/api v0.0.0-20201214114959-164a2fb63b5f/go.mod h1:aqU5Cq+kqKKPbDMqxo9FojgDeSpNJI7iuskjXjtojDg= @@ -418,6 +420,7 @@ github.com/openshift/api v0.0.0-20210325044225-ef3741adfc31/go.mod h1:aqU5Cq+kqK github.com/openshift/api v0.0.0-20210729103544-e4a0474d1519 h1:g9hT0d7niFH2GD9NT8RHRq/45qDfNkRfEZw2A4HTrjc= github.com/openshift/api v0.0.0-20210729103544-e4a0474d1519/go.mod h1:wf/SnvIX5Aq1NkALk26b2extjOGm3Q781gEgvr0+CDY= github.com/openshift/build-machinery-go v0.0.0-20200917070002-f171684f77ab/go.mod h1:b1BuldmJlbA/xYtdZvKi+7j5YGB44qJUJDZ9zwiNCfE= +github.com/openshift/build-machinery-go v0.0.0-20210115170933-e575b44a7a94/go.mod h1:b1BuldmJlbA/xYtdZvKi+7j5YGB44qJUJDZ9zwiNCfE= github.com/openshift/build-machinery-go v0.0.0-20210712174854-1bb7fd1518d3 h1:hYMLjavR8LrcCva788SxDqYjRc1k2w0LNGi7eX9vY5Y= github.com/openshift/build-machinery-go v0.0.0-20210712174854-1bb7fd1518d3/go.mod h1:b1BuldmJlbA/xYtdZvKi+7j5YGB44qJUJDZ9zwiNCfE= github.com/openshift/client-go v0.0.0-20201214125552-e615e336eb49/go.mod h1:9/jG4I6sh+5QublJpZZ4Zs/P4/QCXMsQQ/K/058bSB8= diff --git a/manifests/03-rbac-role-cluster.yaml b/manifests/03-rbac-role-cluster.yaml index d7a1e0af30..99d6f9372f 100644 --- a/manifests/03-rbac-role-cluster.yaml +++ b/manifests/03-rbac-role-cluster.yaml @@ -7,79 +7,87 @@ metadata: include.release.openshift.io/self-managed-high-availability: "true" include.release.openshift.io/single-node-developer: "true" rules: -- apiGroups: - - oauth.openshift.io - resources: - - oauthclients - verbs: - - get - - list - - update - - watch - resourceNames: - - console -- apiGroups: - - config.openshift.io - resources: - - oauths - verbs: - - get - - list - - watch -- apiGroups: - - config.openshift.io - resources: - - infrastructures - - ingresses - verbs: - - get - - list - - watch -- apiGroups: - - config.openshift.io - resources: - - proxies - verbs: - - get - - list - - watch -- apiGroups: - - config.openshift.io - resources: - - consoles - - consoles/status - - clusteroperators - - clusteroperators/status - verbs: - - get - - list - - watch - - create - - update - - delete -- apiGroups: - - operator.openshift.io - resources: - - consoles - - consoles/status - verbs: - - get - - list - - watch - - create - - update - - delete -- apiGroups: - - console.openshift.io - resources: - - consoleclidownloads - verbs: - - get - - list - - watch - - create - - update - - delete + - apiGroups: + - oauth.openshift.io + resources: + - oauthclients + verbs: + - get + - list + - update + - watch + resourceNames: + - console + - apiGroups: + - config.openshift.io + resources: + - oauths + verbs: + - get + - list + - watch + - apiGroups: + - config.openshift.io + resources: + - infrastructures + - ingresses + verbs: + - get + - list + - watch + - apiGroups: + - config.openshift.io + resources: + - proxies + verbs: + - get + - list + - watch + - apiGroups: + - config.openshift.io + resources: + - consoles + - consoles/status + - clusteroperators + - clusteroperators/status + verbs: + - get + - list + - watch + - create + - update + - delete + - apiGroups: + - operator.openshift.io + resources: + - consoles + - consoles/status + verbs: + - get + - list + - watch + - create + - update + - delete + - apiGroups: + - console.openshift.io + resources: + - consoleclidownloads + verbs: + - get + - list + - watch + - create + - update + - delete + - apiGroups: + - cluster.open-cluster-management.io + resources: + - managedclusters + verbs: + - get + - list + - watch --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 @@ -90,29 +98,29 @@ metadata: include.release.openshift.io/self-managed-high-availability: "true" include.release.openshift.io/single-node-developer: "true" rules: -- apiGroups: - - apiextensions.k8s.io - resources: - - customresourcedefinitions - verbs: - - get - - list - - watch -- apiGroups: - - admissionregistration.k8s.io - resources: - - mutatingwebhookconfigurations - - validatingwebhookconfigurations - verbs: - - get -- apiGroups: - - operators.coreos.com - resources: - - subscriptions - resourceNames: - - web-terminal - verbs: - - get + - apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - get + - list + - watch + - apiGroups: + - admissionregistration.k8s.io + resources: + - mutatingwebhookconfigurations + - validatingwebhookconfigurations + verbs: + - get + - apiGroups: + - operators.coreos.com + resources: + - subscriptions + resourceNames: + - web-terminal + verbs: + - get --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 diff --git a/pkg/api/api.go b/pkg/api/api.go index 12adb53979..76f44b65c3 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -35,6 +35,14 @@ const ( TrustedCABundleMountFile = "tls-ca-bundle.pem" OCCLIDownloadsCustomResourceName = "oc-cli-downloads" ODOCLIDownloadsCustomResourceName = "odo-cli-downloads" + HubClusterName = "local-cluster" + ManagedClusterLabel = "managed-cluster" + ManagedClusterConfigMapName = "managed-clusters" + ManagedClusterConfigMountDir = "/var/managed-cluster-config" + ManagedClusterConfigKey = "managed-clusters.yaml" + ManagedClusterAPIServerCAMountDir = "/var/managed-cluster-certs" + ManagedClusterAPIServerCAName = "managed-cluster-api-server-ca" + ManagedClusterAPIServerCAKey = "ca-bundle.crt" ConsoleContainerPortName = "https" ConsoleContainerPort = 443 diff --git a/pkg/console/controllers/clidownloads/controller.go b/pkg/console/controllers/clidownloads/controller.go index 4395675126..07550d93e3 100644 --- a/pkg/console/controllers/clidownloads/controller.go +++ b/pkg/console/controllers/clidownloads/controller.go @@ -72,10 +72,10 @@ func NewCLIDownloadsSyncController( return factory.New(). WithFilteredEventsInformers( // configs - controllersutil.NamesFilter(api.ConfigResourceName), + controllersutil.IncludeNamesFilter(api.ConfigResourceName), operatorConfigInformer.Informer(), ).WithFilteredEventsInformers( // console resources - controllersutil.NamesFilter(api.OpenShiftConsoleDownloadsRouteName), + controllersutil.IncludeNamesFilter(api.OpenShiftConsoleDownloadsRouteName), routeInformer.Informer(), ).WithInformers( consoleCLIDownloadsInformers.Informer(), diff --git a/pkg/console/controllers/downloadsdeployment/controller.go b/pkg/console/controllers/downloadsdeployment/controller.go index e072062ab2..85732cab45 100644 --- a/pkg/console/controllers/downloadsdeployment/controller.go +++ b/pkg/console/controllers/downloadsdeployment/controller.go @@ -64,8 +64,8 @@ func NewDownloadsDeploymentSyncController( deploymentClient: deploymentClient, } - configNameFilter := util.NamesFilter(api.ConfigResourceName) - downloadsNameFilter := util.NamesFilter(api.OpenShiftConsoleDownloadsDeploymentName) + configNameFilter := util.IncludeNamesFilter(api.ConfigResourceName) + downloadsNameFilter := util.IncludeNamesFilter(api.OpenShiftConsoleDownloadsDeploymentName) return factory.New(). WithFilteredEventsInformers( // infrastructure configs diff --git a/pkg/console/controllers/healthcheck/controller.go b/pkg/console/controllers/healthcheck/controller.go index a110b345e4..b1df7ccd30 100644 --- a/pkg/console/controllers/healthcheck/controller.go +++ b/pkg/console/controllers/healthcheck/controller.go @@ -71,10 +71,10 @@ func NewHealthCheckController( return factory.New(). WithFilteredEventsInformers( // service - util.NamesFilter(api.TrustedCAConfigMapName, api.DefaultIngressCertConfigMapName), + util.IncludeNamesFilter(api.TrustedCAConfigMapName, api.OAuthServingCertConfigMapName), configMapInformer.Informer(), ).WithFilteredEventsInformers( // route - util.NamesFilter(api.OpenShiftConsoleRouteName, api.OpenshiftConsoleCustomRouteName), + util.IncludeNamesFilter(api.OpenShiftConsoleRouteName, api.OpenshiftConsoleCustomRouteName), routeInformer.Informer(), ).ResyncEvery(30*time.Second).WithSync(ctrl.Sync). ToController("HealthCheckController", recorder.WithComponentSuffix("health-check-controller")) diff --git a/pkg/console/controllers/managedclusters/controller.go b/pkg/console/controllers/managedclusters/controller.go new file mode 100644 index 0000000000..d2eb9e36f7 --- /dev/null +++ b/pkg/console/controllers/managedclusters/controller.go @@ -0,0 +1,265 @@ +package managedcluster + +import ( + "context" + "errors" + "fmt" + "strings" + + // k8s + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + coreclientv1 "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/klog/v2" + + // openshift + clusterclientv1 "github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1" + clusterinformersv1 "github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1" + clusterv1 "github.com/open-cluster-management/api/cluster/v1" + operatorv1 "github.com/openshift/api/operator/v1" + configclientv1 "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1" + configinformer "github.com/openshift/client-go/config/informers/externalversions" + operatorclientv1 "github.com/openshift/client-go/operator/clientset/versioned/typed/operator/v1" + v1 "github.com/openshift/client-go/operator/informers/externalversions/operator/v1" + "github.com/openshift/library-go/pkg/controller/factory" + "github.com/openshift/library-go/pkg/operator/events" + "github.com/openshift/library-go/pkg/operator/resource/resourceapply" + "github.com/openshift/library-go/pkg/operator/v1helpers" + + //subresources + configmapsub "github.com/openshift/console-operator/pkg/console/subresource/configmap" + + // console-operator + "github.com/openshift/console-operator/pkg/api" + "github.com/openshift/console-operator/pkg/console/controllers/util" + "github.com/openshift/console-operator/pkg/console/status" + "github.com/openshift/console-operator/pkg/console/subresource/consoleserver" +) + +type ManagedClusterController struct { + operatorClient v1helpers.OperatorClient + operatorConfigClient operatorclientv1.ConsoleInterface + configMapClient coreclientv1.ConfigMapsGetter + managedClusterClient clusterclientv1.ManagedClustersGetter +} + +func NewManagedClusterController( + // top level config + configClient configclientv1.ConfigV1Interface, + configInformer configinformer.SharedInformerFactory, + // clients + operatorClient v1helpers.OperatorClient, + operatorConfigClient operatorclientv1.ConsoleInterface, + configMapClient coreclientv1.ConfigMapsGetter, + managedClusterClient clusterclientv1.ClusterV1Interface, + + // informers + operatorConfigInformer v1.ConsoleInformer, + managedClusterInformers clusterinformersv1.ManagedClusterInformer, + + // events + recorder events.Recorder, +) factory.Controller { + ctrl := &ManagedClusterController{ + operatorClient: operatorClient, + operatorConfigClient: operatorConfigClient, + configMapClient: configMapClient, + managedClusterClient: managedClusterClient, + } + + configV1Informers := configInformer.Config().V1() + + return factory.New(). + WithFilteredEventsInformers( // configs + util.IncludeNamesFilter(api.ConfigResourceName), + configV1Informers.Consoles().Informer(), + operatorConfigInformer.Informer(), + ).WithFilteredEventsInformers( + util.ExcludeNamesFilter(api.HubClusterName), + managedClusterInformers.Informer(), + ).WithSync(ctrl.Sync). + ToController("ManagedClusterController", recorder.WithComponentSuffix("managed-cluster-controller")) +} + +func (c *ManagedClusterController) Sync(ctx context.Context, controllerContext factory.SyncContext) error { + operatorConfig, err := c.operatorConfigClient.Get(ctx, api.ConfigResourceName, metav1.GetOptions{}) + if err != nil { + return err + } + + switch operatorConfig.Spec.ManagementState { + case operatorv1.Managed: + klog.V(4).Info("console-operator is in a managed state: syncing managed clusters") + case operatorv1.Unmanaged: + klog.V(4).Info("console-operator is in an unmanaged state: skipping managed cluster sync") + return nil + case operatorv1.Removed: + klog.V(4).Infof("console-operator is in a removed state: deleting managed clusters") + return c.removeManagedClusters(ctx) + default: + return fmt.Errorf("unknown state: %v", operatorConfig.Spec.ManagementState) + } + + statusHandler := status.NewStatusHandler(c.operatorClient) + + // Get a list of ManagedCluster resources, degraded if error is returned + managedClusterClientConfigs, managedClusterClientConfigValidationErr, managedClusterClientConfigValidationErrReason := c.ValidateManagedClusterClientConfigs(ctx, operatorConfig, controllerContext.Recorder()) + statusHandler.AddConditions(status.HandleProgressingOrDegraded("ManagedClusterValidation", managedClusterClientConfigValidationErrReason, managedClusterClientConfigValidationErr)) + if managedClusterClientConfigValidationErr != nil { + return statusHandler.FlushAndReturn(managedClusterClientConfigValidationErr) + } + + // No managed clusters exist, quit sync + if len(managedClusterClientConfigs) == 0 { + return statusHandler.FlushAndReturn(nil) + } + + // Create config maps for each managed cluster API server ca bundle + apiServerCASyncErr, apiServerCASyncErrReason := c.SyncAPIServerCAConfigMaps(managedClusterClientConfigs, ctx, operatorConfig, controllerContext.Recorder()) + statusHandler.AddConditions(status.HandleProgressingOrDegraded("ManagedClusterAPIServerCASync", apiServerCASyncErrReason, apiServerCASyncErr)) + if apiServerCASyncErr != nil { + return statusHandler.FlushAndReturn(apiServerCASyncErr) + } + + // Create manged cluster config map + configSyncErr, configSyncErrReason := c.SyncManagedClusterConfigMap(managedClusterClientConfigs, ctx, operatorConfig, controllerContext.Recorder()) + statusHandler.AddConditions(status.HandleProgressingOrDegraded("ManagedClusterConfigSync", configSyncErrReason, configSyncErr)) + return statusHandler.FlushAndReturn(configSyncErr) +} + +// Return slice of clusterv1.ClientConfigs that have been validated or error and reaons if unable to list ManagedClusters +func (c *ManagedClusterController) ValidateManagedClusterClientConfigs(ctx context.Context, operatorConfig *operatorv1.Console, recorder events.Recorder) (map[string]*clusterv1.ClientConfig, error, string) { + managedClusters, err := c.managedClusterClient.ManagedClusters().List(ctx, metav1.ListOptions{LabelSelector: "local-cluster!=true"}) + + // Not found means API is not on the cluster + if apierrors.IsNotFound(err) { + return nil, nil, "" + } + + // Any other list request failure means operator is degraded + if err != nil { + return nil, err, "FailedList" + } + + validatedClientConfigs := map[string]*clusterv1.ClientConfig{} + for _, managedCluster := range managedClusters.Items { + clusterName := managedCluster.GetName() + + // Ensure client configs exists + clientConfigs := managedCluster.Spec.ManagedClusterClientConfigs + if len(clientConfigs) == 0 { + klog.V(4).Infoln(fmt.Sprintf("Skipping managed cluster %v, no client config found", clusterName)) + continue + } + + // Ensure client config CA bundle exists + if clientConfigs[0].CABundle == nil { + klog.V(4).Infoln(fmt.Sprintf("Skipping managed cluster %v, client config CA bundle not found", clusterName)) + continue + } + + // Ensure client config URL exists + if clientConfigs[0].URL == "" { + klog.V(4).Infof("Skipping managed cluster %v, client config URL not found", clusterName) + continue + } + + validatedClientConfigs[clusterName] = &clientConfigs[0] + } + + return validatedClientConfigs, nil, "" +} + +// Using ManagedCluster.spec.ManagedClusterClientConfigs, sync ConfigMaps containing the API server CA bundle for each managed cluster +// If a managed cluster doesn't have complete client config yet, the information is logged, but no error is returned +// If applying any ConfigMap fails, an error and reason are returned +func (c *ManagedClusterController) SyncAPIServerCAConfigMaps(clientConfigs map[string]*clusterv1.ClientConfig, ctx context.Context, operatorConfig *operatorv1.Console, recorder events.Recorder) (error, string) { + errs := []string{} + for clusterName, clientConfig := range clientConfigs { + // Apply the config map. If this fails for any managed cluster, operator is degraded + required := configmapsub.DefaultAPIServerCAConfigMap(clusterName, clientConfig.CABundle, operatorConfig) + _, _, configMapApplyError := resourceapply.ApplyConfigMap(c.configMapClient, recorder, required) + if configMapApplyError != nil { + klog.V(4).Infoln(fmt.Sprintf("Skipping API server CA ConfigMap sync for managed cluster %v, Error applying ConfigMap", clusterName)) + errs = append(errs, configMapApplyError.Error()) + continue + } + } + + // Return any apply errors that occurred + if len(errs) > 0 { + return errors.New(strings.Join(errs, "\n")), "APIServerCAConfigMapSyncError" + } + + // Success + return nil, "" +} + +// Using ManagedClusters.Spec.ManagedClusterClientConfigs and previously synced CA bundles, sync a ConfigMap containing serverconfig.ManagedClusterConfig YAML for each managed cluster +// If a managed cluster doesn't have an API server CA bundle ConfigMap yet or the client config is incomplete, this is logged, but no error is returned +// If applying the ConfigMap fails, an error and reason are returned +func (c *ManagedClusterController) SyncManagedClusterConfigMap(clientConfigs map[string]*clusterv1.ClientConfig, ctx context.Context, operatorConfig *operatorv1.Console, recorder events.Recorder) (error, string) { + managedClusterConfigs := []consoleserver.ManagedClusterConfig{} + for clusterName, clientConfig := range clientConfigs { + klog.V(4).Infoln(fmt.Sprintf("Building config for managed cluster: %v", clusterName)) + + // Check that managed cluster CA ConfigMap has already been synced, skip if not found + _, err := c.configMapClient.ConfigMaps(api.OpenShiftConsoleNamespace).Get(ctx, configmapsub.APIServerCAConfigMapName(clusterName), metav1.GetOptions{}) + if apierrors.IsNotFound(err) { + klog.V(4).Infof("CA file not found for managed cluster %v", clusterName) + continue + } + + // Skip if unable to get managed cluster API server config map for any other reason + if err != nil { + klog.V(4).Infof("Error getting CA file for managed cluster %v", clusterName) + continue + } + + managedClusterConfigs = append(managedClusterConfigs, consoleserver.ManagedClusterConfig{ + Name: clusterName, + APIServer: consoleserver.ManagedClusterAPIServerConfig{ + URL: clientConfig.URL, + CAFile: fmt.Sprintf("%s/%s/%s", api.ManagedClusterAPIServerCAMountDir, configmapsub.APIServerCAConfigMapName(clusterName), api.ManagedClusterAPIServerCAKey), + }, + }) + } + + if len(managedClusterConfigs) > 0 { + required, err := configmapsub.DefaultManagedClustersConfigMap(operatorConfig, managedClusterConfigs) + if err != nil { + return err, "FailedMarshallingYAML" + } + + if _, _, applyErr := resourceapply.ApplyConfigMap(c.configMapClient, recorder, required); applyErr != nil { + return applyErr, "FailedApply" + } + } + + return nil, "" +} + +func (c *ManagedClusterController) removeManagedClusters(ctx context.Context) error { + errs := []string{} + configMaps, err := c.configMapClient.ConfigMaps(api.OpenShiftConsoleNamespace).List(ctx, metav1.ListOptions{LabelSelector: api.ManagedClusterLabel}) + if err != nil { + klog.Errorf("Error listing managed cluster resources to remove: %v", err) + return err + } + + if len(configMaps.Items) == 0 { + klog.Info("No managed cluster resources to remove.") + return nil + } + + for _, configMap := range configMaps.Items { + deletionErr := c.configMapClient.ConfigMaps(api.OpenShiftConsoleNamespace).Delete(ctx, configMap.GetName(), metav1.DeleteOptions{}) + if deletionErr != nil && !apierrors.IsNotFound(deletionErr) { + errs = append(errs, deletionErr.Error()) + } + } + if len(errs) > 0 { + return errors.New(strings.Join(errs, "\n")) + } + return nil +} diff --git a/pkg/console/controllers/route/controller.go b/pkg/console/controllers/route/controller.go index 3aa13b3ced..e8076696da 100644 --- a/pkg/console/controllers/route/controller.go +++ b/pkg/console/controllers/route/controller.go @@ -81,14 +81,14 @@ func NewRouteSyncController( return factory.New(). WithFilteredEventsInformers( // configs - util.NamesFilter(api.ConfigResourceName), + util.IncludeNamesFilter(api.ConfigResourceName), configV1Informers.Consoles().Informer(), operatorConfigInformer.Informer(), configV1Informers.Ingresses().Informer(), ).WithInformers( secretInformer.Informer(), ).WithFilteredEventsInformers( // route - util.NamesFilter(routeName, routesub.GetCustomRouteName(routeName)), + util.IncludeNamesFilter(routeName, routesub.GetCustomRouteName(routeName)), routeInformer.Informer(), ).ResyncEvery(time.Minute).WithSync(ctrl.Sync). ToController(fmt.Sprintf("%sRouteController", strings.Title(routeName)), recorder.WithComponentSuffix(fmt.Sprintf("%s-route-controller", routeName))) diff --git a/pkg/console/controllers/service/controller.go b/pkg/console/controllers/service/controller.go index 0543394678..abc2b29cbf 100644 --- a/pkg/console/controllers/service/controller.go +++ b/pkg/console/controllers/service/controller.go @@ -71,11 +71,11 @@ func NewServiceSyncController( return factory.New(). WithFilteredEventsInformers( // configs - util.NamesFilter(api.ConfigResourceName), + util.IncludeNamesFilter(api.ConfigResourceName), operatorConfigInformer.Informer(), configV1Informers.Ingresses().Informer(), ).WithFilteredEventsInformers( // console resources - util.NamesFilter(serviceName, ctrl.getRedirectServiceName()), + util.IncludeNamesFilter(serviceName, ctrl.getRedirectServiceName()), serviceInformer.Informer(), ).ResyncEvery(time.Minute).WithSync(ctrl.Sync). ToController("ConsoleServiceController", recorder.WithComponentSuffix("console-service-controller")) diff --git a/pkg/console/controllers/util/util.go b/pkg/console/controllers/util/util.go index 42a2e33d0e..8d6603d93c 100644 --- a/pkg/console/controllers/util/util.go +++ b/pkg/console/controllers/util/util.go @@ -7,13 +7,33 @@ import ( "github.com/openshift/library-go/pkg/controller/factory" ) -func NamesFilter(names ...string) factory.EventFilterFunc { +// Return func which returns true if obj name is in names +func IncludeNamesFilter(names ...string) factory.EventFilterFunc { nameSet := sets.NewString(names...) return func(obj interface{}) bool { metaObj := obj.(metav1.Object) - if nameSet.Has(metaObj.GetName()) { - return true + return nameSet.Has(metaObj.GetName()) + } +} + +// Inverse of IncludeNamesFilter +func ExcludeNamesFilter(names ...string) factory.EventFilterFunc { + return func(obj interface{}) bool { + return !IncludeNamesFilter(names...)(obj) + } +} + +// Return a func which returns true if obj matches on every label in labels +// (i.e for each key in labels map, obj.metadata.labels[key] is equal to labels[key]) +func LabelFilter(labels map[string]string) factory.EventFilterFunc { + return func(obj interface{}) bool { + metaObj := obj.(metav1.Object) + objLabels := metaObj.GetLabels() + for k, v := range labels { + if objLabels[k] != v { + return false + } } - return false + return true } } diff --git a/pkg/console/operator/operator.go b/pkg/console/operator/operator.go index 70423bc550..a1d98ceb67 100644 --- a/pkg/console/operator/operator.go +++ b/pkg/console/operator/operator.go @@ -128,8 +128,8 @@ func NewConsoleOperator( managedConfigMapInformer := managedCoreV1.ConfigMaps() serviceInformer := coreV1.Services() configV1Informers := configInformer.Config().V1() - configNameFilter := util.NamesFilter(api.ConfigResourceName) - targetNameFilter := util.NamesFilter(api.OpenShiftConsoleName) + configNameFilter := util.IncludeNamesFilter(api.ConfigResourceName) + targetNameFilter := util.IncludeNamesFilter(api.OpenShiftConsoleName) return factory.New(). WithFilteredEventsInformers( // configs @@ -149,13 +149,13 @@ func NewConsoleOperator( ).WithInformers( consolePluginInformer.Informer(), ).WithFilteredEventsInformers( - util.NamesFilter(api.OpenShiftConsoleConfigMapName, api.ServiceCAConfigMapName, api.OpenShiftCustomLogoConfigMapName, api.TrustedCAConfigMapName), + util.LabelFilter(map[string]string{"app": "console"}), configMapInformer.Informer(), ).WithFilteredEventsInformers( - util.NamesFilter(api.OpenShiftConsoleConfigMapName, api.OpenShiftConsolePublicConfigMapName), + util.IncludeNamesFilter(api.OpenShiftConsoleConfigMapName, api.OpenShiftConsolePublicConfigMapName), managedConfigMapInformer.Informer(), ).WithFilteredEventsInformers( - util.NamesFilter(deployment.ConsoleOauthConfigName), + util.IncludeNamesFilter(deployment.ConsoleOauthConfigName), secretsInformer.Informer(), ).ResyncEvery(time.Minute).WithSync(c.Sync). ToController("ConsoleOperator", recorder.WithComponentSuffix("console-operator")) diff --git a/pkg/console/operator/sync_v400.go b/pkg/console/operator/sync_v400.go index 7746c5fba1..dd8bc6a3ab 100644 --- a/pkg/console/operator/sync_v400.go +++ b/pkg/console/operator/sync_v400.go @@ -78,6 +78,10 @@ func (co *consoleOperator) sync_v400(ctx context.Context, controllerContext fact return statusHandler.FlushAndReturn(cmErr) } + // managed-clusters ConfigMap is managed by another controller and is not required, we don't need to exit the sync loop if it's not present + canMountManagedClusterConfig, managedClusterConfigErrReason, managedClusterConfigErr := co.SyncManagedClusterConfigMap(ctx) + statusHandler.AddConditions(status.HandleProgressingOrDegraded("ManagedClusterConfigSync", managedClusterConfigErrReason, managedClusterConfigErr)) + serviceCAConfigMap, serviceCAChanged, serviceCAErrReason, serviceCAErr := co.SyncServiceCAConfigMap(ctx, set.Operator) toUpdate = toUpdate || serviceCAChanged statusHandler.AddConditions(status.HandleProgressingOrDegraded("ServiceCASync", serviceCAErrReason, serviceCAErr)) @@ -121,7 +125,7 @@ func (co *consoleOperator) sync_v400(ctx context.Context, controllerContext fact return statusHandler.FlushAndReturn(oauthErr) } - actualDeployment, depChanged, depErrReason, depErr := co.SyncDeployment(ctx, set.Operator, cm, serviceCAConfigMap, oauthServingCertConfigMap, trustedCAConfigMap, sec, set.Proxy, set.Infrastructure, customLogoCanMount, controllerContext.Recorder()) + actualDeployment, depChanged, depErrReason, depErr := co.SyncDeployment(ctx, set.Operator, cm, serviceCAConfigMap, oauthServingCertConfigMap, trustedCAConfigMap, sec, set.Proxy, set.Infrastructure, customLogoCanMount, canMountManagedClusterConfig, controllerContext.Recorder()) toUpdate = toUpdate || depChanged statusHandler.AddConditions(status.HandleProgressingOrDegraded("DeploymentSync", depErrReason, depErr)) if depErr != nil { @@ -241,10 +245,15 @@ func (co *consoleOperator) SyncDeployment( proxyConfig *configv1.Proxy, infrastructureConfig *configv1.Infrastructure, canMountCustomLogo bool, + canMountManagedClusterConfig bool, recorder events.Recorder) (consoleDeployment *appsv1.Deployment, changed bool, reason string, err error) { updatedOperatorConfig := operatorConfig.DeepCopy() - requiredDeployment := deploymentsub.DefaultDeployment(operatorConfig, cm, serviceCAConfigMap, oauthServingCertConfigMap, trustedCAConfigMap, sec, proxyConfig, infrastructureConfig, canMountCustomLogo) + apiServerCAConfigMaps, clusterCAConfigMapsErr := co.configMapClient.ConfigMaps(api.OpenShiftConsoleNamespace).List(ctx, metav1.ListOptions{LabelSelector: api.ManagedClusterAPIServerCAName}) + if clusterCAConfigMapsErr != nil { + klog.Warningf("Unable to list managed cluster API server CA bundle ConfigMaps. Multicluster will not be enabled: %v", clusterCAConfigMapsErr) + } + requiredDeployment := deploymentsub.DefaultDeployment(operatorConfig, cm, apiServerCAConfigMaps, serviceCAConfigMap, oauthServingCertConfigMap, trustedCAConfigMap, sec, proxyConfig, infrastructureConfig, canMountCustomLogo, canMountManagedClusterConfig) genChanged := operatorConfig.ObjectMeta.Generation != operatorConfig.Status.ObservedGeneration if genChanged { @@ -339,9 +348,8 @@ func (co *consoleOperator) SyncConfigMap( } } - pluginsEndpoingMap := co.GetPluginsEndpointMap(operatorConfig.Spec.Plugins) - - defaultConfigmap, _, err := configmapsub.DefaultConfigMap(operatorConfig, consoleConfig, managedConfig, infrastructureConfig, activeConsoleRoute, useDefaultCAFile, inactivityTimeoutSeconds, pluginsEndpoingMap) + pluginsEndpointMap := co.GetPluginsEndpointMap(operatorConfig.Spec.Plugins) + defaultConfigmap, _, err := configmapsub.DefaultConfigMap(operatorConfig, consoleConfig, managedConfig, infrastructureConfig, activeConsoleRoute, useDefaultCAFile, inactivityTimeoutSeconds, pluginsEndpointMap) if err != nil { return nil, false, "FailedConsoleConfigBuilder", err } @@ -356,6 +364,29 @@ func (co *consoleOperator) SyncConfigMap( return cm, cmChanged, "ConsoleConfigBuilder", cmErr } +func (co *consoleOperator) SyncManagedClusterConfigMap(ctx context.Context) (bool, string, error) { + managedClusterConfigMap, err := co.configMapClient.ConfigMaps(api.OpenShiftConsoleNamespace).Get(ctx, api.ManagedClusterConfigMapName, metav1.GetOptions{}) + // Not degraded if get fails because the config map isn't there + if apierrors.IsNotFound(err) { + klog.V(4).Infof("%v config map not found, continuing...", api.ManagedClusterConfigMapName) + return false, "", nil + } + + // Degraded if get fails for any other reason + if err != nil { + return false, "FailedGet", err + } + + // Degraded if managed cluster config map is present but doesn't have the correct data key + _, ok := managedClusterConfigMap.Data[api.ManagedClusterConfigKey] + if !ok { + return false, "MissingManagedClusterConfig", fmt.Errorf("%v ConfigMap is missing %v data key", api.ManagedClusterConfigMapName, api.ManagedClusterConfigKey) + } + + // Managed cluster config map is present and can be mounted + return true, "", nil +} + // apply service-ca configmap func (co *consoleOperator) SyncServiceCAConfigMap(ctx context.Context, operatorConfig *operatorv1.Console) (consoleCM *corev1.ConfigMap, changed bool, reason string, err error) { required := configmapsub.DefaultServiceCAConfigMap(operatorConfig) diff --git a/pkg/console/starter/starter.go b/pkg/console/starter/starter.go index 5fde3a2984..7c534b9326 100644 --- a/pkg/console/starter/starter.go +++ b/pkg/console/starter/starter.go @@ -21,6 +21,7 @@ import ( "github.com/openshift/console-operator/pkg/console/controllers/clidownloads" "github.com/openshift/console-operator/pkg/console/controllers/downloadsdeployment" "github.com/openshift/console-operator/pkg/console/controllers/healthcheck" + managedcluster "github.com/openshift/console-operator/pkg/console/controllers/managedclusters" "github.com/openshift/console-operator/pkg/console/controllers/route" "github.com/openshift/console-operator/pkg/console/controllers/service" "github.com/openshift/console-operator/pkg/console/operatorclient" @@ -49,6 +50,9 @@ import ( // consolev1client "github.com/openshift/client-go/console/clientset/versioned/typed/console/v1" consoleinformers "github.com/openshift/client-go/console/informers/externalversions" + clusterclient "github.com/open-cluster-management/api/client/cluster/clientset/versioned" + clusterinformers "github.com/open-cluster-management/api/client/cluster/informers/externalversions" + "github.com/openshift/console-operator/pkg/console/clientwrapper" "github.com/openshift/console-operator/pkg/console/operator" "github.com/openshift/library-go/pkg/operator/loglevel" @@ -86,6 +90,11 @@ func RunOperator(ctx context.Context, controllerContext *controllercmd.Controlle return err } + managedClusterClient, err := clusterclient.NewForConfig(controllerContext.KubeConfig) + if err != nil { + return err + } + const resync = 10 * time.Minute tweakListOptionsForOAuth := func(options *metav1.ListOptions) { @@ -139,6 +148,11 @@ func RunOperator(ctx context.Context, controllerContext *controllercmd.Controlle resync, ) + managedClusterInformers := clusterinformers.NewSharedInformerFactoryWithOptions( + managedClusterClient, + resync, + ) + operatorClient := &operatorclient.OperatorClient{ Informers: operatorConfigInformers, Client: operatorConfigClient.OperatorV1(), @@ -305,6 +319,22 @@ func RunOperator(ctx context.Context, controllerContext *controllercmd.Controlle recorder, ) + managedClusterController := managedcluster.NewManagedClusterController( + // top level config + configClient.ConfigV1(), + configInformers, + // clients + operatorClient, + operatorConfigClient.OperatorV1().Consoles(), + kubeClient.CoreV1(), + managedClusterClient.ClusterV1(), + // informers + operatorConfigInformers.Operator().V1().Consoles(), + managedClusterInformers.Cluster().V1().ManagedClusters(), + //events + recorder, + ) + versionRecorder := status.NewVersionGetter() versionRecorder.SetVersion("operator", os.Getenv("RELEASE_VERSION")) @@ -367,6 +397,7 @@ func RunOperator(ctx context.Context, controllerContext *controllercmd.Controlle configInformers, routesInformersNamespaced, oauthInformers, + managedClusterInformers, } { informer.Start(ctx.Done()) } @@ -383,6 +414,7 @@ func RunOperator(ctx context.Context, controllerContext *controllercmd.Controlle consoleRouteController, downloadsServiceController, downloadsRouteController, + managedClusterController, consoleOperator, cliDownloadsController, downloadsDeploymentController, diff --git a/pkg/console/subresource/configmap/api_server_ca.go b/pkg/console/subresource/configmap/api_server_ca.go new file mode 100644 index 0000000000..fc00c11f06 --- /dev/null +++ b/pkg/console/subresource/configmap/api_server_ca.go @@ -0,0 +1,45 @@ +package configmap + +import ( + "fmt" + + corev1 "k8s.io/api/core/v1" + + operatorv1 "github.com/openshift/api/operator/v1" + + "github.com/openshift/console-operator/pkg/api" + "github.com/openshift/console-operator/pkg/console/subresource/util" +) + +// DefaultServiceCAConfigMap creates a config map that holds the API server CA bundle for a managed cluster. +// Console uses this bundle to proxy to managed clusters. +func DefaultAPIServerCAConfigMap(clusterName string, caBundle []byte, cr *operatorv1.Console) *corev1.ConfigMap { + configMap := APIServerCAConfigMapStub(clusterName) + + if caBundle != nil { + configMap.Data = map[string]string{ + "ca.crt": string(caBundle), + } + } + + util.AddOwnerRef(configMap, util.OwnerRefFrom(cr)) + return configMap +} + +func APIServerCAConfigMapStub(clusterName string) *corev1.ConfigMap { + meta := util.SharedMeta() + meta.Name = APIServerCAConfigMapName(clusterName) + meta.Labels = map[string]string{ + api.ManagedClusterAPIServerCAName: "", + api.ManagedClusterLabel: clusterName, + "app": "console", + } + configMap := &corev1.ConfigMap{ + ObjectMeta: meta, + } + return configMap +} + +func APIServerCAConfigMapName(clusterName string) string { + return fmt.Sprintf("%s-%s", clusterName, api.ManagedClusterAPIServerCAName) +} diff --git a/pkg/console/subresource/configmap/api_server_ca_test.go b/pkg/console/subresource/configmap/api_server_ca_test.go new file mode 100644 index 0000000000..19f71609e4 --- /dev/null +++ b/pkg/console/subresource/configmap/api_server_ca_test.go @@ -0,0 +1,107 @@ +package configmap + +import ( + "testing" + + "github.com/go-test/deep" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + operatorv1 "github.com/openshift/api/operator/v1" + "github.com/openshift/console-operator/pkg/api" +) + +func TestDefaultAPIServerCAConfigMap(t *testing.T) { + type args struct { + clusterName string + caBundle []byte + cr *operatorv1.Console + } + tests := []struct { + name string + args args + want *corev1.ConfigMap + }{ + { + name: "Test default API server CA config map", + args: args{ + clusterName: "test-cluster", + caBundle: []byte("test-bundle"), + cr: &operatorv1.Console{ + TypeMeta: metav1.TypeMeta{}, + ObjectMeta: metav1.ObjectMeta{}, + Spec: operatorv1.ConsoleSpec{}, + Status: operatorv1.ConsoleStatus{}, + }, + }, + want: &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: APIServerCAConfigMapName("test-cluster"), + Namespace: api.OpenShiftConsoleNamespace, + Generation: 0, + CreationTimestamp: metav1.Time{}, + DeletionTimestamp: nil, + DeletionGracePeriodSeconds: nil, + Labels: map[string]string{api.ManagedClusterLabel: "test-cluster", api.ManagedClusterAPIServerCAName: "", "app": "console"}, + Annotations: map[string]string{}, + OwnerReferences: nil, + Finalizers: nil, + }, + Data: map[string]string{ + "ca.crt": "test-bundle", + }, + BinaryData: nil, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if diff := deep.Equal(DefaultAPIServerCAConfigMap(tt.args.clusterName, tt.args.caBundle, tt.args.cr), tt.want); diff != nil { + t.Error(diff) + } + }) + } +} + +func TestAPIServerCAStub(t *testing.T) { + type args struct { + clusterName string + } + tests := []struct { + name string + args args + want *corev1.ConfigMap + }{ + { + name: "Test stubbing API server CA config map", + args: args{ + clusterName: "test-cluster", + }, + want: &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{}, + ObjectMeta: metav1.ObjectMeta{ + Name: APIServerCAConfigMapName("test-cluster"), + Namespace: api.OpenShiftConsoleNamespace, + Generation: 0, + CreationTimestamp: metav1.Time{}, + DeletionTimestamp: nil, + DeletionGracePeriodSeconds: nil, + Labels: map[string]string{api.ManagedClusterLabel: "test-cluster", api.ManagedClusterAPIServerCAName: "", "app": "console"}, + Annotations: map[string]string{}, + OwnerReferences: nil, + Finalizers: nil, + }, + Data: nil, + BinaryData: nil, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if diff := deep.Equal(APIServerCAConfigMapStub(tt.args.clusterName), tt.want); diff != nil { + t.Error(diff) + } + }) + } +} diff --git a/pkg/console/subresource/configmap/configmap.go b/pkg/console/subresource/configmap/configmap.go index 700efeb487..da31d2799a 100644 --- a/pkg/console/subresource/configmap/configmap.go +++ b/pkg/console/subresource/configmap/configmap.go @@ -53,6 +53,7 @@ func DefaultConfigMap( OAuthServingCert(useDefaultCAFile). APIServerURL(getApiUrl(infrastructureConfig)). InactivityTimeout(inactivityTimeoutSeconds). + ManagedClusterConfigFile(fmt.Sprintf("%v/%v", api.ManagedClusterConfigMountDir, api.ManagedClusterConfigKey)). ConfigYAML() if err != nil { klog.Errorf("failed to generate default console-config config: %v", err) diff --git a/pkg/console/subresource/configmap/configmap_test.go b/pkg/console/subresource/configmap/configmap_test.go index 734d5a617a..18fe9dad3f 100644 --- a/pkg/console/subresource/configmap/configmap_test.go +++ b/pkg/console/subresource/configmap/configmap_test.go @@ -82,6 +82,7 @@ auth: clusterInfo: consoleBaseAddress: https://` + host + ` masterPublicURL: ` + mockAPIServer + ` +managedClusterConfigFile: /var/managed-cluster-config/managed-clusters.yaml customization: branding: ` + DEFAULT_BRAND + ` documentationBaseURL: ` + DEFAULT_DOC_URL + ` @@ -132,6 +133,7 @@ auth: clusterInfo: consoleBaseAddress: https://` + host + ` masterPublicURL: ` + mockAPIServer + ` +managedClusterConfigFile: /var/managed-cluster-config/managed-clusters.yaml customization: branding: ` + DEFAULT_BRAND + ` documentationBaseURL: ` + DEFAULT_DOC_URL + ` @@ -152,6 +154,7 @@ providers: {} managedConfig: &corev1.ConfigMap{ Data: map[string]string{configKey: `kind: ConsoleConfig apiVersion: console.openshift.io/v1 +managedClusterConfigFile: /var/managed-cluster-config/managed-clusters.yaml customization: branding: online documentationBaseURL: https://docs.okd.io/4.4/ @@ -190,8 +193,9 @@ auth: clusterInfo: consoleBaseAddress: https://` + host + ` masterPublicURL: ` + mockAPIServer + ` +managedClusterConfigFile: /var/managed-cluster-config/managed-clusters.yaml customization: - branding: online + branding: online documentationBaseURL: https://docs.okd.io/4.4/ servingInfo: bindAddress: https://[::]:8443 @@ -219,6 +223,7 @@ providers: {} managedConfig: &corev1.ConfigMap{ Data: map[string]string{configKey: `kind: ConsoleConfig apiVersion: console.openshift.io/v1 +managedClusterConfigFile: /var/managed-cluster-config/managed-clusters.yaml customization: branding: online documentationBaseURL: https://docs.okd.io/4.4/ @@ -257,6 +262,7 @@ auth: clusterInfo: consoleBaseAddress: https://` + host + ` masterPublicURL: ` + mockAPIServer + ` +managedClusterConfigFile: /var/managed-cluster-config/managed-clusters.yaml customization: branding: ` + string(operatorv1.BrandDedicated) + ` documentationBaseURL: ` + mockOperatorDocURL + ` @@ -291,6 +297,7 @@ providers: {} managedConfig: &corev1.ConfigMap{ Data: map[string]string{configKey: `kind: ConsoleConfig apiVersion: console.openshift.io/v1 +managedClusterConfigFile: /var/managed-cluster-config/managed-clusters.yaml customization: branding: online documentationBaseURL: https://docs.okd.io/4.4/ @@ -329,6 +336,7 @@ auth: clusterInfo: consoleBaseAddress: https://` + host + ` masterPublicURL: ` + mockAPIServer + ` +managedClusterConfigFile: /var/managed-cluster-config/managed-clusters.yaml customization: branding: ` + string(operatorv1.BrandDedicated) + ` documentationBaseURL: ` + mockOperatorDocURL + ` @@ -365,6 +373,7 @@ providers: {} managedConfig: &corev1.ConfigMap{ Data: map[string]string{configKey: `kind: ConsoleConfig apiVersion: console.openshift.io/v1 +managedClusterConfigFile: /var/managed-cluster-config/managed-clusters.yaml customization: branding: online documentationBaseURL: https://docs.okd.io/4.4/ @@ -403,6 +412,7 @@ auth: clusterInfo: consoleBaseAddress: https://` + host + ` masterPublicURL: ` + mockAPIServer + ` +managedClusterConfigFile: /var/managed-cluster-config/managed-clusters.yaml customization: branding: ` + string(operatorv1.BrandDedicated) + ` documentationBaseURL: ` + mockOperatorDocURL + ` @@ -410,7 +420,7 @@ servingInfo: bindAddress: https://[::]:8443 certFile: /var/serving-cert/tls.crt keyFile: /var/serving-cert/tls.key -providers: +providers: statuspageID: id-1234 `, }, @@ -460,6 +470,7 @@ auth: clusterInfo: consoleBaseAddress: https://` + customHostname + ` masterPublicURL: ` + mockAPIServer + ` +managedClusterConfigFile: /var/managed-cluster-config/managed-clusters.yaml customization: branding: ` + DEFAULT_BRAND + ` documentationBaseURL: ` + DEFAULT_DOC_URL + ` @@ -512,6 +523,7 @@ auth: clusterInfo: consoleBaseAddress: https://` + host + ` masterPublicURL: ` + mockAPIServer + ` +managedClusterConfigFile: /var/managed-cluster-config/managed-clusters.yaml customization: branding: ` + DEFAULT_BRAND + ` documentationBaseURL: ` + DEFAULT_DOC_URL + ` @@ -566,6 +578,7 @@ auth: clusterInfo: consoleBaseAddress: https://` + host + ` masterPublicURL: ` + mockAPIServer + ` +managedClusterConfigFile: /var/managed-cluster-config/managed-clusters.yaml customization: branding: ` + DEFAULT_BRAND + ` documentationBaseURL: ` + DEFAULT_DOC_URL + ` @@ -739,6 +752,7 @@ func Test_extractYAML(t *testing.T) { }, Data: map[string]string{configKey: `kind: ConsoleConfig apiVersion: console.openshift.io/v1 +managedClusterConfigFile: /var/managed-cluster-config/managed-clusters.yaml customization: branding: online documentationBaseURL: https://docs.okd.io/4.4/ @@ -749,6 +763,7 @@ customization: }, want: `kind: ConsoleConfig apiVersion: console.openshift.io/v1 +managedClusterConfigFile: /var/managed-cluster-config/managed-clusters.yaml customization: branding: online documentationBaseURL: https://docs.okd.io/4.4/ diff --git a/pkg/console/subresource/configmap/managed_clusters.go b/pkg/console/subresource/configmap/managed_clusters.go new file mode 100644 index 0000000000..04491e8e6b --- /dev/null +++ b/pkg/console/subresource/configmap/managed_clusters.go @@ -0,0 +1,41 @@ +package configmap + +import ( + "gopkg.in/yaml.v2" + corev1 "k8s.io/api/core/v1" + "k8s.io/klog/v2" + + operatorv1 "github.com/openshift/api/operator/v1" + "github.com/openshift/console-operator/pkg/api" + "github.com/openshift/console-operator/pkg/console/subresource/consoleserver" + "github.com/openshift/console-operator/pkg/console/subresource/util" +) + +func DefaultManagedClustersConfigMap(operatorConfig *operatorv1.Console, managedClusters []consoleserver.ManagedClusterConfig) (*corev1.ConfigMap, error) { + yml, err := yaml.Marshal(managedClusters) + if err != nil { + klog.V(4).Infof("Error marshalling managed clusters YAML: %v", err) + return nil, err + } + + configMap := ManagedClustersConfigMapStub() + configMap.Data = map[string]string{ + api.ManagedClusterConfigKey: string(yml), + } + util.AddOwnerRef(configMap, util.OwnerRefFrom(operatorConfig)) + + return configMap, nil +} + +func ManagedClustersConfigMapStub() *corev1.ConfigMap { + meta := util.SharedMeta() + meta.Name = api.ManagedClusterConfigMapName + meta.Labels = map[string]string{ + "app": "console", + api.ManagedClusterLabel: "", + } + configMap := &corev1.ConfigMap{ + ObjectMeta: meta, + } + return configMap +} diff --git a/pkg/console/subresource/configmap/managed_clusters_test.go b/pkg/console/subresource/configmap/managed_clusters_test.go new file mode 100644 index 0000000000..9562f92f09 --- /dev/null +++ b/pkg/console/subresource/configmap/managed_clusters_test.go @@ -0,0 +1,124 @@ +package configmap + +import ( + "testing" + + "github.com/go-test/deep" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + operatorv1 "github.com/openshift/api/operator/v1" + "github.com/openshift/console-operator/pkg/api" + "github.com/openshift/console-operator/pkg/console/subresource/consoleserver" +) + +var ( + testManagedClusterConfig consoleserver.ManagedClusterConfig = consoleserver.ManagedClusterConfig{ + Name: "test-cluster", + APIServer: consoleserver.ManagedClusterAPIServerConfig{ + URL: "test-url", + CAFile: "/var/api/ca", + }, + Oauth: consoleserver.ManagedClusterOAuthConfig{ + ClientID: "test-client-id", + ClientSecret: "test-client-secret", + CAFile: "/var/oauth/ca", + }, + } + testManagedClusterConfigYaml = `- name: test-cluster + apiServer: + url: test-url + caFile: /var/api/ca + oauth: + clientID: test-client-id + clientSecret: test-client-secret + caFile: /var/oauth/ca +` +) + +func TestDefaultManagedClustersConfigMap(t *testing.T) { + type args struct { + managedClusters []consoleserver.ManagedClusterConfig + cr *operatorv1.Console + } + tests := []struct { + name string + args args + want *corev1.ConfigMap + }{ + { + name: "Test default managed clusters config map", + args: args{ + managedClusters: []consoleserver.ManagedClusterConfig{testManagedClusterConfig}, + cr: &operatorv1.Console{ + TypeMeta: metav1.TypeMeta{}, + ObjectMeta: metav1.ObjectMeta{}, + Spec: operatorv1.ConsoleSpec{}, + Status: operatorv1.ConsoleStatus{}, + }, + }, + want: &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: api.ManagedClusterConfigMapName, + Namespace: api.OpenShiftConsoleNamespace, + Generation: 0, + CreationTimestamp: metav1.Time{}, + DeletionTimestamp: nil, + DeletionGracePeriodSeconds: nil, + Labels: map[string]string{"app": "console", api.ManagedClusterLabel: ""}, + Annotations: map[string]string{}, + OwnerReferences: nil, + Finalizers: nil, + }, + Data: map[string]string{ + api.ManagedClusterConfigKey: testManagedClusterConfigYaml, + }, + BinaryData: nil, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cm, _ := DefaultManagedClustersConfigMap(tt.args.cr, tt.args.managedClusters) + if diff := deep.Equal(cm, tt.want); diff != nil { + t.Error(diff) + } + }) + } +} + +func TestManagedClusterStub(t *testing.T) { + tests := []struct { + name string + want *corev1.ConfigMap + }{ + { + name: "Test stubbing managed clusters config map", + want: &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{}, + ObjectMeta: metav1.ObjectMeta{ + Name: api.ManagedClusterConfigMapName, + Namespace: api.OpenShiftConsoleNamespace, + Generation: 0, + CreationTimestamp: metav1.Time{}, + DeletionTimestamp: nil, + DeletionGracePeriodSeconds: nil, + Labels: map[string]string{"app": "console", api.ManagedClusterLabel: ""}, + Annotations: map[string]string{}, + OwnerReferences: nil, + Finalizers: nil, + }, + Data: nil, + BinaryData: nil, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if diff := deep.Equal(ManagedClustersConfigMapStub(), tt.want); diff != nil { + t.Error(diff) + } + }) + } +} diff --git a/pkg/console/subresource/consoleserver/config_builder.go b/pkg/console/subresource/consoleserver/config_builder.go index 06c3234417..03bd30555a 100644 --- a/pkg/console/subresource/consoleserver/config_builder.go +++ b/pkg/console/subresource/consoleserver/config_builder.go @@ -45,6 +45,7 @@ type ConsoleServerCLIConfigBuilder struct { customHostnameRedirectPort int inactivityTimeoutSeconds int pluginsList map[string]string + managedClusterConfigFile string } func (b *ConsoleServerCLIConfigBuilder) Host(host string) *ConsoleServerCLIConfigBuilder { @@ -126,16 +127,22 @@ func (b *ConsoleServerCLIConfigBuilder) Plugins(plugins map[string]string) *Cons return b } +func (b *ConsoleServerCLIConfigBuilder) ManagedClusterConfigFile(file string) *ConsoleServerCLIConfigBuilder { + b.managedClusterConfigFile = file + return b +} + func (b *ConsoleServerCLIConfigBuilder) Config() Config { return Config{ - Kind: "ConsoleConfig", - APIVersion: "console.openshift.io/v1", - Auth: b.auth(), - ClusterInfo: b.clusterInfo(), - Customization: b.customization(), - ServingInfo: b.servingInfo(), - Providers: b.providers(), - Plugins: b.plugins(), + Kind: "ConsoleConfig", + APIVersion: "console.openshift.io/v1", + Auth: b.auth(), + ClusterInfo: b.clusterInfo(), + Customization: b.customization(), + ServingInfo: b.servingInfo(), + Providers: b.providers(), + Plugins: b.plugins(), + ManagedClusterConfigFile: b.managedClusterConfigFile, } } diff --git a/pkg/console/subresource/consoleserver/types.go b/pkg/console/subresource/consoleserver/types.go index 405cad34bf..7db866fbf6 100644 --- a/pkg/console/subresource/consoleserver/types.go +++ b/pkg/console/subresource/consoleserver/types.go @@ -11,14 +11,15 @@ package consoleserver // Config is the top-level console server cli configuration. type Config struct { - APIVersion string `yaml:"apiVersion"` - Kind string `yaml:"kind"` - ServingInfo `yaml:"servingInfo"` - ClusterInfo `yaml:"clusterInfo"` - Auth `yaml:"auth"` - Customization `yaml:"customization"` - Providers `yaml:"providers"` - Plugins map[string]string `yaml:"plugins,omitempty"` + APIVersion string `yaml:"apiVersion"` + Kind string `yaml:"kind"` + ServingInfo `yaml:"servingInfo"` + ClusterInfo `yaml:"clusterInfo"` + Auth `yaml:"auth"` + Customization `yaml:"customization"` + Providers `yaml:"providers"` + Plugins map[string]string `yaml:"plugins,omitempty"` + ManagedClusterConfigFile string `yaml:"managedClusterConfigFile,omitempty"` } // ServingInfo holds configuration for serving HTTP. @@ -124,3 +125,23 @@ type HelmChartRepo struct { type Helm struct { ChartRepo HelmChartRepo `yaml:"chartRepository"` } + +// ManagedClusterAPIServerConfig enables proxying managed cluster API server requests +type ManagedClusterAPIServerConfig struct { + URL string `json:"url" yaml:"url"` + CAFile string `json:"caFile" yaml:"caFile"` +} + +// ManagedClusterOauthConfig enables proxying managed cluster auth +type ManagedClusterOAuthConfig struct { + ClientID string `json:"clientID" yaml:"clientID"` + ClientSecret string `json:"clientSecret" yaml:"clientSecret"` + CAFile string `json:"caFile" yaml:"caFile"` +} + +// ManagedClusterConfig enables proxying to an ACM managed cluster +type ManagedClusterConfig struct { + Name string `json:"name" yaml:"name"` // ManagedCluster name, provided through ACM + APIServer ManagedClusterAPIServerConfig `json:"apiServer" yaml:"apiServer"` + Oauth ManagedClusterOAuthConfig `json:"oauth" yaml:"oauth"` +} diff --git a/pkg/console/subresource/deployment/deployment.go b/pkg/console/subresource/deployment/deployment.go index d633f20c40..6c7002d858 100644 --- a/pkg/console/subresource/deployment/deployment.go +++ b/pkg/console/subresource/deployment/deployment.go @@ -61,13 +61,13 @@ type volumeConfig struct { mappedKeys map[string]string } -func DefaultDeployment(operatorConfig *operatorv1.Console, cm *corev1.ConfigMap, serviceCAConfigMap *corev1.ConfigMap, oauthServingCertConfigMap *corev1.ConfigMap, trustedCAConfigMap *corev1.ConfigMap, sec *corev1.Secret, proxyConfig *configv1.Proxy, infrastructureConfig *configv1.Infrastructure, canMountCustomLogo bool) *appsv1.Deployment { +func DefaultDeployment(operatorConfig *operatorv1.Console, cm *corev1.ConfigMap, apiServerCAConfigMaps *corev1.ConfigMapList, serviceCAConfigMap *corev1.ConfigMap, oauthServingCertConfigMap *corev1.ConfigMap, trustedCAConfigMap *corev1.ConfigMap, sec *corev1.Secret, proxyConfig *configv1.Proxy, infrastructureConfig *configv1.Infrastructure, canMountCustomLogo bool, canMountManagedClusterConfigMap bool) *appsv1.Deployment { deployment := resourceread.ReadDeploymentV1OrDie(assets.MustAsset("deployments/console-deployment.yaml")) withReplicas(deployment, infrastructureConfig) withAffinity(deployment, infrastructureConfig, "ui") withStrategy(deployment, infrastructureConfig) withConsoleAnnotations(deployment, cm, serviceCAConfigMap, oauthServingCertConfigMap, trustedCAConfigMap, sec, proxyConfig, infrastructureConfig) - withConsoleVolumes(deployment, trustedCAConfigMap, canMountCustomLogo) + withConsoleVolumes(deployment, trustedCAConfigMap, apiServerCAConfigMaps, canMountCustomLogo, canMountManagedClusterConfigMap) withConsoleContainerImage(deployment, operatorConfig, proxyConfig) withConsoleNodeSelector(deployment, infrastructureConfig) util.AddOwnerRef(deployment, util.OwnerRefFrom(operatorConfig)) @@ -148,7 +148,7 @@ func withConsoleAnnotations(deployment *appsv1.Deployment, cm *corev1.ConfigMap, deployment.Spec.Template.ObjectMeta.Annotations = podAnnotations } -func withConsoleVolumes(deployment *appsv1.Deployment, trustedCAConfigMap *corev1.ConfigMap, canMountCustomLogo bool) { +func withConsoleVolumes(deployment *appsv1.Deployment, trustedCAConfigMap *corev1.ConfigMap, apiServerCAConfigMaps *corev1.ConfigMapList, canMountCustomLogo bool, canMountManagedClusterConfigMap bool) { volumeConfig := defaultVolumeConfig() caBundle, caBundleExists := trustedCAConfigMap.Data["ca-bundle.crt"] @@ -158,6 +158,14 @@ func withConsoleVolumes(deployment *appsv1.Deployment, trustedCAConfigMap *corev if canMountCustomLogo { volumeConfig = append(volumeConfig, customLogoVolume()) } + if canMountManagedClusterConfigMap { + volumeConfig = append(volumeConfig, managedClusterVolumeConfig()) + } + if len(apiServerCAConfigMaps.Items) > 0 { + for _, apiServerCAConfigMap := range apiServerCAConfigMaps.Items { + volumeConfig = append(volumeConfig, apiServerCAVolumeConfig(apiServerCAConfigMap)) + } + } volMountList := make([]corev1.VolumeMount, len(volumeConfig)) for i, item := range volumeConfig { @@ -386,3 +394,22 @@ func customLogoVolume() volumeConfig { path: "/var/logo/", isConfigMap: true} } + +func managedClusterVolumeConfig() volumeConfig { + return volumeConfig{ + name: api.ManagedClusterConfigMapName, + path: api.ManagedClusterConfigMountDir, + readOnly: true, + isConfigMap: true, + } +} + +func apiServerCAVolumeConfig(configMap corev1.ConfigMap) volumeConfig { + name := configMap.GetName() + return volumeConfig{ + name: name, + path: fmt.Sprintf("%s/%s", api.ManagedClusterAPIServerCAMountDir, name), + readOnly: true, + isConfigMap: true, + } +} diff --git a/pkg/console/subresource/deployment/deployment_test.go b/pkg/console/subresource/deployment/deployment_test.go index 66d00be2ab..90b1d4231a 100644 --- a/pkg/console/subresource/deployment/deployment_test.go +++ b/pkg/console/subresource/deployment/deployment_test.go @@ -34,15 +34,17 @@ func TestDefaultDeployment(t *testing.T) { tolerationSeconds int64 = 120 ) type args struct { - config *operatorsv1.Console - cm *corev1.ConfigMap - ca *corev1.ConfigMap - dica *corev1.ConfigMap - tca *corev1.ConfigMap - sec *corev1.Secret - proxy *configv1.Proxy - infrastructure *configv1.Infrastructure - canMountCustomLogo bool + config *operatorsv1.Console + cm *corev1.ConfigMap + ccas *corev1.ConfigMapList + ca *corev1.ConfigMap + dica *corev1.ConfigMap + tca *corev1.ConfigMap + sec *corev1.Secret + proxy *configv1.Proxy + infrastructure *configv1.Infrastructure + canMountCustomLogo bool + canMountManagedClusterConfigMap bool } consoleOperatorConfig := &operatorsv1.Console{ @@ -176,10 +178,10 @@ func TestDefaultDeployment(t *testing.T) { consoleDeploymentTemplate := resourceread.ReadDeploymentV1OrDie(assets.MustAsset("deployments/console-deployment.yaml")) withConsoleContainerImage(consoleDeploymentTemplate, consoleOperatorConfig, proxyConfig) - withConsoleVolumes(consoleDeploymentTemplate, trustedCAConfigMapEmpty, false) + withConsoleVolumes(consoleDeploymentTemplate, trustedCAConfigMapEmpty, &corev1.ConfigMapList{}, false, false) consoleDeploymentContainer := consoleDeploymentTemplate.Spec.Template.Spec.Containers[0] consoleDeploymentVolumes := consoleDeploymentTemplate.Spec.Template.Spec.Volumes - withConsoleVolumes(consoleDeploymentTemplate, trustedCAConfigMapSet, false) + withConsoleVolumes(consoleDeploymentTemplate, trustedCAConfigMapSet, &corev1.ConfigMapList{}, false, false) consoleDeploymentContainerTrusted := consoleDeploymentTemplate.Spec.Template.Spec.Containers[0] consoleDeploymentVolumesTrusted := consoleDeploymentTemplate.Spec.Template.Spec.Volumes @@ -193,6 +195,7 @@ func TestDefaultDeployment(t *testing.T) { args: args{ config: consoleOperatorConfig, cm: consoleConfig, + ccas: &corev1.ConfigMapList{}, ca: &corev1.ConfigMap{}, dica: &corev1.ConfigMap{ Data: map[string]string{"ca-bundle.crt": "test"}, @@ -270,6 +273,7 @@ func TestDefaultDeployment(t *testing.T) { args: args{ config: consoleOperatorConfig, cm: consoleConfig, + ccas: &corev1.ConfigMapList{}, ca: &corev1.ConfigMap{}, dica: &corev1.ConfigMap{ Data: map[string]string{"ca-bundle.crt": "test"}, @@ -346,6 +350,7 @@ func TestDefaultDeployment(t *testing.T) { args: args{ config: consoleOperatorConfig, cm: consoleConfig, + ccas: &corev1.ConfigMapList{}, ca: &corev1.ConfigMap{}, dica: &corev1.ConfigMap{ Data: map[string]string{"ca-bundle.crt": "test"}, @@ -415,6 +420,7 @@ func TestDefaultDeployment(t *testing.T) { args: args{ config: consoleOperatorConfig, cm: consoleConfig, + ccas: &corev1.ConfigMapList{}, ca: &corev1.ConfigMap{}, dica: &corev1.ConfigMap{ Data: map[string]string{"ca-bundle.crt": "test"}, @@ -486,7 +492,7 @@ func TestDefaultDeployment(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if diff := deep.Equal(DefaultDeployment(tt.args.config, tt.args.cm, tt.args.dica, tt.args.cm, tt.args.tca, tt.args.sec, tt.args.proxy, tt.args.infrastructure, tt.args.canMountCustomLogo), tt.want); diff != nil { + if diff := deep.Equal(DefaultDeployment(tt.args.config, tt.args.cm, tt.args.ccas, tt.args.dica, tt.args.cm, tt.args.tca, tt.args.sec, tt.args.proxy, tt.args.infrastructure, tt.args.canMountCustomLogo, tt.args.canMountManagedClusterConfigMap), tt.want); diff != nil { t.Error(diff) } }) @@ -1053,7 +1059,7 @@ func TestWithConsoleVolumes(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - withConsoleVolumes(tt.args.deployment, tt.args.trustedCAConfigMap, tt.args.canMountCustomLogo) + withConsoleVolumes(tt.args.deployment, tt.args.trustedCAConfigMap, &corev1.ConfigMapList{}, tt.args.canMountCustomLogo, false) if diff := deep.Equal(tt.args.deployment, tt.want); diff != nil { t.Error(diff) } diff --git a/vendor/github.com/open-cluster-management/api/LICENSE b/vendor/github.com/open-cluster-management/api/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/clientset.go b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/clientset.go new file mode 100644 index 0000000000..43e8819bfd --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/clientset.go @@ -0,0 +1,95 @@ +// Code generated by client-gen. DO NOT EDIT. + +package versioned + +import ( + "fmt" + + clusterv1 "github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1" + clusterv1alpha1 "github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1" + discovery "k8s.io/client-go/discovery" + rest "k8s.io/client-go/rest" + flowcontrol "k8s.io/client-go/util/flowcontrol" +) + +type Interface interface { + Discovery() discovery.DiscoveryInterface + ClusterV1() clusterv1.ClusterV1Interface + ClusterV1alpha1() clusterv1alpha1.ClusterV1alpha1Interface +} + +// Clientset contains the clients for groups. Each group has exactly one +// version included in a Clientset. +type Clientset struct { + *discovery.DiscoveryClient + clusterV1 *clusterv1.ClusterV1Client + clusterV1alpha1 *clusterv1alpha1.ClusterV1alpha1Client +} + +// ClusterV1 retrieves the ClusterV1Client +func (c *Clientset) ClusterV1() clusterv1.ClusterV1Interface { + return c.clusterV1 +} + +// ClusterV1alpha1 retrieves the ClusterV1alpha1Client +func (c *Clientset) ClusterV1alpha1() clusterv1alpha1.ClusterV1alpha1Interface { + return c.clusterV1alpha1 +} + +// Discovery retrieves the DiscoveryClient +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + if c == nil { + return nil + } + return c.DiscoveryClient +} + +// NewForConfig creates a new Clientset for the given config. +// If config's RateLimiter is not set and QPS and Burst are acceptable, +// NewForConfig will generate a rate-limiter in configShallowCopy. +func NewForConfig(c *rest.Config) (*Clientset, error) { + configShallowCopy := *c + if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { + if configShallowCopy.Burst <= 0 { + return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0") + } + configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) + } + var cs Clientset + var err error + cs.clusterV1, err = clusterv1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.clusterV1alpha1, err = clusterv1alpha1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + + cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + return &cs, nil +} + +// NewForConfigOrDie creates a new Clientset for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *Clientset { + var cs Clientset + cs.clusterV1 = clusterv1.NewForConfigOrDie(c) + cs.clusterV1alpha1 = clusterv1alpha1.NewForConfigOrDie(c) + + cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c) + return &cs +} + +// New creates a new Clientset for the given RESTClient. +func New(c rest.Interface) *Clientset { + var cs Clientset + cs.clusterV1 = clusterv1.New(c) + cs.clusterV1alpha1 = clusterv1alpha1.New(c) + + cs.DiscoveryClient = discovery.NewDiscoveryClient(c) + return &cs +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/doc.go b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/doc.go new file mode 100644 index 0000000000..0e0c2a8900 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/doc.go @@ -0,0 +1,4 @@ +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated clientset. +package versioned diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/scheme/doc.go b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/scheme/doc.go new file mode 100644 index 0000000000..14db57a58f --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/scheme/doc.go @@ -0,0 +1,4 @@ +// Code generated by client-gen. DO NOT EDIT. + +// This package contains the scheme of the automatically generated clientset. +package scheme diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/scheme/register.go b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/scheme/register.go new file mode 100644 index 0000000000..9400e7090c --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/scheme/register.go @@ -0,0 +1,42 @@ +// Code generated by client-gen. DO NOT EDIT. + +package scheme + +import ( + clusterv1 "github.com/open-cluster-management/api/cluster/v1" + clusterv1alpha1 "github.com/open-cluster-management/api/cluster/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" +) + +var Scheme = runtime.NewScheme() +var Codecs = serializer.NewCodecFactory(Scheme) +var ParameterCodec = runtime.NewParameterCodec(Scheme) +var localSchemeBuilder = runtime.SchemeBuilder{ + clusterv1.AddToScheme, + clusterv1alpha1.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(Scheme)) +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1/cluster_client.go b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1/cluster_client.go new file mode 100644 index 0000000000..46fa0341d6 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1/cluster_client.go @@ -0,0 +1,73 @@ +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + "github.com/open-cluster-management/api/client/cluster/clientset/versioned/scheme" + v1 "github.com/open-cluster-management/api/cluster/v1" + rest "k8s.io/client-go/rest" +) + +type ClusterV1Interface interface { + RESTClient() rest.Interface + ManagedClustersGetter +} + +// ClusterV1Client is used to interact with features provided by the cluster.open-cluster-management.io group. +type ClusterV1Client struct { + restClient rest.Interface +} + +func (c *ClusterV1Client) ManagedClusters() ManagedClusterInterface { + return newManagedClusters(c) +} + +// NewForConfig creates a new ClusterV1Client for the given config. +func NewForConfig(c *rest.Config) (*ClusterV1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &ClusterV1Client{client}, nil +} + +// NewForConfigOrDie creates a new ClusterV1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *ClusterV1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new ClusterV1Client for the given RESTClient. +func New(c rest.Interface) *ClusterV1Client { + return &ClusterV1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *ClusterV1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1/doc.go b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1/doc.go new file mode 100644 index 0000000000..225e6b2be3 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1/doc.go @@ -0,0 +1,4 @@ +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1 diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1/generated_expansion.go b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1/generated_expansion.go new file mode 100644 index 0000000000..4985a7a4d6 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1/generated_expansion.go @@ -0,0 +1,5 @@ +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +type ManagedClusterExpansion interface{} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1/managedcluster.go b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1/managedcluster.go new file mode 100644 index 0000000000..1a52b68134 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1/managedcluster.go @@ -0,0 +1,168 @@ +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + "time" + + scheme "github.com/open-cluster-management/api/client/cluster/clientset/versioned/scheme" + v1 "github.com/open-cluster-management/api/cluster/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// ManagedClustersGetter has a method to return a ManagedClusterInterface. +// A group's client should implement this interface. +type ManagedClustersGetter interface { + ManagedClusters() ManagedClusterInterface +} + +// ManagedClusterInterface has methods to work with ManagedCluster resources. +type ManagedClusterInterface interface { + Create(ctx context.Context, managedCluster *v1.ManagedCluster, opts metav1.CreateOptions) (*v1.ManagedCluster, error) + Update(ctx context.Context, managedCluster *v1.ManagedCluster, opts metav1.UpdateOptions) (*v1.ManagedCluster, error) + UpdateStatus(ctx context.Context, managedCluster *v1.ManagedCluster, opts metav1.UpdateOptions) (*v1.ManagedCluster, error) + Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error + Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.ManagedCluster, error) + List(ctx context.Context, opts metav1.ListOptions) (*v1.ManagedClusterList, error) + Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.ManagedCluster, err error) + ManagedClusterExpansion +} + +// managedClusters implements ManagedClusterInterface +type managedClusters struct { + client rest.Interface +} + +// newManagedClusters returns a ManagedClusters +func newManagedClusters(c *ClusterV1Client) *managedClusters { + return &managedClusters{ + client: c.RESTClient(), + } +} + +// Get takes name of the managedCluster, and returns the corresponding managedCluster object, and an error if there is any. +func (c *managedClusters) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.ManagedCluster, err error) { + result = &v1.ManagedCluster{} + err = c.client.Get(). + Resource("managedclusters"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ManagedClusters that match those selectors. +func (c *managedClusters) List(ctx context.Context, opts metav1.ListOptions) (result *v1.ManagedClusterList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1.ManagedClusterList{} + err = c.client.Get(). + Resource("managedclusters"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested managedClusters. +func (c *managedClusters) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("managedclusters"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a managedCluster and creates it. Returns the server's representation of the managedCluster, and an error, if there is any. +func (c *managedClusters) Create(ctx context.Context, managedCluster *v1.ManagedCluster, opts metav1.CreateOptions) (result *v1.ManagedCluster, err error) { + result = &v1.ManagedCluster{} + err = c.client.Post(). + Resource("managedclusters"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(managedCluster). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a managedCluster and updates it. Returns the server's representation of the managedCluster, and an error, if there is any. +func (c *managedClusters) Update(ctx context.Context, managedCluster *v1.ManagedCluster, opts metav1.UpdateOptions) (result *v1.ManagedCluster, err error) { + result = &v1.ManagedCluster{} + err = c.client.Put(). + Resource("managedclusters"). + Name(managedCluster.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(managedCluster). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *managedClusters) UpdateStatus(ctx context.Context, managedCluster *v1.ManagedCluster, opts metav1.UpdateOptions) (result *v1.ManagedCluster, err error) { + result = &v1.ManagedCluster{} + err = c.client.Put(). + Resource("managedclusters"). + Name(managedCluster.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(managedCluster). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the managedCluster and deletes it. Returns an error if one occurs. +func (c *managedClusters) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { + return c.client.Delete(). + Resource("managedclusters"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *managedClusters) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("managedclusters"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched managedCluster. +func (c *managedClusters) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.ManagedCluster, err error) { + result = &v1.ManagedCluster{} + err = c.client.Patch(pt). + Resource("managedclusters"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/cluster_client.go b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/cluster_client.go new file mode 100644 index 0000000000..aa835a2d4d --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/cluster_client.go @@ -0,0 +1,93 @@ +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "github.com/open-cluster-management/api/client/cluster/clientset/versioned/scheme" + v1alpha1 "github.com/open-cluster-management/api/cluster/v1alpha1" + rest "k8s.io/client-go/rest" +) + +type ClusterV1alpha1Interface interface { + RESTClient() rest.Interface + ClusterClaimsGetter + ManagedClusterSetsGetter + ManagedClusterSetBindingsGetter + PlacementsGetter + PlacementDecisionsGetter +} + +// ClusterV1alpha1Client is used to interact with features provided by the cluster.open-cluster-management.io group. +type ClusterV1alpha1Client struct { + restClient rest.Interface +} + +func (c *ClusterV1alpha1Client) ClusterClaims() ClusterClaimInterface { + return newClusterClaims(c) +} + +func (c *ClusterV1alpha1Client) ManagedClusterSets() ManagedClusterSetInterface { + return newManagedClusterSets(c) +} + +func (c *ClusterV1alpha1Client) ManagedClusterSetBindings(namespace string) ManagedClusterSetBindingInterface { + return newManagedClusterSetBindings(c, namespace) +} + +func (c *ClusterV1alpha1Client) Placements(namespace string) PlacementInterface { + return newPlacements(c, namespace) +} + +func (c *ClusterV1alpha1Client) PlacementDecisions(namespace string) PlacementDecisionInterface { + return newPlacementDecisions(c, namespace) +} + +// NewForConfig creates a new ClusterV1alpha1Client for the given config. +func NewForConfig(c *rest.Config) (*ClusterV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &ClusterV1alpha1Client{client}, nil +} + +// NewForConfigOrDie creates a new ClusterV1alpha1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *ClusterV1alpha1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new ClusterV1alpha1Client for the given RESTClient. +func New(c rest.Interface) *ClusterV1alpha1Client { + return &ClusterV1alpha1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1alpha1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *ClusterV1alpha1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/clusterclaim.go b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/clusterclaim.go new file mode 100644 index 0000000000..387cc09db8 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/clusterclaim.go @@ -0,0 +1,152 @@ +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + "time" + + scheme "github.com/open-cluster-management/api/client/cluster/clientset/versioned/scheme" + v1alpha1 "github.com/open-cluster-management/api/cluster/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// ClusterClaimsGetter has a method to return a ClusterClaimInterface. +// A group's client should implement this interface. +type ClusterClaimsGetter interface { + ClusterClaims() ClusterClaimInterface +} + +// ClusterClaimInterface has methods to work with ClusterClaim resources. +type ClusterClaimInterface interface { + Create(ctx context.Context, clusterClaim *v1alpha1.ClusterClaim, opts v1.CreateOptions) (*v1alpha1.ClusterClaim, error) + Update(ctx context.Context, clusterClaim *v1alpha1.ClusterClaim, opts v1.UpdateOptions) (*v1alpha1.ClusterClaim, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ClusterClaim, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ClusterClaimList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ClusterClaim, err error) + ClusterClaimExpansion +} + +// clusterClaims implements ClusterClaimInterface +type clusterClaims struct { + client rest.Interface +} + +// newClusterClaims returns a ClusterClaims +func newClusterClaims(c *ClusterV1alpha1Client) *clusterClaims { + return &clusterClaims{ + client: c.RESTClient(), + } +} + +// Get takes name of the clusterClaim, and returns the corresponding clusterClaim object, and an error if there is any. +func (c *clusterClaims) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ClusterClaim, err error) { + result = &v1alpha1.ClusterClaim{} + err = c.client.Get(). + Resource("clusterclaims"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ClusterClaims that match those selectors. +func (c *clusterClaims) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ClusterClaimList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.ClusterClaimList{} + err = c.client.Get(). + Resource("clusterclaims"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested clusterClaims. +func (c *clusterClaims) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("clusterclaims"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a clusterClaim and creates it. Returns the server's representation of the clusterClaim, and an error, if there is any. +func (c *clusterClaims) Create(ctx context.Context, clusterClaim *v1alpha1.ClusterClaim, opts v1.CreateOptions) (result *v1alpha1.ClusterClaim, err error) { + result = &v1alpha1.ClusterClaim{} + err = c.client.Post(). + Resource("clusterclaims"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(clusterClaim). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a clusterClaim and updates it. Returns the server's representation of the clusterClaim, and an error, if there is any. +func (c *clusterClaims) Update(ctx context.Context, clusterClaim *v1alpha1.ClusterClaim, opts v1.UpdateOptions) (result *v1alpha1.ClusterClaim, err error) { + result = &v1alpha1.ClusterClaim{} + err = c.client.Put(). + Resource("clusterclaims"). + Name(clusterClaim.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(clusterClaim). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the clusterClaim and deletes it. Returns an error if one occurs. +func (c *clusterClaims) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Resource("clusterclaims"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *clusterClaims) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("clusterclaims"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched clusterClaim. +func (c *clusterClaims) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ClusterClaim, err error) { + result = &v1alpha1.ClusterClaim{} + err = c.client.Patch(pt). + Resource("clusterclaims"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/doc.go b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/doc.go new file mode 100644 index 0000000000..93a7ca4e0e --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/doc.go @@ -0,0 +1,4 @@ +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1alpha1 diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/generated_expansion.go b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/generated_expansion.go new file mode 100644 index 0000000000..457dafc99a --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/generated_expansion.go @@ -0,0 +1,13 @@ +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +type ClusterClaimExpansion interface{} + +type ManagedClusterSetExpansion interface{} + +type ManagedClusterSetBindingExpansion interface{} + +type PlacementExpansion interface{} + +type PlacementDecisionExpansion interface{} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/managedclusterset.go b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/managedclusterset.go new file mode 100644 index 0000000000..6bb4069096 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/managedclusterset.go @@ -0,0 +1,168 @@ +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + "time" + + scheme "github.com/open-cluster-management/api/client/cluster/clientset/versioned/scheme" + v1alpha1 "github.com/open-cluster-management/api/cluster/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// ManagedClusterSetsGetter has a method to return a ManagedClusterSetInterface. +// A group's client should implement this interface. +type ManagedClusterSetsGetter interface { + ManagedClusterSets() ManagedClusterSetInterface +} + +// ManagedClusterSetInterface has methods to work with ManagedClusterSet resources. +type ManagedClusterSetInterface interface { + Create(ctx context.Context, managedClusterSet *v1alpha1.ManagedClusterSet, opts v1.CreateOptions) (*v1alpha1.ManagedClusterSet, error) + Update(ctx context.Context, managedClusterSet *v1alpha1.ManagedClusterSet, opts v1.UpdateOptions) (*v1alpha1.ManagedClusterSet, error) + UpdateStatus(ctx context.Context, managedClusterSet *v1alpha1.ManagedClusterSet, opts v1.UpdateOptions) (*v1alpha1.ManagedClusterSet, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ManagedClusterSet, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ManagedClusterSetList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ManagedClusterSet, err error) + ManagedClusterSetExpansion +} + +// managedClusterSets implements ManagedClusterSetInterface +type managedClusterSets struct { + client rest.Interface +} + +// newManagedClusterSets returns a ManagedClusterSets +func newManagedClusterSets(c *ClusterV1alpha1Client) *managedClusterSets { + return &managedClusterSets{ + client: c.RESTClient(), + } +} + +// Get takes name of the managedClusterSet, and returns the corresponding managedClusterSet object, and an error if there is any. +func (c *managedClusterSets) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ManagedClusterSet, err error) { + result = &v1alpha1.ManagedClusterSet{} + err = c.client.Get(). + Resource("managedclustersets"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ManagedClusterSets that match those selectors. +func (c *managedClusterSets) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ManagedClusterSetList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.ManagedClusterSetList{} + err = c.client.Get(). + Resource("managedclustersets"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested managedClusterSets. +func (c *managedClusterSets) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("managedclustersets"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a managedClusterSet and creates it. Returns the server's representation of the managedClusterSet, and an error, if there is any. +func (c *managedClusterSets) Create(ctx context.Context, managedClusterSet *v1alpha1.ManagedClusterSet, opts v1.CreateOptions) (result *v1alpha1.ManagedClusterSet, err error) { + result = &v1alpha1.ManagedClusterSet{} + err = c.client.Post(). + Resource("managedclustersets"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(managedClusterSet). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a managedClusterSet and updates it. Returns the server's representation of the managedClusterSet, and an error, if there is any. +func (c *managedClusterSets) Update(ctx context.Context, managedClusterSet *v1alpha1.ManagedClusterSet, opts v1.UpdateOptions) (result *v1alpha1.ManagedClusterSet, err error) { + result = &v1alpha1.ManagedClusterSet{} + err = c.client.Put(). + Resource("managedclustersets"). + Name(managedClusterSet.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(managedClusterSet). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *managedClusterSets) UpdateStatus(ctx context.Context, managedClusterSet *v1alpha1.ManagedClusterSet, opts v1.UpdateOptions) (result *v1alpha1.ManagedClusterSet, err error) { + result = &v1alpha1.ManagedClusterSet{} + err = c.client.Put(). + Resource("managedclustersets"). + Name(managedClusterSet.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(managedClusterSet). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the managedClusterSet and deletes it. Returns an error if one occurs. +func (c *managedClusterSets) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Resource("managedclustersets"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *managedClusterSets) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("managedclustersets"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched managedClusterSet. +func (c *managedClusterSets) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ManagedClusterSet, err error) { + result = &v1alpha1.ManagedClusterSet{} + err = c.client.Patch(pt). + Resource("managedclustersets"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/managedclustersetbinding.go b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/managedclustersetbinding.go new file mode 100644 index 0000000000..5357d6aeac --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/managedclustersetbinding.go @@ -0,0 +1,162 @@ +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + "time" + + scheme "github.com/open-cluster-management/api/client/cluster/clientset/versioned/scheme" + v1alpha1 "github.com/open-cluster-management/api/cluster/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// ManagedClusterSetBindingsGetter has a method to return a ManagedClusterSetBindingInterface. +// A group's client should implement this interface. +type ManagedClusterSetBindingsGetter interface { + ManagedClusterSetBindings(namespace string) ManagedClusterSetBindingInterface +} + +// ManagedClusterSetBindingInterface has methods to work with ManagedClusterSetBinding resources. +type ManagedClusterSetBindingInterface interface { + Create(ctx context.Context, managedClusterSetBinding *v1alpha1.ManagedClusterSetBinding, opts v1.CreateOptions) (*v1alpha1.ManagedClusterSetBinding, error) + Update(ctx context.Context, managedClusterSetBinding *v1alpha1.ManagedClusterSetBinding, opts v1.UpdateOptions) (*v1alpha1.ManagedClusterSetBinding, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ManagedClusterSetBinding, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ManagedClusterSetBindingList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ManagedClusterSetBinding, err error) + ManagedClusterSetBindingExpansion +} + +// managedClusterSetBindings implements ManagedClusterSetBindingInterface +type managedClusterSetBindings struct { + client rest.Interface + ns string +} + +// newManagedClusterSetBindings returns a ManagedClusterSetBindings +func newManagedClusterSetBindings(c *ClusterV1alpha1Client, namespace string) *managedClusterSetBindings { + return &managedClusterSetBindings{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the managedClusterSetBinding, and returns the corresponding managedClusterSetBinding object, and an error if there is any. +func (c *managedClusterSetBindings) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ManagedClusterSetBinding, err error) { + result = &v1alpha1.ManagedClusterSetBinding{} + err = c.client.Get(). + Namespace(c.ns). + Resource("managedclustersetbindings"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ManagedClusterSetBindings that match those selectors. +func (c *managedClusterSetBindings) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ManagedClusterSetBindingList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.ManagedClusterSetBindingList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("managedclustersetbindings"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested managedClusterSetBindings. +func (c *managedClusterSetBindings) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("managedclustersetbindings"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a managedClusterSetBinding and creates it. Returns the server's representation of the managedClusterSetBinding, and an error, if there is any. +func (c *managedClusterSetBindings) Create(ctx context.Context, managedClusterSetBinding *v1alpha1.ManagedClusterSetBinding, opts v1.CreateOptions) (result *v1alpha1.ManagedClusterSetBinding, err error) { + result = &v1alpha1.ManagedClusterSetBinding{} + err = c.client.Post(). + Namespace(c.ns). + Resource("managedclustersetbindings"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(managedClusterSetBinding). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a managedClusterSetBinding and updates it. Returns the server's representation of the managedClusterSetBinding, and an error, if there is any. +func (c *managedClusterSetBindings) Update(ctx context.Context, managedClusterSetBinding *v1alpha1.ManagedClusterSetBinding, opts v1.UpdateOptions) (result *v1alpha1.ManagedClusterSetBinding, err error) { + result = &v1alpha1.ManagedClusterSetBinding{} + err = c.client.Put(). + Namespace(c.ns). + Resource("managedclustersetbindings"). + Name(managedClusterSetBinding.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(managedClusterSetBinding). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the managedClusterSetBinding and deletes it. Returns an error if one occurs. +func (c *managedClusterSetBindings) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("managedclustersetbindings"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *managedClusterSetBindings) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("managedclustersetbindings"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched managedClusterSetBinding. +func (c *managedClusterSetBindings) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ManagedClusterSetBinding, err error) { + result = &v1alpha1.ManagedClusterSetBinding{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("managedclustersetbindings"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/placement.go b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/placement.go new file mode 100644 index 0000000000..4cc87e4f37 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/placement.go @@ -0,0 +1,179 @@ +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + "time" + + scheme "github.com/open-cluster-management/api/client/cluster/clientset/versioned/scheme" + v1alpha1 "github.com/open-cluster-management/api/cluster/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// PlacementsGetter has a method to return a PlacementInterface. +// A group's client should implement this interface. +type PlacementsGetter interface { + Placements(namespace string) PlacementInterface +} + +// PlacementInterface has methods to work with Placement resources. +type PlacementInterface interface { + Create(ctx context.Context, placement *v1alpha1.Placement, opts v1.CreateOptions) (*v1alpha1.Placement, error) + Update(ctx context.Context, placement *v1alpha1.Placement, opts v1.UpdateOptions) (*v1alpha1.Placement, error) + UpdateStatus(ctx context.Context, placement *v1alpha1.Placement, opts v1.UpdateOptions) (*v1alpha1.Placement, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.Placement, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.PlacementList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.Placement, err error) + PlacementExpansion +} + +// placements implements PlacementInterface +type placements struct { + client rest.Interface + ns string +} + +// newPlacements returns a Placements +func newPlacements(c *ClusterV1alpha1Client, namespace string) *placements { + return &placements{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the placement, and returns the corresponding placement object, and an error if there is any. +func (c *placements) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.Placement, err error) { + result = &v1alpha1.Placement{} + err = c.client.Get(). + Namespace(c.ns). + Resource("placements"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of Placements that match those selectors. +func (c *placements) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.PlacementList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.PlacementList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("placements"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested placements. +func (c *placements) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("placements"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a placement and creates it. Returns the server's representation of the placement, and an error, if there is any. +func (c *placements) Create(ctx context.Context, placement *v1alpha1.Placement, opts v1.CreateOptions) (result *v1alpha1.Placement, err error) { + result = &v1alpha1.Placement{} + err = c.client.Post(). + Namespace(c.ns). + Resource("placements"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(placement). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a placement and updates it. Returns the server's representation of the placement, and an error, if there is any. +func (c *placements) Update(ctx context.Context, placement *v1alpha1.Placement, opts v1.UpdateOptions) (result *v1alpha1.Placement, err error) { + result = &v1alpha1.Placement{} + err = c.client.Put(). + Namespace(c.ns). + Resource("placements"). + Name(placement.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(placement). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *placements) UpdateStatus(ctx context.Context, placement *v1alpha1.Placement, opts v1.UpdateOptions) (result *v1alpha1.Placement, err error) { + result = &v1alpha1.Placement{} + err = c.client.Put(). + Namespace(c.ns). + Resource("placements"). + Name(placement.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(placement). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the placement and deletes it. Returns an error if one occurs. +func (c *placements) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("placements"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *placements) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("placements"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched placement. +func (c *placements) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.Placement, err error) { + result = &v1alpha1.Placement{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("placements"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/placementdecision.go b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/placementdecision.go new file mode 100644 index 0000000000..627760d5d0 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1/placementdecision.go @@ -0,0 +1,179 @@ +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + "time" + + scheme "github.com/open-cluster-management/api/client/cluster/clientset/versioned/scheme" + v1alpha1 "github.com/open-cluster-management/api/cluster/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// PlacementDecisionsGetter has a method to return a PlacementDecisionInterface. +// A group's client should implement this interface. +type PlacementDecisionsGetter interface { + PlacementDecisions(namespace string) PlacementDecisionInterface +} + +// PlacementDecisionInterface has methods to work with PlacementDecision resources. +type PlacementDecisionInterface interface { + Create(ctx context.Context, placementDecision *v1alpha1.PlacementDecision, opts v1.CreateOptions) (*v1alpha1.PlacementDecision, error) + Update(ctx context.Context, placementDecision *v1alpha1.PlacementDecision, opts v1.UpdateOptions) (*v1alpha1.PlacementDecision, error) + UpdateStatus(ctx context.Context, placementDecision *v1alpha1.PlacementDecision, opts v1.UpdateOptions) (*v1alpha1.PlacementDecision, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.PlacementDecision, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.PlacementDecisionList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.PlacementDecision, err error) + PlacementDecisionExpansion +} + +// placementDecisions implements PlacementDecisionInterface +type placementDecisions struct { + client rest.Interface + ns string +} + +// newPlacementDecisions returns a PlacementDecisions +func newPlacementDecisions(c *ClusterV1alpha1Client, namespace string) *placementDecisions { + return &placementDecisions{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the placementDecision, and returns the corresponding placementDecision object, and an error if there is any. +func (c *placementDecisions) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.PlacementDecision, err error) { + result = &v1alpha1.PlacementDecision{} + err = c.client.Get(). + Namespace(c.ns). + Resource("placementdecisions"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of PlacementDecisions that match those selectors. +func (c *placementDecisions) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.PlacementDecisionList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.PlacementDecisionList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("placementdecisions"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested placementDecisions. +func (c *placementDecisions) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("placementdecisions"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a placementDecision and creates it. Returns the server's representation of the placementDecision, and an error, if there is any. +func (c *placementDecisions) Create(ctx context.Context, placementDecision *v1alpha1.PlacementDecision, opts v1.CreateOptions) (result *v1alpha1.PlacementDecision, err error) { + result = &v1alpha1.PlacementDecision{} + err = c.client.Post(). + Namespace(c.ns). + Resource("placementdecisions"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(placementDecision). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a placementDecision and updates it. Returns the server's representation of the placementDecision, and an error, if there is any. +func (c *placementDecisions) Update(ctx context.Context, placementDecision *v1alpha1.PlacementDecision, opts v1.UpdateOptions) (result *v1alpha1.PlacementDecision, err error) { + result = &v1alpha1.PlacementDecision{} + err = c.client.Put(). + Namespace(c.ns). + Resource("placementdecisions"). + Name(placementDecision.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(placementDecision). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *placementDecisions) UpdateStatus(ctx context.Context, placementDecision *v1alpha1.PlacementDecision, opts v1.UpdateOptions) (result *v1alpha1.PlacementDecision, err error) { + result = &v1alpha1.PlacementDecision{} + err = c.client.Put(). + Namespace(c.ns). + Resource("placementdecisions"). + Name(placementDecision.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(placementDecision). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the placementDecision and deletes it. Returns an error if one occurs. +func (c *placementDecisions) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("placementdecisions"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *placementDecisions) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("placementdecisions"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched placementDecision. +func (c *placementDecisions) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.PlacementDecision, err error) { + result = &v1alpha1.PlacementDecision{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("placementdecisions"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/interface.go b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/interface.go new file mode 100644 index 0000000000..fcb5281fdc --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/interface.go @@ -0,0 +1,38 @@ +// Code generated by informer-gen. DO NOT EDIT. + +package cluster + +import ( + v1 "github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1" + v1alpha1 "github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1" + internalinterfaces "github.com/open-cluster-management/api/client/cluster/informers/externalversions/internalinterfaces" +) + +// Interface provides access to each of this group's versions. +type Interface interface { + // V1 provides access to shared informers for resources in V1. + V1() v1.Interface + // V1alpha1 provides access to shared informers for resources in V1alpha1. + V1alpha1() v1alpha1.Interface +} + +type group struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// V1 returns a new v1.Interface. +func (g *group) V1() v1.Interface { + return v1.New(g.factory, g.namespace, g.tweakListOptions) +} + +// V1alpha1 returns a new v1alpha1.Interface. +func (g *group) V1alpha1() v1alpha1.Interface { + return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1/interface.go b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1/interface.go new file mode 100644 index 0000000000..3d9438231b --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1/interface.go @@ -0,0 +1,29 @@ +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + internalinterfaces "github.com/open-cluster-management/api/client/cluster/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // ManagedClusters returns a ManagedClusterInformer. + ManagedClusters() ManagedClusterInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// ManagedClusters returns a ManagedClusterInformer. +func (v *version) ManagedClusters() ManagedClusterInformer { + return &managedClusterInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1/managedcluster.go b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1/managedcluster.go new file mode 100644 index 0000000000..c63fb90a92 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1/managedcluster.go @@ -0,0 +1,73 @@ +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + time "time" + + versioned "github.com/open-cluster-management/api/client/cluster/clientset/versioned" + internalinterfaces "github.com/open-cluster-management/api/client/cluster/informers/externalversions/internalinterfaces" + v1 "github.com/open-cluster-management/api/client/cluster/listers/cluster/v1" + clusterv1 "github.com/open-cluster-management/api/cluster/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// ManagedClusterInformer provides access to a shared informer and lister for +// ManagedClusters. +type ManagedClusterInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.ManagedClusterLister +} + +type managedClusterInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewManagedClusterInformer constructs a new informer for ManagedCluster type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewManagedClusterInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredManagedClusterInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredManagedClusterInformer constructs a new informer for ManagedCluster type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredManagedClusterInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ClusterV1().ManagedClusters().List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ClusterV1().ManagedClusters().Watch(context.TODO(), options) + }, + }, + &clusterv1.ManagedCluster{}, + resyncPeriod, + indexers, + ) +} + +func (f *managedClusterInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredManagedClusterInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *managedClusterInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&clusterv1.ManagedCluster{}, f.defaultInformer) +} + +func (f *managedClusterInformer) Lister() v1.ManagedClusterLister { + return v1.NewManagedClusterLister(f.Informer().GetIndexer()) +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/clusterclaim.go b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/clusterclaim.go new file mode 100644 index 0000000000..f0b4aade96 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/clusterclaim.go @@ -0,0 +1,73 @@ +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + versioned "github.com/open-cluster-management/api/client/cluster/clientset/versioned" + internalinterfaces "github.com/open-cluster-management/api/client/cluster/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1" + clusterv1alpha1 "github.com/open-cluster-management/api/cluster/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// ClusterClaimInformer provides access to a shared informer and lister for +// ClusterClaims. +type ClusterClaimInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.ClusterClaimLister +} + +type clusterClaimInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewClusterClaimInformer constructs a new informer for ClusterClaim type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewClusterClaimInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredClusterClaimInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredClusterClaimInformer constructs a new informer for ClusterClaim type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredClusterClaimInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ClusterV1alpha1().ClusterClaims().List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ClusterV1alpha1().ClusterClaims().Watch(context.TODO(), options) + }, + }, + &clusterv1alpha1.ClusterClaim{}, + resyncPeriod, + indexers, + ) +} + +func (f *clusterClaimInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredClusterClaimInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *clusterClaimInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&clusterv1alpha1.ClusterClaim{}, f.defaultInformer) +} + +func (f *clusterClaimInformer) Lister() v1alpha1.ClusterClaimLister { + return v1alpha1.NewClusterClaimLister(f.Informer().GetIndexer()) +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/interface.go b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/interface.go new file mode 100644 index 0000000000..facb7869b0 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/interface.go @@ -0,0 +1,57 @@ +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + internalinterfaces "github.com/open-cluster-management/api/client/cluster/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // ClusterClaims returns a ClusterClaimInformer. + ClusterClaims() ClusterClaimInformer + // ManagedClusterSets returns a ManagedClusterSetInformer. + ManagedClusterSets() ManagedClusterSetInformer + // ManagedClusterSetBindings returns a ManagedClusterSetBindingInformer. + ManagedClusterSetBindings() ManagedClusterSetBindingInformer + // Placements returns a PlacementInformer. + Placements() PlacementInformer + // PlacementDecisions returns a PlacementDecisionInformer. + PlacementDecisions() PlacementDecisionInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// ClusterClaims returns a ClusterClaimInformer. +func (v *version) ClusterClaims() ClusterClaimInformer { + return &clusterClaimInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} + +// ManagedClusterSets returns a ManagedClusterSetInformer. +func (v *version) ManagedClusterSets() ManagedClusterSetInformer { + return &managedClusterSetInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} + +// ManagedClusterSetBindings returns a ManagedClusterSetBindingInformer. +func (v *version) ManagedClusterSetBindings() ManagedClusterSetBindingInformer { + return &managedClusterSetBindingInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// Placements returns a PlacementInformer. +func (v *version) Placements() PlacementInformer { + return &placementInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// PlacementDecisions returns a PlacementDecisionInformer. +func (v *version) PlacementDecisions() PlacementDecisionInformer { + return &placementDecisionInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/managedclusterset.go b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/managedclusterset.go new file mode 100644 index 0000000000..6c38d63d31 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/managedclusterset.go @@ -0,0 +1,73 @@ +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + versioned "github.com/open-cluster-management/api/client/cluster/clientset/versioned" + internalinterfaces "github.com/open-cluster-management/api/client/cluster/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1" + clusterv1alpha1 "github.com/open-cluster-management/api/cluster/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// ManagedClusterSetInformer provides access to a shared informer and lister for +// ManagedClusterSets. +type ManagedClusterSetInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.ManagedClusterSetLister +} + +type managedClusterSetInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewManagedClusterSetInformer constructs a new informer for ManagedClusterSet type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewManagedClusterSetInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredManagedClusterSetInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredManagedClusterSetInformer constructs a new informer for ManagedClusterSet type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredManagedClusterSetInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ClusterV1alpha1().ManagedClusterSets().List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ClusterV1alpha1().ManagedClusterSets().Watch(context.TODO(), options) + }, + }, + &clusterv1alpha1.ManagedClusterSet{}, + resyncPeriod, + indexers, + ) +} + +func (f *managedClusterSetInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredManagedClusterSetInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *managedClusterSetInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&clusterv1alpha1.ManagedClusterSet{}, f.defaultInformer) +} + +func (f *managedClusterSetInformer) Lister() v1alpha1.ManagedClusterSetLister { + return v1alpha1.NewManagedClusterSetLister(f.Informer().GetIndexer()) +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/managedclustersetbinding.go b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/managedclustersetbinding.go new file mode 100644 index 0000000000..9063d8fde0 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/managedclustersetbinding.go @@ -0,0 +1,74 @@ +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + versioned "github.com/open-cluster-management/api/client/cluster/clientset/versioned" + internalinterfaces "github.com/open-cluster-management/api/client/cluster/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1" + clusterv1alpha1 "github.com/open-cluster-management/api/cluster/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// ManagedClusterSetBindingInformer provides access to a shared informer and lister for +// ManagedClusterSetBindings. +type ManagedClusterSetBindingInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.ManagedClusterSetBindingLister +} + +type managedClusterSetBindingInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewManagedClusterSetBindingInformer constructs a new informer for ManagedClusterSetBinding type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewManagedClusterSetBindingInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredManagedClusterSetBindingInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredManagedClusterSetBindingInformer constructs a new informer for ManagedClusterSetBinding type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredManagedClusterSetBindingInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ClusterV1alpha1().ManagedClusterSetBindings(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ClusterV1alpha1().ManagedClusterSetBindings(namespace).Watch(context.TODO(), options) + }, + }, + &clusterv1alpha1.ManagedClusterSetBinding{}, + resyncPeriod, + indexers, + ) +} + +func (f *managedClusterSetBindingInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredManagedClusterSetBindingInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *managedClusterSetBindingInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&clusterv1alpha1.ManagedClusterSetBinding{}, f.defaultInformer) +} + +func (f *managedClusterSetBindingInformer) Lister() v1alpha1.ManagedClusterSetBindingLister { + return v1alpha1.NewManagedClusterSetBindingLister(f.Informer().GetIndexer()) +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/placement.go b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/placement.go new file mode 100644 index 0000000000..b4e6268455 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/placement.go @@ -0,0 +1,74 @@ +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + versioned "github.com/open-cluster-management/api/client/cluster/clientset/versioned" + internalinterfaces "github.com/open-cluster-management/api/client/cluster/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1" + clusterv1alpha1 "github.com/open-cluster-management/api/cluster/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// PlacementInformer provides access to a shared informer and lister for +// Placements. +type PlacementInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.PlacementLister +} + +type placementInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewPlacementInformer constructs a new informer for Placement type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewPlacementInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredPlacementInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredPlacementInformer constructs a new informer for Placement type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredPlacementInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ClusterV1alpha1().Placements(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ClusterV1alpha1().Placements(namespace).Watch(context.TODO(), options) + }, + }, + &clusterv1alpha1.Placement{}, + resyncPeriod, + indexers, + ) +} + +func (f *placementInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredPlacementInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *placementInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&clusterv1alpha1.Placement{}, f.defaultInformer) +} + +func (f *placementInformer) Lister() v1alpha1.PlacementLister { + return v1alpha1.NewPlacementLister(f.Informer().GetIndexer()) +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/placementdecision.go b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/placementdecision.go new file mode 100644 index 0000000000..5dcb0ba995 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1/placementdecision.go @@ -0,0 +1,74 @@ +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + versioned "github.com/open-cluster-management/api/client/cluster/clientset/versioned" + internalinterfaces "github.com/open-cluster-management/api/client/cluster/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1" + clusterv1alpha1 "github.com/open-cluster-management/api/cluster/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// PlacementDecisionInformer provides access to a shared informer and lister for +// PlacementDecisions. +type PlacementDecisionInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.PlacementDecisionLister +} + +type placementDecisionInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewPlacementDecisionInformer constructs a new informer for PlacementDecision type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewPlacementDecisionInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredPlacementDecisionInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredPlacementDecisionInformer constructs a new informer for PlacementDecision type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredPlacementDecisionInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ClusterV1alpha1().PlacementDecisions(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ClusterV1alpha1().PlacementDecisions(namespace).Watch(context.TODO(), options) + }, + }, + &clusterv1alpha1.PlacementDecision{}, + resyncPeriod, + indexers, + ) +} + +func (f *placementDecisionInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredPlacementDecisionInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *placementDecisionInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&clusterv1alpha1.PlacementDecision{}, f.defaultInformer) +} + +func (f *placementDecisionInformer) Lister() v1alpha1.PlacementDecisionLister { + return v1alpha1.NewPlacementDecisionLister(f.Informer().GetIndexer()) +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/factory.go b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/factory.go new file mode 100644 index 0000000000..85441ed359 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/factory.go @@ -0,0 +1,164 @@ +// Code generated by informer-gen. DO NOT EDIT. + +package externalversions + +import ( + reflect "reflect" + sync "sync" + time "time" + + versioned "github.com/open-cluster-management/api/client/cluster/clientset/versioned" + cluster "github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster" + internalinterfaces "github.com/open-cluster-management/api/client/cluster/informers/externalversions/internalinterfaces" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" +) + +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + +type sharedInformerFactory struct { + client versioned.Interface + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc + lock sync.Mutex + defaultResync time.Duration + customResync map[reflect.Type]time.Duration + + informers map[reflect.Type]cache.SharedIndexInformer + // startedInformers is used for tracking which informers have been started. + // This allows Start() to be called multiple times safely. + startedInformers map[reflect.Type]bool +} + +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. +func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync) +} + +// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. +// Listers obtained via this SharedInformerFactory will be subject to the same filters +// as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead +func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ + client: client, + namespace: v1.NamespaceAll, + defaultResync: defaultResync, + informers: make(map[reflect.Type]cache.SharedIndexInformer), + startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) + } + + return factory +} + +// Start initializes all requested informers. +func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { + f.lock.Lock() + defer f.lock.Unlock() + + for informerType, informer := range f.informers { + if !f.startedInformers[informerType] { + go informer.Run(stopCh) + f.startedInformers[informerType] = true + } + } +} + +// WaitForCacheSync waits for all started informers' cache were synced. +func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { + informers := func() map[reflect.Type]cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informers := map[reflect.Type]cache.SharedIndexInformer{} + for informerType, informer := range f.informers { + if f.startedInformers[informerType] { + informers[informerType] = informer + } + } + return informers + }() + + res := map[reflect.Type]bool{} + for informType, informer := range informers { + res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced) + } + return res +} + +// InternalInformerFor returns the SharedIndexInformer for obj using an internal +// client. +func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informerType := reflect.TypeOf(obj) + informer, exists := f.informers[informerType] + if exists { + return informer + } + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) + f.informers[informerType] = informer + + return informer +} + +// SharedInformerFactory provides shared informers for resources in all known +// API group versions. +type SharedInformerFactory interface { + internalinterfaces.SharedInformerFactory + ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + + Cluster() cluster.Interface +} + +func (f *sharedInformerFactory) Cluster() cluster.Interface { + return cluster.New(f, f.namespace, f.tweakListOptions) +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/generic.go b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/generic.go new file mode 100644 index 0000000000..0a4db5ea0e --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/generic.go @@ -0,0 +1,59 @@ +// Code generated by informer-gen. DO NOT EDIT. + +package externalversions + +import ( + "fmt" + + v1 "github.com/open-cluster-management/api/cluster/v1" + v1alpha1 "github.com/open-cluster-management/api/cluster/v1alpha1" + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" +) + +// GenericInformer is type of SharedIndexInformer which will locate and delegate to other +// sharedInformers based on type +type GenericInformer interface { + Informer() cache.SharedIndexInformer + Lister() cache.GenericLister +} + +type genericInformer struct { + informer cache.SharedIndexInformer + resource schema.GroupResource +} + +// Informer returns the SharedIndexInformer. +func (f *genericInformer) Informer() cache.SharedIndexInformer { + return f.informer +} + +// Lister returns the GenericLister. +func (f *genericInformer) Lister() cache.GenericLister { + return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) +} + +// ForResource gives generic access to a shared informer of the matching type +// TODO extend this to unknown resources with a client pool +func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { + switch resource { + // Group=cluster.open-cluster-management.io, Version=v1 + case v1.SchemeGroupVersion.WithResource("managedclusters"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Cluster().V1().ManagedClusters().Informer()}, nil + + // Group=cluster.open-cluster-management.io, Version=v1alpha1 + case v1alpha1.SchemeGroupVersion.WithResource("clusterclaims"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Cluster().V1alpha1().ClusterClaims().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("managedclustersets"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Cluster().V1alpha1().ManagedClusterSets().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("managedclustersetbindings"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Cluster().V1alpha1().ManagedClusterSetBindings().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("placements"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Cluster().V1alpha1().Placements().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("placementdecisions"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Cluster().V1alpha1().PlacementDecisions().Informer()}, nil + + } + + return nil, fmt.Errorf("no informer found for %v", resource) +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/internalinterfaces/factory_interfaces.go b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/internalinterfaces/factory_interfaces.go new file mode 100644 index 0000000000..82af2636e9 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -0,0 +1,24 @@ +// Code generated by informer-gen. DO NOT EDIT. + +package internalinterfaces + +import ( + time "time" + + versioned "github.com/open-cluster-management/api/client/cluster/clientset/versioned" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + cache "k8s.io/client-go/tools/cache" +) + +// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. +type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer + +// SharedInformerFactory a small interface to allow for adding an informer without an import cycle +type SharedInformerFactory interface { + Start(stopCh <-chan struct{}) + InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer +} + +// TweakListOptionsFunc is a function that transforms a v1.ListOptions. +type TweakListOptionsFunc func(*v1.ListOptions) diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1/expansion_generated.go b/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1/expansion_generated.go new file mode 100644 index 0000000000..9b200e963b --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1/expansion_generated.go @@ -0,0 +1,7 @@ +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +// ManagedClusterListerExpansion allows custom methods to be added to +// ManagedClusterLister. +type ManagedClusterListerExpansion interface{} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1/managedcluster.go b/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1/managedcluster.go new file mode 100644 index 0000000000..eeb80fe155 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1/managedcluster.go @@ -0,0 +1,52 @@ +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +import ( + v1 "github.com/open-cluster-management/api/cluster/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// ManagedClusterLister helps list ManagedClusters. +// All objects returned here must be treated as read-only. +type ManagedClusterLister interface { + // List lists all ManagedClusters in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1.ManagedCluster, err error) + // Get retrieves the ManagedCluster from the index for a given name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1.ManagedCluster, error) + ManagedClusterListerExpansion +} + +// managedClusterLister implements the ManagedClusterLister interface. +type managedClusterLister struct { + indexer cache.Indexer +} + +// NewManagedClusterLister returns a new ManagedClusterLister. +func NewManagedClusterLister(indexer cache.Indexer) ManagedClusterLister { + return &managedClusterLister{indexer: indexer} +} + +// List lists all ManagedClusters in the indexer. +func (s *managedClusterLister) List(selector labels.Selector) (ret []*v1.ManagedCluster, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1.ManagedCluster)) + }) + return ret, err +} + +// Get retrieves the ManagedCluster from the index for a given name. +func (s *managedClusterLister) Get(name string) (*v1.ManagedCluster, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1.Resource("managedcluster"), name) + } + return obj.(*v1.ManagedCluster), nil +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/clusterclaim.go b/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/clusterclaim.go new file mode 100644 index 0000000000..94a4d940b5 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/clusterclaim.go @@ -0,0 +1,52 @@ +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/open-cluster-management/api/cluster/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// ClusterClaimLister helps list ClusterClaims. +// All objects returned here must be treated as read-only. +type ClusterClaimLister interface { + // List lists all ClusterClaims in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.ClusterClaim, err error) + // Get retrieves the ClusterClaim from the index for a given name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.ClusterClaim, error) + ClusterClaimListerExpansion +} + +// clusterClaimLister implements the ClusterClaimLister interface. +type clusterClaimLister struct { + indexer cache.Indexer +} + +// NewClusterClaimLister returns a new ClusterClaimLister. +func NewClusterClaimLister(indexer cache.Indexer) ClusterClaimLister { + return &clusterClaimLister{indexer: indexer} +} + +// List lists all ClusterClaims in the indexer. +func (s *clusterClaimLister) List(selector labels.Selector) (ret []*v1alpha1.ClusterClaim, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ClusterClaim)) + }) + return ret, err +} + +// Get retrieves the ClusterClaim from the index for a given name. +func (s *clusterClaimLister) Get(name string) (*v1alpha1.ClusterClaim, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("clusterclaim"), name) + } + return obj.(*v1alpha1.ClusterClaim), nil +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/expansion_generated.go b/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/expansion_generated.go new file mode 100644 index 0000000000..2a82995cc6 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/expansion_generated.go @@ -0,0 +1,35 @@ +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +// ClusterClaimListerExpansion allows custom methods to be added to +// ClusterClaimLister. +type ClusterClaimListerExpansion interface{} + +// ManagedClusterSetListerExpansion allows custom methods to be added to +// ManagedClusterSetLister. +type ManagedClusterSetListerExpansion interface{} + +// ManagedClusterSetBindingListerExpansion allows custom methods to be added to +// ManagedClusterSetBindingLister. +type ManagedClusterSetBindingListerExpansion interface{} + +// ManagedClusterSetBindingNamespaceListerExpansion allows custom methods to be added to +// ManagedClusterSetBindingNamespaceLister. +type ManagedClusterSetBindingNamespaceListerExpansion interface{} + +// PlacementListerExpansion allows custom methods to be added to +// PlacementLister. +type PlacementListerExpansion interface{} + +// PlacementNamespaceListerExpansion allows custom methods to be added to +// PlacementNamespaceLister. +type PlacementNamespaceListerExpansion interface{} + +// PlacementDecisionListerExpansion allows custom methods to be added to +// PlacementDecisionLister. +type PlacementDecisionListerExpansion interface{} + +// PlacementDecisionNamespaceListerExpansion allows custom methods to be added to +// PlacementDecisionNamespaceLister. +type PlacementDecisionNamespaceListerExpansion interface{} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/managedclusterset.go b/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/managedclusterset.go new file mode 100644 index 0000000000..a3a3fe2ac1 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/managedclusterset.go @@ -0,0 +1,52 @@ +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/open-cluster-management/api/cluster/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// ManagedClusterSetLister helps list ManagedClusterSets. +// All objects returned here must be treated as read-only. +type ManagedClusterSetLister interface { + // List lists all ManagedClusterSets in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.ManagedClusterSet, err error) + // Get retrieves the ManagedClusterSet from the index for a given name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.ManagedClusterSet, error) + ManagedClusterSetListerExpansion +} + +// managedClusterSetLister implements the ManagedClusterSetLister interface. +type managedClusterSetLister struct { + indexer cache.Indexer +} + +// NewManagedClusterSetLister returns a new ManagedClusterSetLister. +func NewManagedClusterSetLister(indexer cache.Indexer) ManagedClusterSetLister { + return &managedClusterSetLister{indexer: indexer} +} + +// List lists all ManagedClusterSets in the indexer. +func (s *managedClusterSetLister) List(selector labels.Selector) (ret []*v1alpha1.ManagedClusterSet, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ManagedClusterSet)) + }) + return ret, err +} + +// Get retrieves the ManagedClusterSet from the index for a given name. +func (s *managedClusterSetLister) Get(name string) (*v1alpha1.ManagedClusterSet, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("managedclusterset"), name) + } + return obj.(*v1alpha1.ManagedClusterSet), nil +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/managedclustersetbinding.go b/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/managedclustersetbinding.go new file mode 100644 index 0000000000..bb4eb01f03 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/managedclustersetbinding.go @@ -0,0 +1,83 @@ +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/open-cluster-management/api/cluster/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// ManagedClusterSetBindingLister helps list ManagedClusterSetBindings. +// All objects returned here must be treated as read-only. +type ManagedClusterSetBindingLister interface { + // List lists all ManagedClusterSetBindings in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.ManagedClusterSetBinding, err error) + // ManagedClusterSetBindings returns an object that can list and get ManagedClusterSetBindings. + ManagedClusterSetBindings(namespace string) ManagedClusterSetBindingNamespaceLister + ManagedClusterSetBindingListerExpansion +} + +// managedClusterSetBindingLister implements the ManagedClusterSetBindingLister interface. +type managedClusterSetBindingLister struct { + indexer cache.Indexer +} + +// NewManagedClusterSetBindingLister returns a new ManagedClusterSetBindingLister. +func NewManagedClusterSetBindingLister(indexer cache.Indexer) ManagedClusterSetBindingLister { + return &managedClusterSetBindingLister{indexer: indexer} +} + +// List lists all ManagedClusterSetBindings in the indexer. +func (s *managedClusterSetBindingLister) List(selector labels.Selector) (ret []*v1alpha1.ManagedClusterSetBinding, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ManagedClusterSetBinding)) + }) + return ret, err +} + +// ManagedClusterSetBindings returns an object that can list and get ManagedClusterSetBindings. +func (s *managedClusterSetBindingLister) ManagedClusterSetBindings(namespace string) ManagedClusterSetBindingNamespaceLister { + return managedClusterSetBindingNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// ManagedClusterSetBindingNamespaceLister helps list and get ManagedClusterSetBindings. +// All objects returned here must be treated as read-only. +type ManagedClusterSetBindingNamespaceLister interface { + // List lists all ManagedClusterSetBindings in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.ManagedClusterSetBinding, err error) + // Get retrieves the ManagedClusterSetBinding from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.ManagedClusterSetBinding, error) + ManagedClusterSetBindingNamespaceListerExpansion +} + +// managedClusterSetBindingNamespaceLister implements the ManagedClusterSetBindingNamespaceLister +// interface. +type managedClusterSetBindingNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all ManagedClusterSetBindings in the indexer for a given namespace. +func (s managedClusterSetBindingNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.ManagedClusterSetBinding, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ManagedClusterSetBinding)) + }) + return ret, err +} + +// Get retrieves the ManagedClusterSetBinding from the indexer for a given namespace and name. +func (s managedClusterSetBindingNamespaceLister) Get(name string) (*v1alpha1.ManagedClusterSetBinding, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("managedclustersetbinding"), name) + } + return obj.(*v1alpha1.ManagedClusterSetBinding), nil +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/placement.go b/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/placement.go new file mode 100644 index 0000000000..8b472af9f9 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/placement.go @@ -0,0 +1,83 @@ +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/open-cluster-management/api/cluster/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// PlacementLister helps list Placements. +// All objects returned here must be treated as read-only. +type PlacementLister interface { + // List lists all Placements in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.Placement, err error) + // Placements returns an object that can list and get Placements. + Placements(namespace string) PlacementNamespaceLister + PlacementListerExpansion +} + +// placementLister implements the PlacementLister interface. +type placementLister struct { + indexer cache.Indexer +} + +// NewPlacementLister returns a new PlacementLister. +func NewPlacementLister(indexer cache.Indexer) PlacementLister { + return &placementLister{indexer: indexer} +} + +// List lists all Placements in the indexer. +func (s *placementLister) List(selector labels.Selector) (ret []*v1alpha1.Placement, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.Placement)) + }) + return ret, err +} + +// Placements returns an object that can list and get Placements. +func (s *placementLister) Placements(namespace string) PlacementNamespaceLister { + return placementNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// PlacementNamespaceLister helps list and get Placements. +// All objects returned here must be treated as read-only. +type PlacementNamespaceLister interface { + // List lists all Placements in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.Placement, err error) + // Get retrieves the Placement from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.Placement, error) + PlacementNamespaceListerExpansion +} + +// placementNamespaceLister implements the PlacementNamespaceLister +// interface. +type placementNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all Placements in the indexer for a given namespace. +func (s placementNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.Placement, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.Placement)) + }) + return ret, err +} + +// Get retrieves the Placement from the indexer for a given namespace and name. +func (s placementNamespaceLister) Get(name string) (*v1alpha1.Placement, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("placement"), name) + } + return obj.(*v1alpha1.Placement), nil +} diff --git a/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/placementdecision.go b/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/placementdecision.go new file mode 100644 index 0000000000..0fb84728f5 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1/placementdecision.go @@ -0,0 +1,83 @@ +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/open-cluster-management/api/cluster/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// PlacementDecisionLister helps list PlacementDecisions. +// All objects returned here must be treated as read-only. +type PlacementDecisionLister interface { + // List lists all PlacementDecisions in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.PlacementDecision, err error) + // PlacementDecisions returns an object that can list and get PlacementDecisions. + PlacementDecisions(namespace string) PlacementDecisionNamespaceLister + PlacementDecisionListerExpansion +} + +// placementDecisionLister implements the PlacementDecisionLister interface. +type placementDecisionLister struct { + indexer cache.Indexer +} + +// NewPlacementDecisionLister returns a new PlacementDecisionLister. +func NewPlacementDecisionLister(indexer cache.Indexer) PlacementDecisionLister { + return &placementDecisionLister{indexer: indexer} +} + +// List lists all PlacementDecisions in the indexer. +func (s *placementDecisionLister) List(selector labels.Selector) (ret []*v1alpha1.PlacementDecision, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.PlacementDecision)) + }) + return ret, err +} + +// PlacementDecisions returns an object that can list and get PlacementDecisions. +func (s *placementDecisionLister) PlacementDecisions(namespace string) PlacementDecisionNamespaceLister { + return placementDecisionNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// PlacementDecisionNamespaceLister helps list and get PlacementDecisions. +// All objects returned here must be treated as read-only. +type PlacementDecisionNamespaceLister interface { + // List lists all PlacementDecisions in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.PlacementDecision, err error) + // Get retrieves the PlacementDecision from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.PlacementDecision, error) + PlacementDecisionNamespaceListerExpansion +} + +// placementDecisionNamespaceLister implements the PlacementDecisionNamespaceLister +// interface. +type placementDecisionNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all PlacementDecisions in the indexer for a given namespace. +func (s placementDecisionNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.PlacementDecision, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.PlacementDecision)) + }) + return ret, err +} + +// Get retrieves the PlacementDecision from the indexer for a given namespace and name. +func (s placementDecisionNamespaceLister) Get(name string) (*v1alpha1.PlacementDecision, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("placementdecision"), name) + } + return obj.(*v1alpha1.PlacementDecision), nil +} diff --git a/vendor/github.com/open-cluster-management/api/cluster/v1/0000_00_clusters.open-cluster-management.io_managedclusters.crd.yaml b/vendor/github.com/open-cluster-management/api/cluster/v1/0000_00_clusters.open-cluster-management.io_managedclusters.crd.yaml new file mode 100644 index 0000000000..cb876560ac --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/cluster/v1/0000_00_clusters.open-cluster-management.io_managedclusters.crd.yaml @@ -0,0 +1,244 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: managedclusters.cluster.open-cluster-management.io +spec: + group: cluster.open-cluster-management.io + names: + kind: ManagedCluster + listKind: ManagedClusterList + plural: managedclusters + shortNames: + - mcl + - mcls + singular: managedcluster + scope: Cluster + preserveUnknownFields: false + versions: + - additionalPrinterColumns: + - jsonPath: .spec.hubAcceptsClient + name: Hub Accepted + type: boolean + - jsonPath: .spec.managedClusterClientConfigs[*].url + name: Managed Cluster URLs + type: string + - jsonPath: .status.conditions[?(@.type=="ManagedClusterJoined")].status + name: Joined + type: string + - jsonPath: .status.conditions[?(@.type=="ManagedClusterConditionAvailable")].status + name: Available + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: "ManagedCluster represents the desired state and current status + of managed cluster. ManagedCluster is a cluster scoped resource. The name + is the cluster UID. \n The cluster join process follows a double opt-in + process: \n 1. Agent on managed cluster creates CSR on hub with cluster + UID and agent name. 2. Agent on managed cluster creates ManagedCluster on + hub. 3. Cluster admin on hub approves the CSR for UID and agent name of + the ManagedCluster. 4. Cluster admin sets spec.acceptClient of ManagedCluster + to true. 5. Cluster admin on managed cluster creates credential of kubeconfig + to hub. \n Once the hub creates the cluster namespace, the Klusterlet agent + on the ManagedCluster pushes the credential to the hub to use against the + kube-apiserver of the ManagedCluster." + type: object + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec represents a desired configuration for the agent on + the managed cluster. + type: object + properties: + hubAcceptsClient: + description: hubAcceptsClient represents that hub accepts the joining + of Klusterlet agent on the managed cluster with the hub. The default + value is false, and can only be set true when the user on hub has + an RBAC rule to UPDATE on the virtual subresource of managedclusters/accept. + When the value is set true, a namespace whose name is the same as + the name of ManagedCluster is created on the hub. This namespace + represents the managed cluster, also role/rolebinding is created + on the namespace to grant the permision of access from the agent + on the managed cluster. When the value is set to false, the namespace + representing the managed cluster is deleted. + type: boolean + leaseDurationSeconds: + description: LeaseDurationSeconds is used to coordinate the lease + update time of Klusterlet agents on the managed cluster. If its + value is zero, the Klusterlet agent will update its lease every + 60 seconds by default + type: integer + format: int32 + managedClusterClientConfigs: + description: ManagedClusterClientConfigs represents a list of the + apiserver address of the managed cluster. If it is empty, the managed + cluster has no accessible address for the hub to connect with it. + type: array + items: + description: ClientConfig represents the apiserver address of the + managed cluster. TODO include credential to connect to managed + cluster kube-apiserver + type: object + properties: + caBundle: + description: CABundle is the ca bundle to connect to apiserver + of the managed cluster. System certs are used if it is not + set. + type: string + format: byte + url: + description: URL is the URL of apiserver endpoint of the managed + cluster. + type: string + status: + description: Status represents the current status of joined managed cluster + type: object + properties: + allocatable: + description: Allocatable represents the total allocatable resources + on the managed cluster. + type: object + additionalProperties: + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + capacity: + description: Capacity represents the total resource capacity from + all nodeStatuses on the managed cluster. + type: object + additionalProperties: + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + clusterClaims: + description: ClusterClaims represents cluster information that a managed + cluster claims, for example a unique cluster identifier (id.k8s.io) + and kubernetes version (kubeversion.open-cluster-management.io). + They are written from the managed cluster. The set of claims is + not uniform across a fleet, some claims can be vendor or version + specific and may not be included from all managed clusters. + type: array + items: + description: ManagedClusterClaim represents a ClusterClaim collected + from a managed cluster. + type: object + properties: + name: + description: Name is the name of a ClusterClaim resource on + managed cluster. It's a well known or customized name to identify + the claim. + type: string + maxLength: 253 + minLength: 1 + value: + description: Value is a claim-dependent string + type: string + maxLength: 1024 + minLength: 1 + conditions: + description: Conditions contains the different condition statuses + for this managed cluster. + type: array + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: + \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // +listMapKey=type + \ Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + type: object + required: + - lastTransitionTime + - message + - reason + - status + - type + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + type: string + format: date-time + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + type: string + maxLength: 32768 + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + type: integer + format: int64 + minimum: 0 + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + type: string + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + status: + description: status of the condition, one of True, False, Unknown. + type: string + enum: + - "True" + - "False" + - Unknown + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + type: string + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + version: + description: Version represents the kubernetes version of the managed + cluster. + type: object + properties: + kubernetes: + description: Kubernetes is the kubernetes version of managed cluster. + type: string + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/vendor/github.com/open-cluster-management/api/cluster/v1/doc.go b/vendor/github.com/open-cluster-management/api/cluster/v1/doc.go new file mode 100644 index 0000000000..b702907817 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/cluster/v1/doc.go @@ -0,0 +1,9 @@ +// Package v1 contains API Schema definitions for the cluster v1 API group +// +k8s:deepcopy-gen=package,register +// +k8s:conversion-gen=github.com/open-cluster-management/api/cluster +// +k8s:defaulter-gen=TypeMeta +// +k8s:openapi-gen=true + +// +kubebuilder:validation:Optional +// +groupName=cluster.open-cluster-management.io +package v1 diff --git a/vendor/github.com/open-cluster-management/api/cluster/v1/register.go b/vendor/github.com/open-cluster-management/api/cluster/v1/register.go new file mode 100644 index 0000000000..6ac0fdc415 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/cluster/v1/register.go @@ -0,0 +1,38 @@ +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +var ( + GroupName = "cluster.open-cluster-management.io" + GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"} + schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + // Install is a function which adds this version to a scheme + Install = schemeBuilder.AddToScheme + + // SchemeGroupVersion generated code relies on this name + // Deprecated + SchemeGroupVersion = GroupVersion + // AddToScheme exists solely to keep the old generators creating valid code + // DEPRECATED + AddToScheme = schemeBuilder.AddToScheme +) + +// Resource generated code relies on this being here, but it logically belongs to the group +// DEPRECATED +func Resource(resource string) schema.GroupResource { + return schema.GroupResource{Group: GroupName, Resource: resource} +} + +// Adds the list of known types to api.Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(GroupVersion, + &ManagedCluster{}, + &ManagedClusterList{}, + ) + metav1.AddToGroupVersion(scheme, GroupVersion) + return nil +} diff --git a/vendor/github.com/open-cluster-management/api/cluster/v1/types.go b/vendor/github.com/open-cluster-management/api/cluster/v1/types.go new file mode 100644 index 0000000000..8ebced45ba --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/cluster/v1/types.go @@ -0,0 +1,171 @@ +package v1 + +import ( + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope="Cluster",shortName={"mcl","mcls"} +// +kubebuilder:printcolumn:JSONPath=`.spec.hubAcceptsClient`,name="Hub Accepted",type=boolean +// +kubebuilder:printcolumn:JSONPath=`.spec.managedClusterClientConfigs[*].url`,name="Managed Cluster URLs",type=string +// +kubebuilder:printcolumn:JSONPath=`.status.conditions[?(@.type=="ManagedClusterJoined")].status`,name="Joined",type=string +// +kubebuilder:printcolumn:JSONPath=`.status.conditions[?(@.type=="ManagedClusterConditionAvailable")].status`,name="Available",type=string +// +kubebuilder:printcolumn:JSONPath=`.metadata.creationTimestamp`,name="Age",type=date + +// ManagedCluster represents the desired state and current status of managed +// cluster. ManagedCluster is a cluster scoped resource. The name is the cluster +// UID. +// +// The cluster join process follows a double opt-in process: +// +// 1. Agent on managed cluster creates CSR on hub with cluster UID and agent name. +// 2. Agent on managed cluster creates ManagedCluster on hub. +// 3. Cluster admin on hub approves the CSR for UID and agent name of the ManagedCluster. +// 4. Cluster admin sets spec.acceptClient of ManagedCluster to true. +// 5. Cluster admin on managed cluster creates credential of kubeconfig to hub. +// +// Once the hub creates the cluster namespace, the Klusterlet agent on the ManagedCluster +// pushes the credential to the hub to use against the kube-apiserver of the ManagedCluster. +type ManagedCluster struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec represents a desired configuration for the agent on the managed cluster. + Spec ManagedClusterSpec `json:"spec"` + + // Status represents the current status of joined managed cluster + // +optional + Status ManagedClusterStatus `json:"status,omitempty"` +} + +// ManagedClusterSpec provides the information to securely connect to a remote server +// and verify its identity. +type ManagedClusterSpec struct { + // ManagedClusterClientConfigs represents a list of the apiserver address of the managed cluster. + // If it is empty, the managed cluster has no accessible address for the hub to connect with it. + // +optional + ManagedClusterClientConfigs []ClientConfig `json:"managedClusterClientConfigs,omitempty"` + + // hubAcceptsClient represents that hub accepts the joining of Klusterlet agent on + // the managed cluster with the hub. The default value is false, and can only be set + // true when the user on hub has an RBAC rule to UPDATE on the virtual subresource + // of managedclusters/accept. + // When the value is set true, a namespace whose name is the same as the name of ManagedCluster + // is created on the hub. This namespace represents the managed cluster, also role/rolebinding is created on + // the namespace to grant the permision of access from the agent on the managed cluster. + // When the value is set to false, the namespace representing the managed cluster is + // deleted. + // +required + HubAcceptsClient bool `json:"hubAcceptsClient"` + + // LeaseDurationSeconds is used to coordinate the lease update time of Klusterlet agents on the managed cluster. + // If its value is zero, the Klusterlet agent will update its lease every 60 seconds by default + // +optional + LeaseDurationSeconds int32 `json:"leaseDurationSeconds,omitempty"` +} + +// ClientConfig represents the apiserver address of the managed cluster. +// TODO include credential to connect to managed cluster kube-apiserver +type ClientConfig struct { + // URL is the URL of apiserver endpoint of the managed cluster. + // +required + URL string `json:"url"` + + // CABundle is the ca bundle to connect to apiserver of the managed cluster. + // System certs are used if it is not set. + // +optional + CABundle []byte `json:"caBundle,omitempty"` +} + +// ManagedClusterStatus represents the current status of joined managed cluster. +type ManagedClusterStatus struct { + // Conditions contains the different condition statuses for this managed cluster. + Conditions []metav1.Condition `json:"conditions"` + + // Capacity represents the total resource capacity from all nodeStatuses + // on the managed cluster. + Capacity ResourceList `json:"capacity,omitempty"` + + // Allocatable represents the total allocatable resources on the managed cluster. + Allocatable ResourceList `json:"allocatable,omitempty"` + + // Version represents the kubernetes version of the managed cluster. + Version ManagedClusterVersion `json:"version,omitempty"` + + // ClusterClaims represents cluster information that a managed cluster claims, + // for example a unique cluster identifier (id.k8s.io) and kubernetes version + // (kubeversion.open-cluster-management.io). They are written from the managed + // cluster. The set of claims is not uniform across a fleet, some claims can be + // vendor or version specific and may not be included from all managed clusters. + // +optional + ClusterClaims []ManagedClusterClaim `json:"clusterClaims,omitempty"` +} + +// ManagedClusterVersion represents version information about the managed cluster. +// TODO add managed agent versions +type ManagedClusterVersion struct { + // Kubernetes is the kubernetes version of managed cluster. + // +optional + Kubernetes string `json:"kubernetes,omitempty"` +} + +// ManagedClusterClaim represents a ClusterClaim collected from a managed cluster. +type ManagedClusterClaim struct { + // Name is the name of a ClusterClaim resource on managed cluster. It's a well known + // or customized name to identify the claim. + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:validation:MinLength=1 + Name string `json:"name,omitempty"` + + // Value is a claim-dependent string + // +kubebuilder:validation:MaxLength=1024 + // +kubebuilder:validation:MinLength=1 + Value string `json:"value,omitempty"` +} + +const ( + // ManagedClusterConditionJoined means the managed cluster has successfully joined the hub. + ManagedClusterConditionJoined string = "ManagedClusterJoined" + // ManagedClusterConditionHubAccepted means the request to join the cluster is + // approved by cluster-admin on hub. + ManagedClusterConditionHubAccepted string = "HubAcceptedManagedCluster" + // ManagedClusterConditionHubDenied means the request to join the cluster is denied by + // cluster-admin on hub. + ManagedClusterConditionHubDenied string = "HubDeniedManagedCluster" + // ManagedClusterConditionAvailable means the managed cluster is available. If a managed + // cluster is available, the kube-apiserver is healthy and the Klusterlet agent is + // running with the minimum deployment on this managed cluster + ManagedClusterConditionAvailable string = "ManagedClusterConditionAvailable" +) + +// ResourceName is the name identifying various resources in a ResourceList. +type ResourceName string + +const ( + // ResourceCPU defines the number of CPUs in cores. (500m = .5 cores) + ResourceCPU ResourceName = "cpu" + // ResourceMemory defines the amount of memory in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024) + ResourceMemory ResourceName = "memory" +) + +// ResourceList defines a map for the quantity of different resources, the definition +// matches the ResourceList defined in k8s.io/api/core/v1. +type ResourceList map[ResourceName]resource.Quantity + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ManagedClusterList is a collection of managed cluster. +type ManagedClusterList struct { + metav1.TypeMeta `json:",inline"` + // Standard list metadata. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds + // +optional + metav1.ListMeta `json:"metadata,omitempty"` + + // Items is a list of managed clusters. + Items []ManagedCluster `json:"items"` +} diff --git a/vendor/github.com/open-cluster-management/api/cluster/v1/zz_generated.deepcopy.go b/vendor/github.com/open-cluster-management/api/cluster/v1/zz_generated.deepcopy.go new file mode 100644 index 0000000000..05d18c890b --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/cluster/v1/zz_generated.deepcopy.go @@ -0,0 +1,212 @@ +// +build !ignore_autogenerated + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClientConfig) DeepCopyInto(out *ClientConfig) { + *out = *in + if in.CABundle != nil { + in, out := &in.CABundle, &out.CABundle + *out = make([]byte, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClientConfig. +func (in *ClientConfig) DeepCopy() *ClientConfig { + if in == nil { + return nil + } + out := new(ClientConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedCluster) DeepCopyInto(out *ManagedCluster) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedCluster. +func (in *ManagedCluster) DeepCopy() *ManagedCluster { + if in == nil { + return nil + } + out := new(ManagedCluster) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ManagedCluster) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClusterClaim) DeepCopyInto(out *ManagedClusterClaim) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClusterClaim. +func (in *ManagedClusterClaim) DeepCopy() *ManagedClusterClaim { + if in == nil { + return nil + } + out := new(ManagedClusterClaim) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClusterList) DeepCopyInto(out *ManagedClusterList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ManagedCluster, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClusterList. +func (in *ManagedClusterList) DeepCopy() *ManagedClusterList { + if in == nil { + return nil + } + out := new(ManagedClusterList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ManagedClusterList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClusterSpec) DeepCopyInto(out *ManagedClusterSpec) { + *out = *in + if in.ManagedClusterClientConfigs != nil { + in, out := &in.ManagedClusterClientConfigs, &out.ManagedClusterClientConfigs + *out = make([]ClientConfig, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClusterSpec. +func (in *ManagedClusterSpec) DeepCopy() *ManagedClusterSpec { + if in == nil { + return nil + } + out := new(ManagedClusterSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClusterStatus) DeepCopyInto(out *ManagedClusterStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Capacity != nil { + in, out := &in.Capacity, &out.Capacity + *out = make(ResourceList, len(*in)) + for key, val := range *in { + (*out)[key] = val.DeepCopy() + } + } + if in.Allocatable != nil { + in, out := &in.Allocatable, &out.Allocatable + *out = make(ResourceList, len(*in)) + for key, val := range *in { + (*out)[key] = val.DeepCopy() + } + } + out.Version = in.Version + if in.ClusterClaims != nil { + in, out := &in.ClusterClaims, &out.ClusterClaims + *out = make([]ManagedClusterClaim, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClusterStatus. +func (in *ManagedClusterStatus) DeepCopy() *ManagedClusterStatus { + if in == nil { + return nil + } + out := new(ManagedClusterStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClusterVersion) DeepCopyInto(out *ManagedClusterVersion) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClusterVersion. +func (in *ManagedClusterVersion) DeepCopy() *ManagedClusterVersion { + if in == nil { + return nil + } + out := new(ManagedClusterVersion) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in ResourceList) DeepCopyInto(out *ResourceList) { + { + in := &in + *out = make(ResourceList, len(*in)) + for key, val := range *in { + (*out)[key] = val.DeepCopy() + } + return + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceList. +func (in ResourceList) DeepCopy() ResourceList { + if in == nil { + return nil + } + out := new(ResourceList) + in.DeepCopyInto(out) + return *out +} diff --git a/vendor/github.com/open-cluster-management/api/cluster/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/open-cluster-management/api/cluster/v1/zz_generated.swagger_doc_generated.go new file mode 100644 index 0000000000..8c6667a4e3 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/cluster/v1/zz_generated.swagger_doc_generated.go @@ -0,0 +1,87 @@ +package v1 + +// This file contains a collection of methods that can be used from go-restful to +// generate Swagger API documentation for its models. Please read this PR for more +// information on the implementation: https://github.com/emicklei/go-restful/pull/215 +// +// TODOs are ignored from the parser (e.g. TODO(andronat):... || TODO:...) if and only if +// they are on one line! For multiple line or blocks that you want to ignore use ---. +// Any context after a --- is ignored. +// +// Those methods can be generated by using hack/update-swagger-docs.sh + +// AUTO-GENERATED FUNCTIONS START HERE +var map_ClientConfig = map[string]string{ + "": "ClientConfig represents the apiserver address of the managed cluster.", + "url": "URL is the URL of apiserver endpoint of the managed cluster.", + "caBundle": "CABundle is the ca bundle to connect to apiserver of the managed cluster. System certs are used if it is not set.", +} + +func (ClientConfig) SwaggerDoc() map[string]string { + return map_ClientConfig +} + +var map_ManagedCluster = map[string]string{ + "": "ManagedCluster represents the desired state and current status of managed cluster. ManagedCluster is a cluster scoped resource. The name is the cluster UID.\n\nThe cluster join process follows a double opt-in process:\n\n1. Agent on managed cluster creates CSR on hub with cluster UID and agent name. 2. Agent on managed cluster creates ManagedCluster on hub. 3. Cluster admin on hub approves the CSR for UID and agent name of the ManagedCluster. 4. Cluster admin sets spec.acceptClient of ManagedCluster to true. 5. Cluster admin on managed cluster creates credential of kubeconfig to hub.\n\nOnce the hub creates the cluster namespace, the Klusterlet agent on the ManagedCluster pushes the credential to the hub to use against the kube-apiserver of the ManagedCluster.", + "spec": "Spec represents a desired configuration for the agent on the managed cluster.", + "status": "Status represents the current status of joined managed cluster", +} + +func (ManagedCluster) SwaggerDoc() map[string]string { + return map_ManagedCluster +} + +var map_ManagedClusterClaim = map[string]string{ + "": "ManagedClusterClaim represents a ClusterClaim collected from a managed cluster.", + "name": "Name is the name of a ClusterClaim resource on managed cluster. It's a well known or customized name to identify the claim.", + "value": "Value is a claim-dependent string", +} + +func (ManagedClusterClaim) SwaggerDoc() map[string]string { + return map_ManagedClusterClaim +} + +var map_ManagedClusterList = map[string]string{ + "": "ManagedClusterList is a collection of managed cluster.", + "metadata": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "items": "Items is a list of managed clusters.", +} + +func (ManagedClusterList) SwaggerDoc() map[string]string { + return map_ManagedClusterList +} + +var map_ManagedClusterSpec = map[string]string{ + "": "ManagedClusterSpec provides the information to securely connect to a remote server and verify its identity.", + "managedClusterClientConfigs": "ManagedClusterClientConfigs represents a list of the apiserver address of the managed cluster. If it is empty, the managed cluster has no accessible address for the hub to connect with it.", + "hubAcceptsClient": "hubAcceptsClient represents that hub accepts the joining of Klusterlet agent on the managed cluster with the hub. The default value is false, and can only be set true when the user on hub has an RBAC rule to UPDATE on the virtual subresource of managedclusters/accept. When the value is set true, a namespace whose name is the same as the name of ManagedCluster is created on the hub. This namespace represents the managed cluster, also role/rolebinding is created on the namespace to grant the permision of access from the agent on the managed cluster. When the value is set to false, the namespace representing the managed cluster is deleted.", + "leaseDurationSeconds": "LeaseDurationSeconds is used to coordinate the lease update time of Klusterlet agents on the managed cluster. If its value is zero, the Klusterlet agent will update its lease every 60 seconds by default", +} + +func (ManagedClusterSpec) SwaggerDoc() map[string]string { + return map_ManagedClusterSpec +} + +var map_ManagedClusterStatus = map[string]string{ + "": "ManagedClusterStatus represents the current status of joined managed cluster.", + "conditions": "Conditions contains the different condition statuses for this managed cluster.", + "capacity": "Capacity represents the total resource capacity from all nodeStatuses on the managed cluster.", + "allocatable": "Allocatable represents the total allocatable resources on the managed cluster.", + "version": "Version represents the kubernetes version of the managed cluster.", + "clusterClaims": "ClusterClaims represents cluster information that a managed cluster claims, for example a unique cluster identifier (id.k8s.io) and kubernetes version (kubeversion.open-cluster-management.io). They are written from the managed cluster. The set of claims is not uniform across a fleet, some claims can be vendor or version specific and may not be included from all managed clusters.", +} + +func (ManagedClusterStatus) SwaggerDoc() map[string]string { + return map_ManagedClusterStatus +} + +var map_ManagedClusterVersion = map[string]string{ + "": "ManagedClusterVersion represents version information about the managed cluster.", + "kubernetes": "Kubernetes is the kubernetes version of managed cluster.", +} + +func (ManagedClusterVersion) SwaggerDoc() map[string]string { + return map_ManagedClusterVersion +} + +// AUTO-GENERATED FUNCTIONS END HERE diff --git a/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0000_00_clusters.open-cluster-management.io_managedclustersets.crd.yaml b/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0000_00_clusters.open-cluster-management.io_managedclustersets.crd.yaml new file mode 100644 index 0000000000..731dc173bd --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0000_00_clusters.open-cluster-management.io_managedclustersets.crd.yaml @@ -0,0 +1,134 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: managedclustersets.cluster.open-cluster-management.io +spec: + group: cluster.open-cluster-management.io + names: + kind: ManagedClusterSet + listKind: ManagedClusterSetList + plural: managedclustersets + shortNames: + - mclset + - mclsets + singular: managedclusterset + scope: Cluster + preserveUnknownFields: false + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: "ManagedClusterSet defines a group of ManagedClusters that user's + workload can run on. A workload can be defined to deployed on a ManagedClusterSet, + which mean: 1. The workload can run on any ManagedCluster in the ManagedClusterSet + \ 2. The workload cannot run on any ManagedCluster outside the ManagedClusterSet + \ 3. The service exposed by the workload can be shared in any ManagedCluster + in the ManagedClusterSet \n In order to assign a ManagedCluster to a certian + ManagedClusterSet, add a label with name `cluster.open-cluster-management.io/clusterset` + on the ManagedCluster to refers to the ManagedClusterSet. User is not allow + to add/remove this label on a ManagedCluster unless they have a RBAC rule + to CREATE on a virtual subresource of managedclustersets/join. In order + to update this label, user must have the permission on both the old and + new ManagedClusterSet." + type: object + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the attributes of the ManagedClusterSet + type: object + status: + description: Status represents the current status of the ManagedClusterSet + type: object + properties: + conditions: + description: Conditions contains the different condition statuses + for this ManagedClusterSet. + type: array + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: + \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // +listMapKey=type + \ Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + type: object + required: + - lastTransitionTime + - message + - reason + - status + - type + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + type: string + format: date-time + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + type: string + maxLength: 32768 + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + type: integer + format: int64 + minimum: 0 + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + type: string + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + status: + description: status of the condition, one of True, False, Unknown. + type: string + enum: + - "True" + - "False" + - Unknown + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + type: string + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0000_01_clusters.open-cluster-management.io_managedclustersetbindings.crd.yaml b/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0000_01_clusters.open-cluster-management.io_managedclustersetbindings.crd.yaml new file mode 100644 index 0000000000..c37214040e --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0000_01_clusters.open-cluster-management.io_managedclustersetbindings.crd.yaml @@ -0,0 +1,60 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: managedclustersetbindings.cluster.open-cluster-management.io +spec: + group: cluster.open-cluster-management.io + names: + kind: ManagedClusterSetBinding + listKind: ManagedClusterSetBindingList + plural: managedclustersetbindings + shortNames: + - mclsetbinding + - mclsetbindings + singular: managedclustersetbinding + scope: Namespaced + preserveUnknownFields: false + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: ManagedClusterSetBinding projects a ManagedClusterSet into a + certain namespace. User is able to create a ManagedClusterSetBinding in + a namespace and bind it to a ManagedClusterSet if they have an RBAC rule + to CREATE on the virtual subresource of managedclustersets/bind. Workloads + created in the same namespace can only be distributed to ManagedClusters + in ManagedClusterSets bound in this namespace by higher level controllers. + type: object + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the attributes of ManagedClusterSetBinding. + type: object + properties: + clusterSet: + description: ClusterSet is the name of the ManagedClusterSet to bind. + It must match the instance name of the ManagedClusterSetBinding + and cannot change once created. User is allowed to set this field + if they have an RBAC rule to CREATE on the virtual subresource of + managedclustersets/bind. + type: string + minLength: 1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0000_02_clusters.open-cluster-management.io_clusterclaims.crd.yaml b/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0000_02_clusters.open-cluster-management.io_clusterclaims.crd.yaml new file mode 100644 index 0000000000..eebbe280f3 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0000_02_clusters.open-cluster-management.io_clusterclaims.crd.yaml @@ -0,0 +1,54 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: clusterclaims.cluster.open-cluster-management.io +spec: + group: cluster.open-cluster-management.io + names: + kind: ClusterClaim + listKind: ClusterClaimList + plural: clusterclaims + singular: clusterclaim + scope: Cluster + preserveUnknownFields: false + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: ClusterClaim represents cluster information that a managed cluster + claims ClusterClaims with well known names include, 1. id.k8s.io, it contains + a unique identifier for the cluster. 2. clusterset.k8s.io, it contains + an identifier that relates the cluster to the ClusterSet in which it + belongs. ClusterClaims created on a managed cluster will be collected and + saved into the status of the corresponding ManagedCluster on hub. + type: object + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the attributes of the ClusterClaim. + type: object + properties: + value: + description: Value is a claim-dependent string + type: string + maxLength: 1024 + minLength: 1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0000_03_clusters.open-cluster-management.io_placements.crd.yaml b/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0000_03_clusters.open-cluster-management.io_placements.crd.yaml new file mode 100644 index 0000000000..619a15a897 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0000_03_clusters.open-cluster-management.io_placements.crd.yaml @@ -0,0 +1,274 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: placements.cluster.open-cluster-management.io +spec: + group: cluster.open-cluster-management.io + names: + kind: Placement + listKind: PlacementList + plural: placements + singular: placement + scope: Namespaced + preserveUnknownFields: false + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: "Placement defines a rule to select a set of ManagedClusters + from the ManagedClusterSets bound to the placement namespace. \n Here is + how the placement policy combines with other selection methods to determine + a matching list of ManagedClusters: 1) Kubernetes clusters are registered + with hub as cluster-scoped ManagedClusters; 2) ManagedClusters are organized + into cluster-scoped ManagedClusterSets; 3) ManagedClusterSets are bound + to workload namespaces; 4) Namespace-scoped Placements specify a slice of + ManagedClusterSets which select a working set of potential ManagedClusters; + 5) Then Placements subselect from that working set using label/claim selection. + \n No ManagedCluster will be selected if no ManagedClusterSet is bound to + the placement namespace. User is able to bind a ManagedClusterSet to a namespace + by creating a ManagedClusterSetBinding in that namespace if they have a + RBAC rule to CREATE on the virtual subresource of `managedclustersets/bind`. + \n A slice of PlacementDecisions with label cluster.open-cluster-management.io/placement={placement + name} will be created to represent the ManagedClusters selected by this + placement. \n If a ManagedCluster is selected and added into the PlacementDecisions, + other components may apply workload on it; once it is removed from the PlacementDecisions, + the workload applied on this ManagedCluster should be evicted accordingly." + type: object + required: + - spec + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the attributes of Placement. + type: object + properties: + clusterSets: + description: ClusterSets represent the ManagedClusterSets from which + the ManagedClusters are selected. If the slice is empty, ManagedClusters + will be selected from the ManagedClusterSets bound to the placement + namespace, otherwise ManagedClusters will be selected from the intersection + of this slice and the ManagedClusterSets bound to the placement + namespace. + type: array + items: + type: string + numberOfClusters: + description: NumberOfClusters represents the desired number of ManagedClusters + to be selected which meet the placement requirements. 1) If not + specified, all ManagedClusters which meet the placement requirements + (including ClusterSets, and Predicates) will be selected; 2) + Otherwise if the nubmer of ManagedClusters meet the placement requirements + is larger than NumberOfClusters, a random subset with desired + number of ManagedClusters will be selected; 3) If the nubmer of + ManagedClusters meet the placement requirements is equal to NumberOfClusters, all + of them will be selected; 4) If the nubmer of ManagedClusters meet + the placement requirements is less than NumberOfClusters, all + of them will be selected, and the status of condition `PlacementConditionSatisfied` + will be set to false; + type: integer + format: int32 + predicates: + description: Predicates represent a slice of predicates to select + ManagedClusters. The predicates are ORed. + type: array + items: + description: ClusterPredicate represents a predicate to select ManagedClusters. + type: object + properties: + requiredClusterSelector: + description: RequiredClusterSelector represents a selector of + ManagedClusters by label and claim. If specified, 1) Any ManagedCluster, + which does not match the selector, should not be selected + by this ClusterPredicate; 2) If a selected ManagedCluster + (of this ClusterPredicate) ceases to match the selector (e.g. + due to an update) of any ClusterPredicate, it will be eventually + removed from the placement decisions; 3) If a ManagedCluster + (not selected previously) starts to match the selector, it + will either be selected or at least has a chance to be + selected (when NumberOfClusters is specified); + type: object + properties: + claimSelector: + description: ClaimSelector represents a selector of ManagedClusters + by clusterClaims in status + type: object + properties: + matchExpressions: + description: matchExpressions is a list of cluster claim + selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values array + must be non-empty. If the operator is Exists + or DoesNotExist, the values array must be empty. + This array is replaced during a strategic merge + patch. + type: array + items: + type: string + labelSelector: + description: LabelSelector represents a selector of ManagedClusters + by label + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values array + must be non-empty. If the operator is Exists + or DoesNotExist, the values array must be empty. + This array is replaced during a strategic merge + patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + status: + description: Status represents the current status of the Placement + type: object + properties: + conditions: + description: Conditions contains the different condition statuses + for this Placement. + type: array + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: + \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // +listMapKey=type + \ Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + type: object + required: + - lastTransitionTime + - message + - reason + - status + - type + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + type: string + format: date-time + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + type: string + maxLength: 32768 + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + type: integer + format: int64 + minimum: 0 + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + type: string + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + status: + description: status of the condition, one of True, False, Unknown. + type: string + enum: + - "True" + - "False" + - Unknown + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + type: string + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + numberOfSelectedClusters: + description: NumberOfSelectedClusters represents the number of selected + ManagedClusters + type: integer + format: int32 + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0000_04_clusters.open-cluster-management.io_placementdecisions.crd.yaml b/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0000_04_clusters.open-cluster-management.io_placementdecisions.crd.yaml new file mode 100644 index 0000000000..fc75289ea5 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0000_04_clusters.open-cluster-management.io_placementdecisions.crd.yaml @@ -0,0 +1,76 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: placementdecisions.cluster.open-cluster-management.io +spec: + group: cluster.open-cluster-management.io + names: + kind: PlacementDecision + listKind: PlacementDecisionList + plural: placementdecisions + singular: placementdecision + scope: Namespaced + preserveUnknownFields: false + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: "PlacementDecision indicates a decision from a placement PlacementDecision + should has a label cluster.open-cluster-management.io/placement={placement + name} to reference a certain placement. \n If a placement has spec.numberOfClusters + specified, the total number of decisions contained in status.decisions of + PlacementDecisions should always be NumberOfClusters; otherwise, the total + number of decisions should be the number of ManagedClusters which match + the placement requirements. \n Some of the decisions might be empty when + there are no enough ManagedClusters meet the placement requirements." + type: object + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + status: + description: Status represents the current status of the PlacementDecision + type: object + required: + - decisions + properties: + decisions: + description: Decisions is a slice of decisions according to a placement + The number of decisions should not be larger than 100 + type: array + items: + description: ClusterDecision represents a decision from a placement + An empty ClusterDecision indicates it is not scheduled yet. + type: object + required: + - clusterName + - reason + properties: + clusterName: + description: ClusterName is the name of the ManagedCluster. + If it is not empty, its value should be unique cross all placement + decisions for the Placement. + type: string + reason: + description: Reason represents the reason why the ManagedCluster + is selected. + type: string + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0001_02_clusters.open-cluster-management.io_clusterclaims.crd.yaml b/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0001_02_clusters.open-cluster-management.io_clusterclaims.crd.yaml new file mode 100644 index 0000000000..4027c7a94f --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/0001_02_clusters.open-cluster-management.io_clusterclaims.crd.yaml @@ -0,0 +1,55 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: clusterclaims.cluster.open-cluster-management.io +spec: + group: cluster.open-cluster-management.io + names: + kind: ClusterClaim + listKind: ClusterClaimList + plural: clusterclaims + singular: clusterclaim + scope: Cluster + preserveUnknownFields: false + validation: + openAPIV3Schema: + description: ClusterClaim represents cluster information that a managed cluster + claims ClusterClaims with well known names include, 1. id.k8s.io, it contains + a unique identifier for the cluster. 2. clusterset.k8s.io, it contains an + identifier that relates the cluster to the ClusterSet in which it belongs. + ClusterClaims created on a managed cluster will be collected and saved into + the status of the corresponding ManagedCluster on hub. + type: object + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the attributes of the ClusterClaim. + type: object + properties: + value: + description: Value is a claim-dependent string + type: string + maxLength: 1024 + minLength: 1 + version: v1alpha1 + versions: + - name: v1alpha1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/doc.go b/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/doc.go new file mode 100644 index 0000000000..37b222f289 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/doc.go @@ -0,0 +1,9 @@ +// Package v1alpha1 contains API Schema definitions for the cluster v1alpha1 API group +// +k8s:deepcopy-gen=package,register +// +k8s:conversion-gen=github.com/open-cluster-management/api/cluster +// +k8s:defaulter-gen=TypeMeta +// +k8s:openapi-gen=true + +// +kubebuilder:validation:Optional +// +groupName=cluster.open-cluster-management.io +package v1alpha1 diff --git a/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/register.go b/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/register.go new file mode 100644 index 0000000000..3defb57d6c --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/register.go @@ -0,0 +1,46 @@ +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +var ( + GroupName = "cluster.open-cluster-management.io" + GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} + schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + // Install is a function which adds this version to a scheme + Install = schemeBuilder.AddToScheme + + // SchemeGroupVersion generated code relies on this name + // Deprecated + SchemeGroupVersion = GroupVersion + // AddToScheme exists solely to keep the old generators creating valid code + // DEPRECATED + AddToScheme = schemeBuilder.AddToScheme +) + +// Resource generated code relies on this being here, but it logically belongs to the group +// DEPRECATED +func Resource(resource string) schema.GroupResource { + return schema.GroupResource{Group: GroupName, Resource: resource} +} + +// Adds the list of known types to api.Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(GroupVersion, + &ManagedClusterSet{}, + &ManagedClusterSetList{}, + &ManagedClusterSetBinding{}, + &ManagedClusterSetBindingList{}, + &ClusterClaim{}, + &ClusterClaimList{}, + &Placement{}, + &PlacementList{}, + &PlacementDecision{}, + &PlacementDecisionList{}, + ) + metav1.AddToGroupVersion(scheme, GroupVersion) + return nil +} diff --git a/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/types.go b/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/types.go new file mode 100644 index 0000000000..9c9dc0a0d4 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/types.go @@ -0,0 +1,358 @@ +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope="Cluster",shortName={"mclset","mclsets"} + +// ManagedClusterSet defines a group of ManagedClusters that user's workload can run on. +// A workload can be defined to deployed on a ManagedClusterSet, which mean: +// 1. The workload can run on any ManagedCluster in the ManagedClusterSet +// 2. The workload cannot run on any ManagedCluster outside the ManagedClusterSet +// 3. The service exposed by the workload can be shared in any ManagedCluster in the ManagedClusterSet +// +// In order to assign a ManagedCluster to a certian ManagedClusterSet, add a label with name +// `cluster.open-cluster-management.io/clusterset` on the ManagedCluster to refers to the ManagedClusterSet. +// User is not allow to add/remove this label on a ManagedCluster unless they have a RBAC rule to CREATE on +// a virtual subresource of managedclustersets/join. In order to update this label, user must have the permission +// on both the old and new ManagedClusterSet. +type ManagedClusterSet struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the attributes of the ManagedClusterSet + Spec ManagedClusterSetSpec `json:"spec"` + + // Status represents the current status of the ManagedClusterSet + // +optional + Status ManagedClusterSetStatus `json:"status,omitempty"` +} + +// ManagedClusterSetSpec describes the attributes of the ManagedClusterSet +type ManagedClusterSetSpec struct { +} + +// ManagedClusterSetStatus represents the current status of the ManagedClusterSet. +type ManagedClusterSetStatus struct { + // Conditions contains the different condition statuses for this ManagedClusterSet. + Conditions []metav1.Condition `json:"conditions"` +} + +const ( + // ManagedClusterSetConditionEmpty means no ManagedCluster is included in the + // ManagedClusterSet. + ManagedClusterSetConditionEmpty string = "ClusterSetEmpty" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ManagedClusterSetList is a collection of ManagedClusterSet. +type ManagedClusterSetList struct { + metav1.TypeMeta `json:",inline"` + // Standard list metadata. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds + // +optional + metav1.ListMeta `json:"metadata,omitempty"` + + // Items is a list of ManagedClusterSet. + Items []ManagedClusterSet `json:"items"` +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:resource:scope="Namespaced",shortName={"mclsetbinding","mclsetbindings"} + +// ManagedClusterSetBinding projects a ManagedClusterSet into a certain namespace. +// User is able to create a ManagedClusterSetBinding in a namespace and bind it to a +// ManagedClusterSet if they have an RBAC rule to CREATE on the virtual subresource of +// managedclustersets/bind. Workloads created in the same namespace can only be +// distributed to ManagedClusters in ManagedClusterSets bound in this namespace by +// higher level controllers. +type ManagedClusterSetBinding struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the attributes of ManagedClusterSetBinding. + Spec ManagedClusterSetBindingSpec `json:"spec"` +} + +// ManagedClusterSetBindingSpec defines the attributes of ManagedClusterSetBinding. +type ManagedClusterSetBindingSpec struct { + // ClusterSet is the name of the ManagedClusterSet to bind. It must match the + // instance name of the ManagedClusterSetBinding and cannot change once created. + // User is allowed to set this field if they have an RBAC rule to CREATE on the + // virtual subresource of managedclustersets/bind. + // +kubebuilder:validation:MinLength=1 + ClusterSet string `json:"clusterSet"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ManagedClusterSetBindingList is a collection of ManagedClusterSetBinding. +type ManagedClusterSetBindingList struct { + metav1.TypeMeta `json:",inline"` + // Standard list metadata. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds + // +optional + metav1.ListMeta `json:"metadata,omitempty"` + + // Items is a list of ManagedClusterSetBinding. + Items []ManagedClusterSetBinding `json:"items"` +} + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:resource:scope="Cluster" + +// ClusterClaim represents cluster information that a managed cluster claims +// ClusterClaims with well known names include, +// 1. id.k8s.io, it contains a unique identifier for the cluster. +// 2. clusterset.k8s.io, it contains an identifier that relates the cluster +// to the ClusterSet in which it belongs. +// ClusterClaims created on a managed cluster will be collected and saved into +// the status of the corresponding ManagedCluster on hub. +type ClusterClaim struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the attributes of the ClusterClaim. + Spec ClusterClaimSpec `json:"spec,omitempty"` +} + +type ClusterClaimSpec struct { + // Value is a claim-dependent string + // +kubebuilder:validation:MaxLength=1024 + // +kubebuilder:validation:MinLength=1 + Value string `json:"value,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ClusterClaimList is a collection of ClusterClaim. +type ClusterClaimList struct { + metav1.TypeMeta `json:",inline"` + // Standard list metadata. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds + // +optional + metav1.ListMeta `json:"metadata,omitempty"` + + // Items is a list of ClusterClaim. + Items []ClusterClaim `json:"items"` +} + +// ReservedClusterClaimNames includes a list of reserved names for ClusterNames. +// When exposing ClusterClaims created on managed cluster, the registration agent gives high +// priority to the reserved ClusterClaims. +var ReservedClusterClaimNames = [...]string{ + // unique identifier for the cluster + "id.k8s.io", + // kubernetes version + "kubeversion.open-cluster-management.io", + // platform the managed cluster is running on, like AWS, GCE, and Equinix Metal + "platform.open-cluster-management.io", + // product name, like OpenShift, Anthos, EKS and GKE + "product.open-cluster-management.io", +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:resource:scope="Namespaced" +// +kubebuilder:subresource:status + +// Placement defines a rule to select a set of ManagedClusters from the ManagedClusterSets bound +// to the placement namespace. +// +// Here is how the placement policy combines with other selection methods to determine a matching +// list of ManagedClusters: +// 1) Kubernetes clusters are registered with hub as cluster-scoped ManagedClusters; +// 2) ManagedClusters are organized into cluster-scoped ManagedClusterSets; +// 3) ManagedClusterSets are bound to workload namespaces; +// 4) Namespace-scoped Placements specify a slice of ManagedClusterSets which select a working set +// of potential ManagedClusters; +// 5) Then Placements subselect from that working set using label/claim selection. +// +// No ManagedCluster will be selected if no ManagedClusterSet is bound to the placement +// namespace. User is able to bind a ManagedClusterSet to a namespace by creating a +// ManagedClusterSetBinding in that namespace if they have a RBAC rule to CREATE on the virtual +// subresource of `managedclustersets/bind`. +// +// A slice of PlacementDecisions with label cluster.open-cluster-management.io/placement={placement name} +// will be created to represent the ManagedClusters selected by this placement. +// +// If a ManagedCluster is selected and added into the PlacementDecisions, other components may +// apply workload on it; once it is removed from the PlacementDecisions, the workload applied on +// this ManagedCluster should be evicted accordingly. +type Placement struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the attributes of Placement. + // +kubebuilder:validation:Required + // +required + Spec PlacementSpec `json:"spec"` + + // Status represents the current status of the Placement + // +optional + Status PlacementStatus `json:"status,omitempty"` +} + +// PlacementSpec defines the attributes of Placement. +// An empty PlacementSpec selects all ManagedClusters from the ManagedClusterSets bound to +// the placement namespace. The containing fields are ANDed. +type PlacementSpec struct { + // ClusterSets represent the ManagedClusterSets from which the ManagedClusters are selected. + // If the slice is empty, ManagedClusters will be selected from the ManagedClusterSets bound to the placement + // namespace, otherwise ManagedClusters will be selected from the intersection of this slice and the + // ManagedClusterSets bound to the placement namespace. + // +optional + ClusterSets []string `json:"clusterSets,omitempty"` + + // NumberOfClusters represents the desired number of ManagedClusters to be selected which meet the + // placement requirements. + // 1) If not specified, all ManagedClusters which meet the placement requirements (including ClusterSets, + // and Predicates) will be selected; + // 2) Otherwise if the nubmer of ManagedClusters meet the placement requirements is larger than + // NumberOfClusters, a random subset with desired number of ManagedClusters will be selected; + // 3) If the nubmer of ManagedClusters meet the placement requirements is equal to NumberOfClusters, + // all of them will be selected; + // 4) If the nubmer of ManagedClusters meet the placement requirements is less than NumberOfClusters, + // all of them will be selected, and the status of condition `PlacementConditionSatisfied` will be + // set to false; + // +optional + NumberOfClusters *int32 `json:"numberOfClusters,omitempty"` + + // Predicates represent a slice of predicates to select ManagedClusters. The predicates are ORed. + // +optional + Predicates []ClusterPredicate `json:"predicates,omitempty"` +} + +// ClusterPredicate represents a predicate to select ManagedClusters. +type ClusterPredicate struct { + // RequiredClusterSelector represents a selector of ManagedClusters by label and claim. If specified, + // 1) Any ManagedCluster, which does not match the selector, should not be selected by this ClusterPredicate; + // 2) If a selected ManagedCluster (of this ClusterPredicate) ceases to match the selector (e.g. due to + // an update) of any ClusterPredicate, it will be eventually removed from the placement decisions; + // 3) If a ManagedCluster (not selected previously) starts to match the selector, it will either + // be selected or at least has a chance to be selected (when NumberOfClusters is specified); + // +optional + RequiredClusterSelector ClusterSelector `json:"requiredClusterSelector,omitempty"` +} + +// ClusterSelector represents the AND of the containing selectors. An empty cluster selector matches all objects. +// A null cluster selector matches no objects. +type ClusterSelector struct { + // LabelSelector represents a selector of ManagedClusters by label + // +optional + LabelSelector metav1.LabelSelector `json:"labelSelector,omitempty"` + + // ClaimSelector represents a selector of ManagedClusters by clusterClaims in status + // +optional + ClaimSelector ClusterClaimSelector `json:"claimSelector,omitempty"` +} + +// ClusterClaimSelector is a claim query over a set of ManagedClusters. An empty cluster claim +// selector matches all objects. A null cluster claim selector matches no objects. +type ClusterClaimSelector struct { + // matchExpressions is a list of cluster claim selector requirements. The requirements are ANDed. + // +optional + MatchExpressions []metav1.LabelSelectorRequirement `json:"matchExpressions,omitempty"` +} + +type PlacementStatus struct { + // NumberOfSelectedClusters represents the number of selected ManagedClusters + // +optional + NumberOfSelectedClusters int32 `json:"numberOfSelectedClusters"` + + // Conditions contains the different condition statuses for this Placement. + // +optional + Conditions []metav1.Condition `json:"conditions"` +} + +const ( + // PlacementConditionSatisfied means Placement requirements are satisfied. + // A placement is not satisfied only if there is empty ClusterDecision in the status.decisions + // of PlacementDecisions. + PlacementConditionSatisfied string = "PlacementSatisfied" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// PlacementList is a collection of Placements. +type PlacementList struct { + metav1.TypeMeta `json:",inline"` + // Standard list metadata. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds + // +optional + metav1.ListMeta `json:"metadata,omitempty"` + + // Items is a list of Placements. + Items []Placement `json:"items"` +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:resource:scope="Namespaced" +// +kubebuilder:subresource:status + +// PlacementDecision indicates a decision from a placement +// PlacementDecision should has a label cluster.open-cluster-management.io/placement={placement name} +// to reference a certain placement. +// +// If a placement has spec.numberOfClusters specified, the total number of decisions contained in +// status.decisions of PlacementDecisions should always be NumberOfClusters; otherwise, the total +// number of decisions should be the number of ManagedClusters which match the placement requirements. +// +// Some of the decisions might be empty when there are no enough ManagedClusters meet the placement +// requirements. +type PlacementDecision struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Status represents the current status of the PlacementDecision + // +optional + Status PlacementDecisionStatus `json:"status,omitempty"` +} + +// PlacementDecisionStatus represents the current status of the PlacementDecision. +type PlacementDecisionStatus struct { + // Decisions is a slice of decisions according to a placement + // The number of decisions should not be larger than 100 + // +kubebuilder:validation:Required + // +required + Decisions []ClusterDecision `json:"decisions"` +} + +// ClusterDecision represents a decision from a placement +// An empty ClusterDecision indicates it is not scheduled yet. +type ClusterDecision struct { + // ClusterName is the name of the ManagedCluster. If it is not empty, its value should be unique cross all + // placement decisions for the Placement. + // +kubebuilder:validation:Required + // +required + ClusterName string `json:"clusterName"` + + // Reason represents the reason why the ManagedCluster is selected. + // +kubebuilder:validation:Required + // +required + Reason string `json:"reason"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ClusterDecisionList is a collection of PlacementDecision. +type PlacementDecisionList struct { + metav1.TypeMeta `json:",inline"` + // Standard list metadata. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds + // +optional + metav1.ListMeta `json:"metadata,omitempty"` + + // Items is a list of PlacementDecision. + Items []PlacementDecision `json:"items"` +} diff --git a/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/zz_generated.deepcopy.go b/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 0000000000..7344a96e67 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,534 @@ +// +build !ignore_autogenerated + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterClaim) DeepCopyInto(out *ClusterClaim) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterClaim. +func (in *ClusterClaim) DeepCopy() *ClusterClaim { + if in == nil { + return nil + } + out := new(ClusterClaim) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterClaim) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterClaimList) DeepCopyInto(out *ClusterClaimList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ClusterClaim, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterClaimList. +func (in *ClusterClaimList) DeepCopy() *ClusterClaimList { + if in == nil { + return nil + } + out := new(ClusterClaimList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterClaimList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterClaimSelector) DeepCopyInto(out *ClusterClaimSelector) { + *out = *in + if in.MatchExpressions != nil { + in, out := &in.MatchExpressions, &out.MatchExpressions + *out = make([]v1.LabelSelectorRequirement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterClaimSelector. +func (in *ClusterClaimSelector) DeepCopy() *ClusterClaimSelector { + if in == nil { + return nil + } + out := new(ClusterClaimSelector) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterClaimSpec) DeepCopyInto(out *ClusterClaimSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterClaimSpec. +func (in *ClusterClaimSpec) DeepCopy() *ClusterClaimSpec { + if in == nil { + return nil + } + out := new(ClusterClaimSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterDecision) DeepCopyInto(out *ClusterDecision) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterDecision. +func (in *ClusterDecision) DeepCopy() *ClusterDecision { + if in == nil { + return nil + } + out := new(ClusterDecision) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterPredicate) DeepCopyInto(out *ClusterPredicate) { + *out = *in + in.RequiredClusterSelector.DeepCopyInto(&out.RequiredClusterSelector) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterPredicate. +func (in *ClusterPredicate) DeepCopy() *ClusterPredicate { + if in == nil { + return nil + } + out := new(ClusterPredicate) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterSelector) DeepCopyInto(out *ClusterSelector) { + *out = *in + in.LabelSelector.DeepCopyInto(&out.LabelSelector) + in.ClaimSelector.DeepCopyInto(&out.ClaimSelector) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterSelector. +func (in *ClusterSelector) DeepCopy() *ClusterSelector { + if in == nil { + return nil + } + out := new(ClusterSelector) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClusterSet) DeepCopyInto(out *ManagedClusterSet) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClusterSet. +func (in *ManagedClusterSet) DeepCopy() *ManagedClusterSet { + if in == nil { + return nil + } + out := new(ManagedClusterSet) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ManagedClusterSet) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClusterSetBinding) DeepCopyInto(out *ManagedClusterSetBinding) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClusterSetBinding. +func (in *ManagedClusterSetBinding) DeepCopy() *ManagedClusterSetBinding { + if in == nil { + return nil + } + out := new(ManagedClusterSetBinding) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ManagedClusterSetBinding) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClusterSetBindingList) DeepCopyInto(out *ManagedClusterSetBindingList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ManagedClusterSetBinding, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClusterSetBindingList. +func (in *ManagedClusterSetBindingList) DeepCopy() *ManagedClusterSetBindingList { + if in == nil { + return nil + } + out := new(ManagedClusterSetBindingList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ManagedClusterSetBindingList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClusterSetBindingSpec) DeepCopyInto(out *ManagedClusterSetBindingSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClusterSetBindingSpec. +func (in *ManagedClusterSetBindingSpec) DeepCopy() *ManagedClusterSetBindingSpec { + if in == nil { + return nil + } + out := new(ManagedClusterSetBindingSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClusterSetList) DeepCopyInto(out *ManagedClusterSetList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ManagedClusterSet, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClusterSetList. +func (in *ManagedClusterSetList) DeepCopy() *ManagedClusterSetList { + if in == nil { + return nil + } + out := new(ManagedClusterSetList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ManagedClusterSetList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClusterSetSpec) DeepCopyInto(out *ManagedClusterSetSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClusterSetSpec. +func (in *ManagedClusterSetSpec) DeepCopy() *ManagedClusterSetSpec { + if in == nil { + return nil + } + out := new(ManagedClusterSetSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClusterSetStatus) DeepCopyInto(out *ManagedClusterSetStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClusterSetStatus. +func (in *ManagedClusterSetStatus) DeepCopy() *ManagedClusterSetStatus { + if in == nil { + return nil + } + out := new(ManagedClusterSetStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Placement) DeepCopyInto(out *Placement) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Placement. +func (in *Placement) DeepCopy() *Placement { + if in == nil { + return nil + } + out := new(Placement) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Placement) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PlacementDecision) DeepCopyInto(out *PlacementDecision) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlacementDecision. +func (in *PlacementDecision) DeepCopy() *PlacementDecision { + if in == nil { + return nil + } + out := new(PlacementDecision) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PlacementDecision) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PlacementDecisionList) DeepCopyInto(out *PlacementDecisionList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]PlacementDecision, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlacementDecisionList. +func (in *PlacementDecisionList) DeepCopy() *PlacementDecisionList { + if in == nil { + return nil + } + out := new(PlacementDecisionList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PlacementDecisionList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PlacementDecisionStatus) DeepCopyInto(out *PlacementDecisionStatus) { + *out = *in + if in.Decisions != nil { + in, out := &in.Decisions, &out.Decisions + *out = make([]ClusterDecision, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlacementDecisionStatus. +func (in *PlacementDecisionStatus) DeepCopy() *PlacementDecisionStatus { + if in == nil { + return nil + } + out := new(PlacementDecisionStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PlacementList) DeepCopyInto(out *PlacementList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Placement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlacementList. +func (in *PlacementList) DeepCopy() *PlacementList { + if in == nil { + return nil + } + out := new(PlacementList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PlacementList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PlacementSpec) DeepCopyInto(out *PlacementSpec) { + *out = *in + if in.ClusterSets != nil { + in, out := &in.ClusterSets, &out.ClusterSets + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.NumberOfClusters != nil { + in, out := &in.NumberOfClusters, &out.NumberOfClusters + *out = new(int32) + **out = **in + } + if in.Predicates != nil { + in, out := &in.Predicates, &out.Predicates + *out = make([]ClusterPredicate, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlacementSpec. +func (in *PlacementSpec) DeepCopy() *PlacementSpec { + if in == nil { + return nil + } + out := new(PlacementSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PlacementStatus) DeepCopyInto(out *PlacementStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlacementStatus. +func (in *PlacementStatus) DeepCopy() *PlacementStatus { + if in == nil { + return nil + } + out := new(PlacementStatus) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/zz_generated.swagger_doc_generated.go b/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/zz_generated.swagger_doc_generated.go new file mode 100644 index 0000000000..79653cb612 --- /dev/null +++ b/vendor/github.com/open-cluster-management/api/cluster/v1alpha1/zz_generated.swagger_doc_generated.go @@ -0,0 +1,212 @@ +package v1alpha1 + +// This file contains a collection of methods that can be used from go-restful to +// generate Swagger API documentation for its models. Please read this PR for more +// information on the implementation: https://github.com/emicklei/go-restful/pull/215 +// +// TODOs are ignored from the parser (e.g. TODO(andronat):... || TODO:...) if and only if +// they are on one line! For multiple line or blocks that you want to ignore use ---. +// Any context after a --- is ignored. +// +// Those methods can be generated by using hack/update-swagger-docs.sh + +// AUTO-GENERATED FUNCTIONS START HERE +var map_ClusterClaim = map[string]string{ + "": "ClusterClaim represents cluster information that a managed cluster claims ClusterClaims with well known names include,\n 1. id.k8s.io, it contains a unique identifier for the cluster.\n 2. clusterset.k8s.io, it contains an identifier that relates the cluster\n to the ClusterSet in which it belongs.\nClusterClaims created on a managed cluster will be collected and saved into the status of the corresponding ManagedCluster on hub.", + "spec": "Spec defines the attributes of the ClusterClaim.", +} + +func (ClusterClaim) SwaggerDoc() map[string]string { + return map_ClusterClaim +} + +var map_ClusterClaimList = map[string]string{ + "": "ClusterClaimList is a collection of ClusterClaim.", + "metadata": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "items": "Items is a list of ClusterClaim.", +} + +func (ClusterClaimList) SwaggerDoc() map[string]string { + return map_ClusterClaimList +} + +var map_ClusterClaimSelector = map[string]string{ + "": "ClusterClaimSelector is a claim query over a set of ManagedClusters. An empty cluster claim selector matches all objects. A null cluster claim selector matches no objects.", + "matchExpressions": "matchExpressions is a list of cluster claim selector requirements. The requirements are ANDed.", +} + +func (ClusterClaimSelector) SwaggerDoc() map[string]string { + return map_ClusterClaimSelector +} + +var map_ClusterClaimSpec = map[string]string{ + "value": "Value is a claim-dependent string", +} + +func (ClusterClaimSpec) SwaggerDoc() map[string]string { + return map_ClusterClaimSpec +} + +var map_ClusterDecision = map[string]string{ + "": "ClusterDecision represents a decision from a placement An empty ClusterDecision indicates it is not scheduled yet.", + "clusterName": "ClusterName is the name of the ManagedCluster. If it is not empty, its value should be unique cross all placement decisions for the Placement.", + "reason": "Reason represents the reason why the ManagedCluster is selected.", +} + +func (ClusterDecision) SwaggerDoc() map[string]string { + return map_ClusterDecision +} + +var map_ClusterPredicate = map[string]string{ + "": "ClusterPredicate represents a predicate to select ManagedClusters.", + "requiredClusterSelector": "RequiredClusterSelector represents a selector of ManagedClusters by label and claim. If specified, 1) Any ManagedCluster, which does not match the selector, should not be selected by this ClusterPredicate; 2) If a selected ManagedCluster (of this ClusterPredicate) ceases to match the selector (e.g. due to\n an update) of any ClusterPredicate, it will be eventually removed from the placement decisions;\n3) If a ManagedCluster (not selected previously) starts to match the selector, it will either\n be selected or at least has a chance to be selected (when NumberOfClusters is specified);", +} + +func (ClusterPredicate) SwaggerDoc() map[string]string { + return map_ClusterPredicate +} + +var map_ClusterSelector = map[string]string{ + "": "ClusterSelector represents the AND of the containing selectors. An empty cluster selector matches all objects. A null cluster selector matches no objects.", + "labelSelector": "LabelSelector represents a selector of ManagedClusters by label", + "claimSelector": "ClaimSelector represents a selector of ManagedClusters by clusterClaims in status", +} + +func (ClusterSelector) SwaggerDoc() map[string]string { + return map_ClusterSelector +} + +var map_ManagedClusterSet = map[string]string{ + "": "ManagedClusterSet defines a group of ManagedClusters that user's workload can run on. A workload can be defined to deployed on a ManagedClusterSet, which mean:\n 1. The workload can run on any ManagedCluster in the ManagedClusterSet\n 2. The workload cannot run on any ManagedCluster outside the ManagedClusterSet\n 3. The service exposed by the workload can be shared in any ManagedCluster in the ManagedClusterSet\n\nIn order to assign a ManagedCluster to a certian ManagedClusterSet, add a label with name `cluster.open-cluster-management.io/clusterset` on the ManagedCluster to refers to the ManagedClusterSet. User is not allow to add/remove this label on a ManagedCluster unless they have a RBAC rule to CREATE on a virtual subresource of managedclustersets/join. In order to update this label, user must have the permission on both the old and new ManagedClusterSet.", + "spec": "Spec defines the attributes of the ManagedClusterSet", + "status": "Status represents the current status of the ManagedClusterSet", +} + +func (ManagedClusterSet) SwaggerDoc() map[string]string { + return map_ManagedClusterSet +} + +var map_ManagedClusterSetBinding = map[string]string{ + "": "ManagedClusterSetBinding projects a ManagedClusterSet into a certain namespace. User is able to create a ManagedClusterSetBinding in a namespace and bind it to a ManagedClusterSet if they have an RBAC rule to CREATE on the virtual subresource of managedclustersets/bind. Workloads created in the same namespace can only be distributed to ManagedClusters in ManagedClusterSets bound in this namespace by higher level controllers.", + "spec": "Spec defines the attributes of ManagedClusterSetBinding.", +} + +func (ManagedClusterSetBinding) SwaggerDoc() map[string]string { + return map_ManagedClusterSetBinding +} + +var map_ManagedClusterSetBindingList = map[string]string{ + "": "ManagedClusterSetBindingList is a collection of ManagedClusterSetBinding.", + "metadata": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "items": "Items is a list of ManagedClusterSetBinding.", +} + +func (ManagedClusterSetBindingList) SwaggerDoc() map[string]string { + return map_ManagedClusterSetBindingList +} + +var map_ManagedClusterSetBindingSpec = map[string]string{ + "": "ManagedClusterSetBindingSpec defines the attributes of ManagedClusterSetBinding.", + "clusterSet": "ClusterSet is the name of the ManagedClusterSet to bind. It must match the instance name of the ManagedClusterSetBinding and cannot change once created. User is allowed to set this field if they have an RBAC rule to CREATE on the virtual subresource of managedclustersets/bind.", +} + +func (ManagedClusterSetBindingSpec) SwaggerDoc() map[string]string { + return map_ManagedClusterSetBindingSpec +} + +var map_ManagedClusterSetList = map[string]string{ + "": "ManagedClusterSetList is a collection of ManagedClusterSet.", + "metadata": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "items": "Items is a list of ManagedClusterSet.", +} + +func (ManagedClusterSetList) SwaggerDoc() map[string]string { + return map_ManagedClusterSetList +} + +var map_ManagedClusterSetSpec = map[string]string{ + "": "ManagedClusterSetSpec describes the attributes of the ManagedClusterSet", +} + +func (ManagedClusterSetSpec) SwaggerDoc() map[string]string { + return map_ManagedClusterSetSpec +} + +var map_ManagedClusterSetStatus = map[string]string{ + "": "ManagedClusterSetStatus represents the current status of the ManagedClusterSet.", + "conditions": "Conditions contains the different condition statuses for this ManagedClusterSet.", +} + +func (ManagedClusterSetStatus) SwaggerDoc() map[string]string { + return map_ManagedClusterSetStatus +} + +var map_Placement = map[string]string{ + "": "Placement defines a rule to select a set of ManagedClusters from the ManagedClusterSets bound to the placement namespace.\n\nHere is how the placement policy combines with other selection methods to determine a matching list of ManagedClusters: 1) Kubernetes clusters are registered with hub as cluster-scoped ManagedClusters; 2) ManagedClusters are organized into cluster-scoped ManagedClusterSets; 3) ManagedClusterSets are bound to workload namespaces; 4) Namespace-scoped Placements specify a slice of ManagedClusterSets which select a working set\n of potential ManagedClusters;\n5) Then Placements subselect from that working set using label/claim selection.\n\nNo ManagedCluster will be selected if no ManagedClusterSet is bound to the placement namespace. User is able to bind a ManagedClusterSet to a namespace by creating a ManagedClusterSetBinding in that namespace if they have a RBAC rule to CREATE on the virtual subresource of `managedclustersets/bind`.\n\nA slice of PlacementDecisions with label cluster.open-cluster-management.io/placement={placement name} will be created to represent the ManagedClusters selected by this placement.\n\nIf a ManagedCluster is selected and added into the PlacementDecisions, other components may apply workload on it; once it is removed from the PlacementDecisions, the workload applied on this ManagedCluster should be evicted accordingly.", + "spec": "Spec defines the attributes of Placement.", + "status": "Status represents the current status of the Placement", +} + +func (Placement) SwaggerDoc() map[string]string { + return map_Placement +} + +var map_PlacementDecision = map[string]string{ + "": "PlacementDecision indicates a decision from a placement PlacementDecision should has a label cluster.open-cluster-management.io/placement={placement name} to reference a certain placement.\n\nIf a placement has spec.numberOfClusters specified, the total number of decisions contained in status.decisions of PlacementDecisions should always be NumberOfClusters; otherwise, the total number of decisions should be the number of ManagedClusters which match the placement requirements.\n\nSome of the decisions might be empty when there are no enough ManagedClusters meet the placement requirements.", + "status": "Status represents the current status of the PlacementDecision", +} + +func (PlacementDecision) SwaggerDoc() map[string]string { + return map_PlacementDecision +} + +var map_PlacementDecisionList = map[string]string{ + "": "ClusterDecisionList is a collection of PlacementDecision.", + "metadata": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "items": "Items is a list of PlacementDecision.", +} + +func (PlacementDecisionList) SwaggerDoc() map[string]string { + return map_PlacementDecisionList +} + +var map_PlacementDecisionStatus = map[string]string{ + "": "PlacementDecisionStatus represents the current status of the PlacementDecision.", + "decisions": "Decisions is a slice of decisions according to a placement The number of decisions should not be larger than 100", +} + +func (PlacementDecisionStatus) SwaggerDoc() map[string]string { + return map_PlacementDecisionStatus +} + +var map_PlacementList = map[string]string{ + "": "PlacementList is a collection of Placements.", + "metadata": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "items": "Items is a list of Placements.", +} + +func (PlacementList) SwaggerDoc() map[string]string { + return map_PlacementList +} + +var map_PlacementSpec = map[string]string{ + "": "PlacementSpec defines the attributes of Placement. An empty PlacementSpec selects all ManagedClusters from the ManagedClusterSets bound to the placement namespace. The containing fields are ANDed.", + "clusterSets": "ClusterSets represent the ManagedClusterSets from which the ManagedClusters are selected. If the slice is empty, ManagedClusters will be selected from the ManagedClusterSets bound to the placement namespace, otherwise ManagedClusters will be selected from the intersection of this slice and the ManagedClusterSets bound to the placement namespace.", + "numberOfClusters": "NumberOfClusters represents the desired number of ManagedClusters to be selected which meet the placement requirements. 1) If not specified, all ManagedClusters which meet the placement requirements (including ClusterSets,\n and Predicates) will be selected;\n2) Otherwise if the nubmer of ManagedClusters meet the placement requirements is larger than\n NumberOfClusters, a random subset with desired number of ManagedClusters will be selected;\n3) If the nubmer of ManagedClusters meet the placement requirements is equal to NumberOfClusters,\n all of them will be selected;\n4) If the nubmer of ManagedClusters meet the placement requirements is less than NumberOfClusters,\n all of them will be selected, and the status of condition `PlacementConditionSatisfied` will be\n set to false;", + "predicates": "Predicates represent a slice of predicates to select ManagedClusters. The predicates are ORed.", +} + +func (PlacementSpec) SwaggerDoc() map[string]string { + return map_PlacementSpec +} + +var map_PlacementStatus = map[string]string{ + "numberOfSelectedClusters": "NumberOfSelectedClusters represents the number of selected ManagedClusters", + "conditions": "Conditions contains the different condition statuses for this Placement.", +} + +func (PlacementStatus) SwaggerDoc() map[string]string { + return map_PlacementStatus +} + +// AUTO-GENERATED FUNCTIONS END HERE diff --git a/vendor/modules.txt b/vendor/modules.txt index 17a5a46488..6803c59ea3 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -98,6 +98,21 @@ github.com/modern-go/concurrent github.com/modern-go/reflect2 # github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 github.com/munnerz/goautoneg +# github.com/open-cluster-management/api v0.0.0-20210527013639-a6845f2ebcb1 +## explicit +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 +github.com/open-cluster-management/api/client/cluster/clientset/versioned/typed/cluster/v1alpha1 +github.com/open-cluster-management/api/client/cluster/informers/externalversions +github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster +github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1 +github.com/open-cluster-management/api/client/cluster/informers/externalversions/cluster/v1alpha1 +github.com/open-cluster-management/api/client/cluster/informers/externalversions/internalinterfaces +github.com/open-cluster-management/api/client/cluster/listers/cluster/v1 +github.com/open-cluster-management/api/client/cluster/listers/cluster/v1alpha1 +github.com/open-cluster-management/api/cluster/v1 +github.com/open-cluster-management/api/cluster/v1alpha1 # github.com/openshift/api v0.0.0-20210729103544-e4a0474d1519 ## explicit github.com/openshift/api From 48116add593d4bbbd5c9821a37ea280cb79a7c4e Mon Sep 17 00:00:00 2001 From: Bryan Florkiewicz Date: Thu, 23 Sep 2021 10:14:26 -0400 Subject: [PATCH 2/3] [WIP] CONSOLE 2919: create OAuth clients on spoke clusters Creates oauth clients on spoke clusters using the new managed cluster controller via a dynamic client. CONSOLE 2919: clean up oauth client impl on spoke clusters Add informers for CRD changes via dyanmic informer --- ...anaged-cluster-ingress-cert-configmap.yaml | 4 + ...ed-cluster-action-create-oauth-client.yaml | 14 ++ ...ole-managed-cluster-view-ingress-cert.yaml | 10 + ...ole-managed-cluster-view-oauth-client.yaml | 9 + manifests/03-rbac-role-cluster.yaml | 22 +++ pkg/api/api.go | 3 + pkg/console/assets/bindata.go | 144 ++++++++++++-- .../controllers/managedclusters/controller.go | 187 +++++++++++++++++- pkg/console/starter/starter.go | 17 ++ .../configmap/managed_cluster_ingress_cert.go | 37 ++++ .../managed_cluster_action.go | 45 +++++ .../managed_cluster_view.go | 85 ++++++++ .../subresource/oauthclient/oauthclient.go | 4 + pkg/console/subresource/util/util.go | 12 ++ .../dynamic/dynamicinformer/informer.go | 158 +++++++++++++++ .../dynamic/dynamicinformer/interface.go | 34 ++++ .../dynamic/dynamiclister/interface.go | 40 ++++ .../client-go/dynamic/dynamiclister/lister.go | 91 +++++++++ .../client-go/dynamic/dynamiclister/shim.go | 87 ++++++++ vendor/modules.txt | 2 + 20 files changed, 992 insertions(+), 13 deletions(-) create mode 100644 bindata/configmaps/console-managed-cluster-ingress-cert-configmap.yaml create mode 100644 bindata/managedclusteractions/console-managed-cluster-action-create-oauth-client.yaml create mode 100644 bindata/managedclusterviews/console-managed-cluster-view-ingress-cert.yaml create mode 100644 bindata/managedclusterviews/console-managed-cluster-view-oauth-client.yaml create mode 100644 pkg/console/subresource/configmap/managed_cluster_ingress_cert.go create mode 100644 pkg/console/subresource/managedclusteraction/managed_cluster_action.go create mode 100644 pkg/console/subresource/managedclusterview/managed_cluster_view.go create mode 100644 vendor/k8s.io/client-go/dynamic/dynamicinformer/informer.go create mode 100644 vendor/k8s.io/client-go/dynamic/dynamicinformer/interface.go create mode 100644 vendor/k8s.io/client-go/dynamic/dynamiclister/interface.go create mode 100644 vendor/k8s.io/client-go/dynamic/dynamiclister/lister.go create mode 100644 vendor/k8s.io/client-go/dynamic/dynamiclister/shim.go diff --git a/bindata/configmaps/console-managed-cluster-ingress-cert-configmap.yaml b/bindata/configmaps/console-managed-cluster-ingress-cert-configmap.yaml new file mode 100644 index 0000000000..f39c2d0e06 --- /dev/null +++ b/bindata/configmaps/console-managed-cluster-ingress-cert-configmap.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: openshift-config-managed diff --git a/bindata/managedclusteractions/console-managed-cluster-action-create-oauth-client.yaml b/bindata/managedclusteractions/console-managed-cluster-action-create-oauth-client.yaml new file mode 100644 index 0000000000..80a209a080 --- /dev/null +++ b/bindata/managedclusteractions/console-managed-cluster-action-create-oauth-client.yaml @@ -0,0 +1,14 @@ +apiVersion: action.open-cluster-management.io/v1beta1 +kind: ManagedClusterAction +metadata: + name: console-managed-cluster-action-oauth-create +spec: + actionType: Create + kube: + resource: OAuthClient + template: + apiVersion: oauth.openshift.io/v1 + kind: OAuthClient + metadata: + name: console-managed-cluster-oauth-client + grantMethod: auto \ No newline at end of file diff --git a/bindata/managedclusterviews/console-managed-cluster-view-ingress-cert.yaml b/bindata/managedclusterviews/console-managed-cluster-view-ingress-cert.yaml new file mode 100644 index 0000000000..c72a7e6117 --- /dev/null +++ b/bindata/managedclusterviews/console-managed-cluster-view-ingress-cert.yaml @@ -0,0 +1,10 @@ +apiVersion: view.open-cluster-management.io/v1beta1 +kind: ManagedClusterView +metadata: + name: console-managed-cluster-view-ingress-cert +spec: + scope: + kind: ConfigMap + version: v1 + name: default-ingress-cert + namespace: openshift-config-managed diff --git a/bindata/managedclusterviews/console-managed-cluster-view-oauth-client.yaml b/bindata/managedclusterviews/console-managed-cluster-view-oauth-client.yaml new file mode 100644 index 0000000000..b4875bcc51 --- /dev/null +++ b/bindata/managedclusterviews/console-managed-cluster-view-oauth-client.yaml @@ -0,0 +1,9 @@ +apiVersion: view.open-cluster-management.io/v1beta1 +kind: ManagedClusterView +metadata: + name: console-managed-cluster-view-oauth +spec: + scope: + apiVersion: oauth.openshift.io/v1 + resource: OAuthClient + name: console-managed-cluster-oauth-client diff --git a/manifests/03-rbac-role-cluster.yaml b/manifests/03-rbac-role-cluster.yaml index 99d6f9372f..c10bb6ba1e 100644 --- a/manifests/03-rbac-role-cluster.yaml +++ b/manifests/03-rbac-role-cluster.yaml @@ -88,6 +88,28 @@ rules: - get - list - watch + - apiGroups: + - action.open-cluster-management.io + resources: + - managedclusteractions + verbs: + - get + - list + - watch + - create + - update + - delete + - apiGroups: + - view.open-cluster-management.io + resources: + - managedclusterviews + verbs: + - get + - list + - watch + - create + - update + - delete --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 diff --git a/pkg/api/api.go b/pkg/api/api.go index 76f44b65c3..ad934fc46f 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -17,6 +17,7 @@ const ( ServiceCAConfigMapName = "service-ca" DefaultIngressCertConfigMapName = "default-ingress-cert" OAuthServingCertConfigMapName = "oauth-serving-cert" + OAuthConfigMapName = "oauth-openshift" OpenShiftConsoleDeploymentName = OpenShiftConsoleName OpenShiftConsoleServiceName = OpenShiftConsoleName OpenshiftConsoleRedirectServiceName = "console-redirect" @@ -43,6 +44,8 @@ const ( ManagedClusterAPIServerCAMountDir = "/var/managed-cluster-certs" ManagedClusterAPIServerCAName = "managed-cluster-api-server-ca" ManagedClusterAPIServerCAKey = "ca-bundle.crt" + ManagedClusterIngressCertName = "managed-cluster-ingress-cert" + ManagedClusterIngressCertKey = "ca-bundle.crt" ConsoleContainerPortName = "https" ConsoleContainerPort = 443 diff --git a/pkg/console/assets/bindata.go b/pkg/console/assets/bindata.go index f732d7e8eb..afe47c5490 100644 --- a/pkg/console/assets/bindata.go +++ b/pkg/console/assets/bindata.go @@ -1,8 +1,12 @@ // Code generated for package assets by go-bindata DO NOT EDIT. (@generated) // sources: +// bindata/configmaps/console-managed-cluster-ingress-cert-configmap.yaml // bindata/configmaps/console-public-configmap.yaml // bindata/deployments/console-deployment.yaml // bindata/deployments/downloads-deployment.yaml +// bindata/managedclusteractions/console-managed-cluster-action-create-oauth-client.yaml +// bindata/managedclusterviews/console-managed-cluster-view-ingress-cert.yaml +// bindata/managedclusterviews/console-managed-cluster-view-oauth-client.yaml // bindata/routes/console-custom-route.yaml // bindata/routes/console-redirect-route.yaml // bindata/routes/console-route.yaml @@ -64,6 +68,27 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } +var _configmapsConsoleManagedClusterIngressCertConfigmapYaml = []byte(`apiVersion: v1 +kind: ConfigMap +metadata: + namespace: openshift-config-managed +`) + +func configmapsConsoleManagedClusterIngressCertConfigmapYamlBytes() ([]byte, error) { + return _configmapsConsoleManagedClusterIngressCertConfigmapYaml, nil +} + +func configmapsConsoleManagedClusterIngressCertConfigmapYaml() (*asset, error) { + bytes, err := configmapsConsoleManagedClusterIngressCertConfigmapYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "configmaps/console-managed-cluster-ingress-cert-configmap.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + var _configmapsConsolePublicConfigmapYaml = []byte(`# This configmap 'console-public' manifest is used to expose the console URL # to all authenticated users apiVersion: v1 @@ -402,6 +427,89 @@ func deploymentsDownloadsDeploymentYaml() (*asset, error) { return a, nil } +var _managedclusteractionsConsoleManagedClusterActionCreateOauthClientYaml = []byte(`apiVersion: action.open-cluster-management.io/v1beta1 +kind: ManagedClusterAction +metadata: + name: console-managed-cluster-action-oauth-create +spec: + actionType: Create + kube: + resource: OAuthClient + template: + apiVersion: oauth.openshift.io/v1 + kind: OAuthClient + metadata: + name: console-managed-cluster-oauth-client + grantMethod: auto`) + +func managedclusteractionsConsoleManagedClusterActionCreateOauthClientYamlBytes() ([]byte, error) { + return _managedclusteractionsConsoleManagedClusterActionCreateOauthClientYaml, nil +} + +func managedclusteractionsConsoleManagedClusterActionCreateOauthClientYaml() (*asset, error) { + bytes, err := managedclusteractionsConsoleManagedClusterActionCreateOauthClientYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "managedclusteractions/console-managed-cluster-action-create-oauth-client.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _managedclusterviewsConsoleManagedClusterViewIngressCertYaml = []byte(`apiVersion: view.open-cluster-management.io/v1beta1 +kind: ManagedClusterView +metadata: + name: console-managed-cluster-view-ingress-cert +spec: + scope: + kind: ConfigMap + version: v1 + name: default-ingress-cert + namespace: openshift-config-managed +`) + +func managedclusterviewsConsoleManagedClusterViewIngressCertYamlBytes() ([]byte, error) { + return _managedclusterviewsConsoleManagedClusterViewIngressCertYaml, nil +} + +func managedclusterviewsConsoleManagedClusterViewIngressCertYaml() (*asset, error) { + bytes, err := managedclusterviewsConsoleManagedClusterViewIngressCertYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "managedclusterviews/console-managed-cluster-view-ingress-cert.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _managedclusterviewsConsoleManagedClusterViewOauthClientYaml = []byte(`apiVersion: view.open-cluster-management.io/v1beta1 +kind: ManagedClusterView +metadata: + name: console-managed-cluster-view-oauth +spec: + scope: + apiVersion: oauth.openshift.io/v1 + resource: OAuthClient + name: console-managed-cluster-oauth-client +`) + +func managedclusterviewsConsoleManagedClusterViewOauthClientYamlBytes() ([]byte, error) { + return _managedclusterviewsConsoleManagedClusterViewOauthClientYaml, nil +} + +func managedclusterviewsConsoleManagedClusterViewOauthClientYaml() (*asset, error) { + bytes, err := managedclusterviewsConsoleManagedClusterViewOauthClientYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "managedclusterviews/console-managed-cluster-view-oauth-client.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + var _routesConsoleCustomRouteYaml = []byte(`# This route 'console-custom' manifest is used in case a custom console route is set # either on the ingress config or console-operator config. # The 'console-custom' route will be pointing to the 'console' service. @@ -757,17 +865,21 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ - "configmaps/console-public-configmap.yaml": configmapsConsolePublicConfigmapYaml, - "deployments/console-deployment.yaml": deploymentsConsoleDeploymentYaml, - "deployments/downloads-deployment.yaml": deploymentsDownloadsDeploymentYaml, - "routes/console-custom-route.yaml": routesConsoleCustomRouteYaml, - "routes/console-redirect-route.yaml": routesConsoleRedirectRouteYaml, - "routes/console-route.yaml": routesConsoleRouteYaml, - "routes/downloads-custom-route.yaml": routesDownloadsCustomRouteYaml, - "routes/downloads-route.yaml": routesDownloadsRouteYaml, - "services/console-redirect-service.yaml": servicesConsoleRedirectServiceYaml, - "services/console-service.yaml": servicesConsoleServiceYaml, - "services/downloads-service.yaml": servicesDownloadsServiceYaml, + "configmaps/console-managed-cluster-ingress-cert-configmap.yaml": configmapsConsoleManagedClusterIngressCertConfigmapYaml, + "configmaps/console-public-configmap.yaml": configmapsConsolePublicConfigmapYaml, + "deployments/console-deployment.yaml": deploymentsConsoleDeploymentYaml, + "deployments/downloads-deployment.yaml": deploymentsDownloadsDeploymentYaml, + "managedclusteractions/console-managed-cluster-action-create-oauth-client.yaml": managedclusteractionsConsoleManagedClusterActionCreateOauthClientYaml, + "managedclusterviews/console-managed-cluster-view-ingress-cert.yaml": managedclusterviewsConsoleManagedClusterViewIngressCertYaml, + "managedclusterviews/console-managed-cluster-view-oauth-client.yaml": managedclusterviewsConsoleManagedClusterViewOauthClientYaml, + "routes/console-custom-route.yaml": routesConsoleCustomRouteYaml, + "routes/console-redirect-route.yaml": routesConsoleRedirectRouteYaml, + "routes/console-route.yaml": routesConsoleRouteYaml, + "routes/downloads-custom-route.yaml": routesDownloadsCustomRouteYaml, + "routes/downloads-route.yaml": routesDownloadsRouteYaml, + "services/console-redirect-service.yaml": servicesConsoleRedirectServiceYaml, + "services/console-service.yaml": servicesConsoleServiceYaml, + "services/downloads-service.yaml": servicesDownloadsServiceYaml, } // AssetDir returns the file names below a certain @@ -812,12 +924,20 @@ type bintree struct { var _bintree = &bintree{nil, map[string]*bintree{ "configmaps": {nil, map[string]*bintree{ - "console-public-configmap.yaml": {configmapsConsolePublicConfigmapYaml, map[string]*bintree{}}, + "console-managed-cluster-ingress-cert-configmap.yaml": {configmapsConsoleManagedClusterIngressCertConfigmapYaml, map[string]*bintree{}}, + "console-public-configmap.yaml": {configmapsConsolePublicConfigmapYaml, map[string]*bintree{}}, }}, "deployments": {nil, map[string]*bintree{ "console-deployment.yaml": {deploymentsConsoleDeploymentYaml, map[string]*bintree{}}, "downloads-deployment.yaml": {deploymentsDownloadsDeploymentYaml, map[string]*bintree{}}, }}, + "managedclusteractions": {nil, map[string]*bintree{ + "console-managed-cluster-action-create-oauth-client.yaml": {managedclusteractionsConsoleManagedClusterActionCreateOauthClientYaml, map[string]*bintree{}}, + }}, + "managedclusterviews": {nil, map[string]*bintree{ + "console-managed-cluster-view-ingress-cert.yaml": {managedclusterviewsConsoleManagedClusterViewIngressCertYaml, map[string]*bintree{}}, + "console-managed-cluster-view-oauth-client.yaml": {managedclusterviewsConsoleManagedClusterViewOauthClientYaml, map[string]*bintree{}}, + }}, "routes": {nil, map[string]*bintree{ "console-custom-route.yaml": {routesConsoleCustomRouteYaml, map[string]*bintree{}}, "console-redirect-route.yaml": {routesConsoleRedirectRouteYaml, map[string]*bintree{}}, diff --git a/pkg/console/controllers/managedclusters/controller.go b/pkg/console/controllers/managedclusters/controller.go index d2eb9e36f7..832900576d 100644 --- a/pkg/console/controllers/managedclusters/controller.go +++ b/pkg/console/controllers/managedclusters/controller.go @@ -9,6 +9,9 @@ import ( // k8s apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/dynamic/dynamicinformer" coreclientv1 "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/klog/v2" @@ -19,6 +22,7 @@ import ( operatorv1 "github.com/openshift/api/operator/v1" configclientv1 "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1" configinformer "github.com/openshift/client-go/config/informers/externalversions" + oauthclientv1 "github.com/openshift/client-go/oauth/clientset/versioned/typed/oauth/v1" operatorclientv1 "github.com/openshift/client-go/operator/clientset/versioned/typed/operator/v1" v1 "github.com/openshift/client-go/operator/informers/externalversions/operator/v1" "github.com/openshift/library-go/pkg/controller/factory" @@ -28,6 +32,10 @@ import ( //subresources configmapsub "github.com/openshift/console-operator/pkg/console/subresource/configmap" + managedclusteractionsub "github.com/openshift/console-operator/pkg/console/subresource/managedclusteraction" + managedclusterviewsub "github.com/openshift/console-operator/pkg/console/subresource/managedclusterview" + oauthsub "github.com/openshift/console-operator/pkg/console/subresource/oauthclient" + secretsub "github.com/openshift/console-operator/pkg/console/subresource/secret" // console-operator "github.com/openshift/console-operator/pkg/api" @@ -41,21 +49,29 @@ type ManagedClusterController struct { operatorConfigClient operatorclientv1.ConsoleInterface configMapClient coreclientv1.ConfigMapsGetter managedClusterClient clusterclientv1.ManagedClustersGetter + dynamicClient dynamic.Interface + secretsClient coreclientv1.SecretsGetter + oauthClient oauthclientv1.OAuthClientsGetter } func NewManagedClusterController( // top level config configClient configclientv1.ConfigV1Interface, configInformer configinformer.SharedInformerFactory, + // clients operatorClient v1helpers.OperatorClient, operatorConfigClient operatorclientv1.ConsoleInterface, configMapClient coreclientv1.ConfigMapsGetter, managedClusterClient clusterclientv1.ClusterV1Interface, + dynamicClient dynamic.Interface, + secretsClient coreclientv1.SecretsGetter, + oauthClient oauthclientv1.OAuthClientsGetter, // informers operatorConfigInformer v1.ConsoleInformer, managedClusterInformers clusterinformersv1.ManagedClusterInformer, + dynamicInformers dynamicinformer.DynamicSharedInformerFactory, // events recorder events.Recorder, @@ -65,6 +81,9 @@ func NewManagedClusterController( operatorConfigClient: operatorConfigClient, configMapClient: configMapClient, managedClusterClient: managedClusterClient, + dynamicClient: dynamicClient, + secretsClient: secretsClient, + oauthClient: oauthClient, } configV1Informers := configInformer.Config().V1() @@ -77,6 +96,10 @@ func NewManagedClusterController( ).WithFilteredEventsInformers( util.ExcludeNamesFilter(api.HubClusterName), managedClusterInformers.Informer(), + ).WithInformers( + dynamicInformers.ForResource(managedclusteractionsub.GetGVR()).Informer(), + ).WithInformers( + dynamicInformers.ForResource(managedclusterviewsub.GetGVR()).Informer(), ).WithSync(ctrl.Sync). ToController("ManagedClusterController", recorder.WithComponentSuffix("managed-cluster-controller")) } @@ -121,6 +144,22 @@ func (c *ManagedClusterController) Sync(ctx context.Context, controllerContext f return statusHandler.FlushAndReturn(apiServerCASyncErr) } + // Create managed cluster views for oauth clients + managedClusterViewOAuthClients, managedClusterViewOAuthClientErr, managedClusterViewOAuthClientErrReason := c.SyncManagedClusterViewOAuthClient(ctx, operatorConfig) + statusHandler.AddConditions(status.HandleProgressingOrDegraded("ManagedClusterViewOAuthClientSync", managedClusterViewOAuthClientErrReason, managedClusterViewOAuthClientErr)) + + // Create managed cluster actions for oauth clients + _, managedClusterActionCreateOAuthClientErr, managedClusterActionCreateOAuthClientErrReason := c.SyncManagedClusterActionCreateOAuthClient(ctx, operatorConfig, managedClusterViewOAuthClients) + statusHandler.AddConditions(status.HandleProgressingOrDegraded("ManagedClusterActionCreateOAuthClientSync", managedClusterActionCreateOAuthClientErrReason, managedClusterActionCreateOAuthClientErr)) + + // Create managed cluster views for ingress cert + managedClusterViewsIngressCert, managedClusterViewIngressCertErr, managedClusterViewIngressCertErrReason := c.SyncManagedClusterViewIngressCert(ctx, operatorConfig) + statusHandler.AddConditions(status.HandleProgressingOrDegraded("ManagedClusterViewIngressCertSync", managedClusterViewIngressCertErrReason, managedClusterViewIngressCertErr)) + + // Create config maps for each managed cluster ingress cert bundle + managedClusterIngressCertSyncErr, managedClusterIngressCertSyncErrReason := c.SyncManagedClusterIngressCertConfigMap(managedClusterViewsIngressCert, ctx, operatorConfig, controllerContext.Recorder()) + statusHandler.AddConditions(status.HandleProgressingOrDegraded("ManagedClusterIngressCertConfigMapSync", managedClusterIngressCertSyncErrReason, managedClusterIngressCertSyncErr)) + // Create manged cluster config map configSyncErr, configSyncErrReason := c.SyncManagedClusterConfigMap(managedClusterClientConfigs, ctx, operatorConfig, controllerContext.Recorder()) statusHandler.AddConditions(status.HandleProgressingOrDegraded("ManagedClusterConfigSync", configSyncErrReason, configSyncErr)) @@ -129,7 +168,7 @@ func (c *ManagedClusterController) Sync(ctx context.Context, controllerContext f // Return slice of clusterv1.ClientConfigs that have been validated or error and reaons if unable to list ManagedClusters func (c *ManagedClusterController) ValidateManagedClusterClientConfigs(ctx context.Context, operatorConfig *operatorv1.Console, recorder events.Recorder) (map[string]*clusterv1.ClientConfig, error, string) { - managedClusters, err := c.managedClusterClient.ManagedClusters().List(ctx, metav1.ListOptions{LabelSelector: "local-cluster!=true"}) + managedClusters, err := c.listManagedClusters(ctx) // Not found means API is not on the cluster if apierrors.IsNotFound(err) { @@ -239,6 +278,148 @@ func (c *ManagedClusterController) SyncManagedClusterConfigMap(clientConfigs map return nil, "" } +func (c *ManagedClusterController) SyncManagedClusterViewOAuthClient(ctx context.Context, operatorConfig *operatorv1.Console) ([]*unstructured.Unstructured, error, string) { + managedClusters, listErr := c.listManagedClusters(ctx) + if listErr != nil || len(managedClusters.Items) == 0 { + return nil, listErr, "FailedList" + } + + errs := []string{} + managedClusterOAuthClientViews := []*unstructured.Unstructured{} + for _, managedCluster := range managedClusters.Items { + mcvOAuth := managedclusterviewsub.DefaultViewOAuthClient(operatorConfig, managedCluster.Name) + gvr := managedclusterviewsub.GetGVR() + + oAuthResp, oAuthErr := c.dynamicClient.Resource(gvr).Namespace(managedCluster.Name).Create(ctx, mcvOAuth, metav1.CreateOptions{}) + if oAuthErr != nil && apierrors.IsAlreadyExists(oAuthErr) { + mcvOAuthName, _ := managedclusterviewsub.GetName(mcvOAuth) + oAuthResp, oAuthErr = c.dynamicClient.Resource(gvr).Namespace(managedCluster.Name).Get(ctx, mcvOAuthName, metav1.GetOptions{}) + } + + if oAuthErr != nil || oAuthResp == nil { + errs = append(errs, fmt.Sprintf("Error syncing managed cluster view for oauth client for cluster %s: %v", managedCluster.Name, oAuthErr)) + } else { + managedClusterOAuthClientViews = append(managedClusterOAuthClientViews, oAuthResp) + } + } + + if len(errs) > 0 { + return nil, errors.New(strings.Join(errs, "\n")), "ManagedClusterViewOAuthClientSyncError" + } + + return managedClusterOAuthClientViews, nil, "" +} + +func (c *ManagedClusterController) SyncManagedClusterActionCreateOAuthClient(ctx context.Context, operatorConfig *operatorv1.Console, managedClusterOAuthClientViews []*unstructured.Unstructured) ([]*unstructured.Unstructured, error, string) { + managedClusterList := []string{} + managedClusterListErrors := []string{} + for _, managedClusterOAuthView := range managedClusterOAuthClientViews { + status, statusErr := managedclusterviewsub.GetStatus(managedClusterOAuthView) + if !status || statusErr != nil { + namespace, namespaceErr := managedclusterviewsub.GetNamespace(managedClusterOAuthView) + if namespaceErr != nil || namespace == "" { + managedClusterListErrors = append(managedClusterListErrors, fmt.Sprintf("Unable to create oauth client for cluster %v: managed cluster view status unknown", namespace)) + } else { + managedClusterList = append(managedClusterList, namespace) + } + } + } + + secret, secErr := c.secretsClient.Secrets(api.TargetNamespace).Get(ctx, secretsub.Stub().Name, metav1.GetOptions{}) + if secErr != nil { + return nil, fmt.Errorf("Failed to get secret: %v", secErr), "ManagedClusterActionCreateOAuthClientSyncError" + } + + oauthClient, oAuthErr := c.oauthClient.OAuthClients().Get(ctx, oauthsub.Stub().Name, metav1.GetOptions{}) + if oAuthErr != nil { + return nil, fmt.Errorf("Failed to get oauth client: %v", oAuthErr), "ManagedClusterActionCreateOAuthClientSyncError" + } + + errs := []string{} + managedClusterActionCreateOAuthClients := []*unstructured.Unstructured{} + secretString := secretsub.GetSecretString(secret) + redirects := oauthsub.GetRedirectURIs(oauthClient) + for _, managedClusterName := range managedClusterList { + mca := managedclusteractionsub.DefaultCreateOAuthClient(operatorConfig, managedClusterName, secretString, redirects) + gvr := managedclusteractionsub.GetGVR() + opt := metav1.CreateOptions{} + oAuthCreateResp, oAuthCreateErr := c.dynamicClient.Resource(gvr).Namespace(managedClusterName).Create(ctx, mca, opt) + if oAuthCreateErr != nil && apierrors.IsAlreadyExists(oAuthCreateErr) { + mcaOAuthName, _ := managedclusteractionsub.GetName(mca) + oAuthCreateResp, oAuthCreateErr = c.dynamicClient.Resource(gvr).Namespace(managedClusterName).Get(ctx, mcaOAuthName, metav1.GetOptions{}) + } + + if oAuthCreateErr != nil { + errs = append(errs, fmt.Sprintf("Error syncing managed cluster action for oauth client for cluster %s: %v", managedClusterName, oAuthCreateErr)) + } else { + managedClusterActionCreateOAuthClients = append(managedClusterActionCreateOAuthClients, oAuthCreateResp) + } + } + + if len(errs) > 0 { + return nil, errors.New(strings.Join(errs, "\n")), "ManagedClusterActionCreateOAuthClientSyncError" + } + + if len(managedClusterListErrors) > 0 { + return nil, errors.New(strings.Join(managedClusterListErrors, "\n")), "ManagedClusterActionCreateOAuthClientSyncError" + } + + return managedClusterActionCreateOAuthClients, nil, "" +} + +func (c *ManagedClusterController) SyncManagedClusterViewIngressCert(ctx context.Context, operatorConfig *operatorv1.Console) ([]*unstructured.Unstructured, error, string) { + managedClusters, listErr := c.listManagedClusters(ctx) + if listErr != nil || len(managedClusters.Items) == 0 { + return nil, listErr, "FailedList" + } + + errs := []string{} + managedClusterIngressCertViews := []*unstructured.Unstructured{} + for _, managedCluster := range managedClusters.Items { + mcvIngress := managedclusterviewsub.DefaultViewIngressCert(operatorConfig, managedCluster.Name) + gvr := managedclusterviewsub.GetGVR() + + ingressResp, ingressErr := c.dynamicClient.Resource(gvr).Namespace(managedCluster.Name).Create(ctx, mcvIngress, metav1.CreateOptions{}) + if ingressErr != nil && apierrors.IsAlreadyExists(ingressErr) { + mcvIngressName, _ := managedclusterviewsub.GetName(mcvIngress) + ingressResp, ingressErr = c.dynamicClient.Resource(gvr).Namespace(managedCluster.Name).Get(ctx, mcvIngressName, metav1.GetOptions{}) + } + + if ingressErr != nil || ingressResp == nil { + errs = append(errs, fmt.Sprintf("Error syncing managed cluster view ingress cert for cluster %s: %v", managedCluster.Name, ingressErr)) + } else { + managedClusterIngressCertViews = append(managedClusterIngressCertViews, ingressResp) + } + } + + if len(errs) > 0 { + return nil, errors.New(strings.Join(errs, "\n")), "ManagedClusterViewIngressCertSyncError" + } + + return managedClusterIngressCertViews, nil, "" +} + +func (c *ManagedClusterController) SyncManagedClusterIngressCertConfigMap(managedClusterIngressCertViews []*unstructured.Unstructured, ctx context.Context, operatorConfig *operatorv1.Console, recorder events.Recorder) (error, string) { + errs := []string{} + for _, mcvIngress := range managedClusterIngressCertViews { + clusterName, _ := managedclusterviewsub.GetNamespace(mcvIngress) + certBundle, _ := managedclusterviewsub.GetCertBundle(mcvIngress) + required := configmapsub.DefaultManagedClusterIngressCertConfigMap(clusterName, certBundle, operatorConfig) + _, _, configMapApplyError := resourceapply.ApplyConfigMap(c.configMapClient, recorder, required) + if configMapApplyError != nil { + klog.V(4).Infoln(fmt.Sprintf("Skipping Ingress certificate ConfigMap sync for managed cluster %v, Error applying ConfigMap", clusterName)) + errs = append(errs, configMapApplyError.Error()) + continue + } + } + + if len(errs) > 0 { + return errors.New(strings.Join(errs, "\n")), "ManagedClusterIngressCertConfigMapSyncError" + } + + return nil, "" +} + func (c *ManagedClusterController) removeManagedClusters(ctx context.Context) error { errs := []string{} configMaps, err := c.configMapClient.ConfigMaps(api.OpenShiftConsoleNamespace).List(ctx, metav1.ListOptions{LabelSelector: api.ManagedClusterLabel}) @@ -263,3 +444,7 @@ func (c *ManagedClusterController) removeManagedClusters(ctx context.Context) er } return nil } + +func (c *ManagedClusterController) listManagedClusters(ctx context.Context) (*clusterv1.ManagedClusterList, error) { + return c.managedClusterClient.ManagedClusters().List(ctx, metav1.ListOptions{LabelSelector: fmt.Sprintf("local-cluster!=true")}) +} diff --git a/pkg/console/starter/starter.go b/pkg/console/starter/starter.go index 7c534b9326..b16eacb59b 100644 --- a/pkg/console/starter/starter.go +++ b/pkg/console/starter/starter.go @@ -10,6 +10,8 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/dynamic/dynamicinformer" "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes" @@ -95,6 +97,11 @@ func RunOperator(ctx context.Context, controllerContext *controllercmd.Controlle return err } + dynamicClient, err := dynamic.NewForConfig(controllerContext.KubeConfig) + if err != nil { + return err + } + const resync = 10 * time.Minute tweakListOptionsForOAuth := func(options *metav1.ListOptions) { @@ -153,6 +160,11 @@ func RunOperator(ctx context.Context, controllerContext *controllercmd.Controlle resync, ) + dynamicInformers := dynamicinformer.NewDynamicSharedInformerFactory( + dynamicClient, + resync, + ) + operatorClient := &operatorclient.OperatorClient{ Informers: operatorConfigInformers, Client: operatorConfigClient.OperatorV1(), @@ -328,9 +340,13 @@ func RunOperator(ctx context.Context, controllerContext *controllercmd.Controlle operatorConfigClient.OperatorV1().Consoles(), kubeClient.CoreV1(), managedClusterClient.ClusterV1(), + dynamicClient, + kubeClient.CoreV1(), + oauthClient.OauthV1(), // informers operatorConfigInformers.Operator().V1().Consoles(), managedClusterInformers.Cluster().V1().ManagedClusters(), + dynamicInformers, //events recorder, ) @@ -398,6 +414,7 @@ func RunOperator(ctx context.Context, controllerContext *controllercmd.Controlle routesInformersNamespaced, oauthInformers, managedClusterInformers, + dynamicInformers, } { informer.Start(ctx.Done()) } diff --git a/pkg/console/subresource/configmap/managed_cluster_ingress_cert.go b/pkg/console/subresource/configmap/managed_cluster_ingress_cert.go new file mode 100644 index 0000000000..102f4144b7 --- /dev/null +++ b/pkg/console/subresource/configmap/managed_cluster_ingress_cert.go @@ -0,0 +1,37 @@ +package configmap + +import ( + "fmt" + + corev1 "k8s.io/api/core/v1" + + operatorv1 "github.com/openshift/api/operator/v1" + "github.com/openshift/library-go/pkg/operator/resource/resourceread" + + "github.com/openshift/console-operator/pkg/api" + "github.com/openshift/console-operator/pkg/console/assets" + "github.com/openshift/console-operator/pkg/console/subresource/util" +) + +func DefaultManagedClusterIngressCertConfigMap(clusterName string, caBundle string, cr *operatorv1.Console) *corev1.ConfigMap { + configMap := ManagedClusterIngressCertConfigMapStub(clusterName) + + if caBundle != "" { + configMap.Data = map[string]string{ + "ca.crt": caBundle, + } + } + + util.AddOwnerRef(configMap, util.OwnerRefFrom(cr)) + return configMap +} + +func ManagedClusterIngressCertConfigMapStub(clusterName string) *corev1.ConfigMap { + configMap := resourceread.ReadConfigMapV1OrDie(assets.MustAsset("configmaps/console-managed-cluster-ingress-cert-configmap.yaml")) + configMap.Name = ManagedClusterIngressCertConfigMapName(clusterName) + return configMap +} + +func ManagedClusterIngressCertConfigMapName(clusterName string) string { + return fmt.Sprintf("%s-%s", clusterName, api.ManagedClusterIngressCertName) +} diff --git a/pkg/console/subresource/managedclusteraction/managed_cluster_action.go b/pkg/console/subresource/managedclusteraction/managed_cluster_action.go new file mode 100644 index 0000000000..1545434347 --- /dev/null +++ b/pkg/console/subresource/managedclusteraction/managed_cluster_action.go @@ -0,0 +1,45 @@ +package managedclusteraction + +import ( + operatorv1 "github.com/openshift/api/operator/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + + // openshift + "github.com/openshift/console-operator/pkg/console/assets" + "github.com/openshift/console-operator/pkg/console/subresource/util" + // acm - TODO conflicts adding package to go.mod with several dependencies + // managedclusterviewv1beta1 "github.com/open-cluster-management/multicloud-operators-foundation/pkg/apis/action/v1beta1" +) + +func DefaultCreateOAuthClient(cr *operatorv1.Console, cn string, sec string, redirects []string) *unstructured.Unstructured { + managedClusterAction := CreateOAuthClientStub(cn) + withInfo(managedClusterAction, cn, sec, redirects) + return managedClusterAction +} + +func withInfo(mca *unstructured.Unstructured, cn string, sec string, redirects []string) { + unstructured.SetNestedField(mca.Object, cn, "metadata", "namespace") + unstructured.SetNestedField(mca.Object, sec, "spec", "kube", "template", "secret") + unstructured.SetNestedStringSlice(mca.Object, redirects, "spec", "kube", "template", "redirectURIs") +} + +func CreateOAuthClientStub(cn string) *unstructured.Unstructured { + return util.ReadUnstructuredOrDie(assets.MustAsset("managedclusteractions/console-managed-cluster-action-create-oauth-client.yaml")) +} + +func GetName(mca *unstructured.Unstructured) (string, error) { + name, found, err := unstructured.NestedString(mca.Object, "metadata", "name") + if err != nil || !found || name == "" { + return "", err + } + return name, nil +} + +func GetGVR() schema.GroupVersionResource { + return schema.GroupVersionResource{ + Group: "action.open-cluster-management.io", + Version: "v1beta1", + Resource: "managedclusteractions", + } +} diff --git a/pkg/console/subresource/managedclusterview/managed_cluster_view.go b/pkg/console/subresource/managedclusterview/managed_cluster_view.go new file mode 100644 index 0000000000..c5d1f2be54 --- /dev/null +++ b/pkg/console/subresource/managedclusterview/managed_cluster_view.go @@ -0,0 +1,85 @@ +package managedclusterview + +import ( + operatorv1 "github.com/openshift/api/operator/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + + // openshift + "github.com/openshift/console-operator/pkg/api" + "github.com/openshift/console-operator/pkg/console/assets" + "github.com/openshift/console-operator/pkg/console/subresource/util" + // acm - TODO conflicts adding package to go.mod with several dependencies + // managedclusterviewv1beta1 "github.com/open-cluster-management/multicloud-operators-foundation/pkg/apis/action/v1beta1" +) + +func DefaultViewIngressCert(cr *operatorv1.Console, cn string) *unstructured.Unstructured { + managedClusterView := ViewIngressCertStub(cn) + withInfo(managedClusterView, cn) + return managedClusterView +} + +func DefaultViewOAuthClient(cr *operatorv1.Console, cn string) *unstructured.Unstructured { + managedClusterView := ViewOAuthClientStub(cn) + withInfo(managedClusterView, cn) + return managedClusterView +} + +func withInfo(mcv *unstructured.Unstructured, cn string) { + unstructured.SetNestedField(mcv.Object, cn, "metadata", "namespace") +} + +func ViewIngressCertStub(cn string) *unstructured.Unstructured { + return util.ReadUnstructuredOrDie(assets.MustAsset("managedclusterviews/console-managed-cluster-view-ingress-cert.yaml")) +} + +func ViewOAuthClientStub(cn string) *unstructured.Unstructured { + return util.ReadUnstructuredOrDie(assets.MustAsset("managedclusterviews/console-managed-cluster-view-oauth-client.yaml")) +} + +func GetStatus(mcv *unstructured.Unstructured) (bool, error) { + conditions, found, err := unstructured.NestedSlice(mcv.Object, "status", "conditions") + if err != nil || !found || len(conditions) == 0 { + return false, err + } + + condition := conditions[0].(map[string]interface{}) + status := condition["status"].(string) + if status != "True" { + return false, err + } + + return true, nil +} + +func GetName(mcv *unstructured.Unstructured) (string, error) { + name, found, err := unstructured.NestedString(mcv.Object, "metadata", "name") + if err != nil || !found || name == "" { + return "", err + } + return name, nil +} + +func GetNamespace(mcv *unstructured.Unstructured) (string, error) { + namespace, found, err := unstructured.NestedString(mcv.Object, "metadata", "namespace") + if err != nil || !found || namespace == "" { + return "", err + } + return namespace, nil +} + +func GetGVR() schema.GroupVersionResource { + return schema.GroupVersionResource{ + Group: "view.open-cluster-management.io", + Version: "v1beta1", + Resource: "managedclusterviews", + } +} + +func GetCertBundle(mcv *unstructured.Unstructured) (string, error) { + cert, found, err := unstructured.NestedString(mcv.Object, "status", "result", "data", api.ManagedClusterIngressCertKey) + if err != nil || !found || cert == "" { + return "", err + } + return cert, nil +} diff --git a/pkg/console/subresource/oauthclient/oauthclient.go b/pkg/console/subresource/oauthclient/oauthclient.go index 4f852a4665..d99342aaef 100644 --- a/pkg/console/subresource/oauthclient/oauthclient.go +++ b/pkg/console/subresource/oauthclient/oauthclient.go @@ -101,3 +101,7 @@ func SetRedirectURI(client *oauthv1.OAuthClient, host string) *oauthv1.OAuthClie client.RedirectURIs = append(client.RedirectURIs, util.HTTPS(host)+"/auth/callback") return client } + +func GetRedirectURIs(client *oauthv1.OAuthClient) []string { + return client.RedirectURIs +} diff --git a/pkg/console/subresource/util/util.go b/pkg/console/subresource/util/util.go index 2be5079b3c..d91d14d5f8 100644 --- a/pkg/console/subresource/util/util.go +++ b/pkg/console/subresource/util/util.go @@ -8,7 +8,9 @@ import ( yaml "gopkg.in/yaml.v2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes/scheme" "k8s.io/klog/v2" operatorv1 "github.com/openshift/api/operator/v1" @@ -113,3 +115,13 @@ func HTTPS(host string) string { secured := fmt.Sprintf("%s%s", protocol, host) return secured } + +// borrowed from library-go +// https://github.com/openshift/library-go/blob/master/pkg/operator/resource/resourceread/unstructured.go +func ReadUnstructuredOrDie(objBytes []byte) *unstructured.Unstructured { + udi, _, err := scheme.Codecs.UniversalDecoder().Decode(objBytes, nil, &unstructured.Unstructured{}) + if err != nil { + panic(err) + } + return udi.(*unstructured.Unstructured) +} diff --git a/vendor/k8s.io/client-go/dynamic/dynamicinformer/informer.go b/vendor/k8s.io/client-go/dynamic/dynamicinformer/informer.go new file mode 100644 index 0000000000..40878b400f --- /dev/null +++ b/vendor/k8s.io/client-go/dynamic/dynamicinformer/informer.go @@ -0,0 +1,158 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dynamicinformer + +import ( + "context" + "sync" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/dynamic/dynamiclister" + "k8s.io/client-go/informers" + "k8s.io/client-go/tools/cache" +) + +// NewDynamicSharedInformerFactory constructs a new instance of dynamicSharedInformerFactory for all namespaces. +func NewDynamicSharedInformerFactory(client dynamic.Interface, defaultResync time.Duration) DynamicSharedInformerFactory { + return NewFilteredDynamicSharedInformerFactory(client, defaultResync, metav1.NamespaceAll, nil) +} + +// NewFilteredDynamicSharedInformerFactory constructs a new instance of dynamicSharedInformerFactory. +// Listers obtained via this factory will be subject to the same filters as specified here. +func NewFilteredDynamicSharedInformerFactory(client dynamic.Interface, defaultResync time.Duration, namespace string, tweakListOptions TweakListOptionsFunc) DynamicSharedInformerFactory { + return &dynamicSharedInformerFactory{ + client: client, + defaultResync: defaultResync, + namespace: namespace, + informers: map[schema.GroupVersionResource]informers.GenericInformer{}, + startedInformers: make(map[schema.GroupVersionResource]bool), + tweakListOptions: tweakListOptions, + } +} + +type dynamicSharedInformerFactory struct { + client dynamic.Interface + defaultResync time.Duration + namespace string + + lock sync.Mutex + informers map[schema.GroupVersionResource]informers.GenericInformer + // startedInformers is used for tracking which informers have been started. + // This allows Start() to be called multiple times safely. + startedInformers map[schema.GroupVersionResource]bool + tweakListOptions TweakListOptionsFunc +} + +var _ DynamicSharedInformerFactory = &dynamicSharedInformerFactory{} + +func (f *dynamicSharedInformerFactory) ForResource(gvr schema.GroupVersionResource) informers.GenericInformer { + f.lock.Lock() + defer f.lock.Unlock() + + key := gvr + informer, exists := f.informers[key] + if exists { + return informer + } + + informer = NewFilteredDynamicInformer(f.client, gvr, f.namespace, f.defaultResync, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) + f.informers[key] = informer + + return informer +} + +// Start initializes all requested informers. +func (f *dynamicSharedInformerFactory) Start(stopCh <-chan struct{}) { + f.lock.Lock() + defer f.lock.Unlock() + + for informerType, informer := range f.informers { + if !f.startedInformers[informerType] { + go informer.Informer().Run(stopCh) + f.startedInformers[informerType] = true + } + } +} + +// WaitForCacheSync waits for all started informers' cache were synced. +func (f *dynamicSharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[schema.GroupVersionResource]bool { + informers := func() map[schema.GroupVersionResource]cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informers := map[schema.GroupVersionResource]cache.SharedIndexInformer{} + for informerType, informer := range f.informers { + if f.startedInformers[informerType] { + informers[informerType] = informer.Informer() + } + } + return informers + }() + + res := map[schema.GroupVersionResource]bool{} + for informType, informer := range informers { + res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced) + } + return res +} + +// NewFilteredDynamicInformer constructs a new informer for a dynamic type. +func NewFilteredDynamicInformer(client dynamic.Interface, gvr schema.GroupVersionResource, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions TweakListOptionsFunc) informers.GenericInformer { + return &dynamicInformer{ + gvr: gvr, + informer: cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.Resource(gvr).Namespace(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.Resource(gvr).Namespace(namespace).Watch(context.TODO(), options) + }, + }, + &unstructured.Unstructured{}, + resyncPeriod, + indexers, + ), + } +} + +type dynamicInformer struct { + informer cache.SharedIndexInformer + gvr schema.GroupVersionResource +} + +var _ informers.GenericInformer = &dynamicInformer{} + +func (d *dynamicInformer) Informer() cache.SharedIndexInformer { + return d.informer +} + +func (d *dynamicInformer) Lister() cache.GenericLister { + return dynamiclister.NewRuntimeObjectShim(dynamiclister.New(d.informer.GetIndexer(), d.gvr)) +} diff --git a/vendor/k8s.io/client-go/dynamic/dynamicinformer/interface.go b/vendor/k8s.io/client-go/dynamic/dynamicinformer/interface.go new file mode 100644 index 0000000000..083977c301 --- /dev/null +++ b/vendor/k8s.io/client-go/dynamic/dynamicinformer/interface.go @@ -0,0 +1,34 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dynamicinformer + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/informers" +) + +// DynamicSharedInformerFactory provides access to a shared informer and lister for dynamic client +type DynamicSharedInformerFactory interface { + Start(stopCh <-chan struct{}) + ForResource(gvr schema.GroupVersionResource) informers.GenericInformer + WaitForCacheSync(stopCh <-chan struct{}) map[schema.GroupVersionResource]bool +} + +// TweakListOptionsFunc defines the signature of a helper function +// that wants to provide more listing options to API +type TweakListOptionsFunc func(*metav1.ListOptions) diff --git a/vendor/k8s.io/client-go/dynamic/dynamiclister/interface.go b/vendor/k8s.io/client-go/dynamic/dynamiclister/interface.go new file mode 100644 index 0000000000..c39cbee925 --- /dev/null +++ b/vendor/k8s.io/client-go/dynamic/dynamiclister/interface.go @@ -0,0 +1,40 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dynamiclister + +import ( + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/labels" +) + +// Lister helps list resources. +type Lister interface { + // List lists all resources in the indexer. + List(selector labels.Selector) (ret []*unstructured.Unstructured, err error) + // Get retrieves a resource from the indexer with the given name + Get(name string) (*unstructured.Unstructured, error) + // Namespace returns an object that can list and get resources in a given namespace. + Namespace(namespace string) NamespaceLister +} + +// NamespaceLister helps list and get resources. +type NamespaceLister interface { + // List lists all resources in the indexer for a given namespace. + List(selector labels.Selector) (ret []*unstructured.Unstructured, err error) + // Get retrieves a resource from the indexer for a given namespace and name. + Get(name string) (*unstructured.Unstructured, error) +} diff --git a/vendor/k8s.io/client-go/dynamic/dynamiclister/lister.go b/vendor/k8s.io/client-go/dynamic/dynamiclister/lister.go new file mode 100644 index 0000000000..a50fc471e9 --- /dev/null +++ b/vendor/k8s.io/client-go/dynamic/dynamiclister/lister.go @@ -0,0 +1,91 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dynamiclister + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/tools/cache" +) + +var _ Lister = &dynamicLister{} +var _ NamespaceLister = &dynamicNamespaceLister{} + +// dynamicLister implements the Lister interface. +type dynamicLister struct { + indexer cache.Indexer + gvr schema.GroupVersionResource +} + +// New returns a new Lister. +func New(indexer cache.Indexer, gvr schema.GroupVersionResource) Lister { + return &dynamicLister{indexer: indexer, gvr: gvr} +} + +// List lists all resources in the indexer. +func (l *dynamicLister) List(selector labels.Selector) (ret []*unstructured.Unstructured, err error) { + err = cache.ListAll(l.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*unstructured.Unstructured)) + }) + return ret, err +} + +// Get retrieves a resource from the indexer with the given name +func (l *dynamicLister) Get(name string) (*unstructured.Unstructured, error) { + obj, exists, err := l.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(l.gvr.GroupResource(), name) + } + return obj.(*unstructured.Unstructured), nil +} + +// Namespace returns an object that can list and get resources from a given namespace. +func (l *dynamicLister) Namespace(namespace string) NamespaceLister { + return &dynamicNamespaceLister{indexer: l.indexer, namespace: namespace, gvr: l.gvr} +} + +// dynamicNamespaceLister implements the NamespaceLister interface. +type dynamicNamespaceLister struct { + indexer cache.Indexer + namespace string + gvr schema.GroupVersionResource +} + +// List lists all resources in the indexer for a given namespace. +func (l *dynamicNamespaceLister) List(selector labels.Selector) (ret []*unstructured.Unstructured, err error) { + err = cache.ListAllByNamespace(l.indexer, l.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*unstructured.Unstructured)) + }) + return ret, err +} + +// Get retrieves a resource from the indexer for a given namespace and name. +func (l *dynamicNamespaceLister) Get(name string) (*unstructured.Unstructured, error) { + obj, exists, err := l.indexer.GetByKey(l.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(l.gvr.GroupResource(), name) + } + return obj.(*unstructured.Unstructured), nil +} diff --git a/vendor/k8s.io/client-go/dynamic/dynamiclister/shim.go b/vendor/k8s.io/client-go/dynamic/dynamiclister/shim.go new file mode 100644 index 0000000000..92a5f54af9 --- /dev/null +++ b/vendor/k8s.io/client-go/dynamic/dynamiclister/shim.go @@ -0,0 +1,87 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dynamiclister + +import ( + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/tools/cache" +) + +var _ cache.GenericLister = &dynamicListerShim{} +var _ cache.GenericNamespaceLister = &dynamicNamespaceListerShim{} + +// dynamicListerShim implements the cache.GenericLister interface. +type dynamicListerShim struct { + lister Lister +} + +// NewRuntimeObjectShim returns a new shim for Lister. +// It wraps Lister so that it implements cache.GenericLister interface +func NewRuntimeObjectShim(lister Lister) cache.GenericLister { + return &dynamicListerShim{lister: lister} +} + +// List will return all objects across namespaces +func (s *dynamicListerShim) List(selector labels.Selector) (ret []runtime.Object, err error) { + objs, err := s.lister.List(selector) + if err != nil { + return nil, err + } + + ret = make([]runtime.Object, len(objs)) + for index, obj := range objs { + ret[index] = obj + } + return ret, err +} + +// Get will attempt to retrieve assuming that name==key +func (s *dynamicListerShim) Get(name string) (runtime.Object, error) { + return s.lister.Get(name) +} + +func (s *dynamicListerShim) ByNamespace(namespace string) cache.GenericNamespaceLister { + return &dynamicNamespaceListerShim{ + namespaceLister: s.lister.Namespace(namespace), + } +} + +// dynamicNamespaceListerShim implements the NamespaceLister interface. +// It wraps NamespaceLister so that it implements cache.GenericNamespaceLister interface +type dynamicNamespaceListerShim struct { + namespaceLister NamespaceLister +} + +// List will return all objects in this namespace +func (ns *dynamicNamespaceListerShim) List(selector labels.Selector) (ret []runtime.Object, err error) { + objs, err := ns.namespaceLister.List(selector) + if err != nil { + return nil, err + } + + ret = make([]runtime.Object, len(objs)) + for index, obj := range objs { + ret[index] = obj + } + return ret, err +} + +// Get will attempt to retrieve by namespace and name +func (ns *dynamicNamespaceListerShim) Get(name string) (runtime.Object, error) { + return ns.namespaceLister.Get(name) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 6803c59ea3..59b91d9748 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -731,6 +731,8 @@ k8s.io/client-go/applyconfigurations/storage/v1beta1 k8s.io/client-go/discovery k8s.io/client-go/discovery/fake k8s.io/client-go/dynamic +k8s.io/client-go/dynamic/dynamicinformer +k8s.io/client-go/dynamic/dynamiclister k8s.io/client-go/informers k8s.io/client-go/informers/admissionregistration k8s.io/client-go/informers/admissionregistration/v1 From 09afff78ab308f2480c31ff6ec670b8e56438892 Mon Sep 17 00:00:00 2001 From: Bryan Florkiewicz Date: Tue, 19 Oct 2021 09:59:42 -0400 Subject: [PATCH 3/3] Code review comments for spoke cluster oauth clients --- .../controllers/managedclusters/controller.go | 50 +++++++------------ ...aged_cluster_action.go => oauth-client.go} | 6 +-- .../default-ingress-cert.go | 35 +++++++++++++ ...anaged_cluster_view.go => oauth-client.go} | 26 ++-------- pkg/console/subresource/util/util.go | 1 + 5 files changed, 60 insertions(+), 58 deletions(-) rename pkg/console/subresource/managedclusteraction/{managed_cluster_action.go => oauth-client.go} (86%) create mode 100644 pkg/console/subresource/managedclusterview/default-ingress-cert.go rename pkg/console/subresource/managedclusterview/{managed_cluster_view.go => oauth-client.go} (69%) diff --git a/pkg/console/controllers/managedclusters/controller.go b/pkg/console/controllers/managedclusters/controller.go index 832900576d..c94ee800fb 100644 --- a/pkg/console/controllers/managedclusters/controller.go +++ b/pkg/console/controllers/managedclusters/controller.go @@ -97,9 +97,9 @@ func NewManagedClusterController( util.ExcludeNamesFilter(api.HubClusterName), managedClusterInformers.Informer(), ).WithInformers( - dynamicInformers.ForResource(managedclusteractionsub.GetGVR()).Informer(), + dynamicInformers.ForResource(managedclusteractionsub.GetGroupVersionResource()).Informer(), ).WithInformers( - dynamicInformers.ForResource(managedclusterviewsub.GetGVR()).Informer(), + dynamicInformers.ForResource(managedclusterviewsub.GetGroupVersionResource()).Informer(), ).WithSync(ctrl.Sync). ToController("ManagedClusterController", recorder.WithComponentSuffix("managed-cluster-controller")) } @@ -125,8 +125,14 @@ func (c *ManagedClusterController) Sync(ctx context.Context, controllerContext f statusHandler := status.NewStatusHandler(c.operatorClient) + managedClusters, err := c.listManagedClusters(ctx) + // Not found means API is not on the cluster + if apierrors.IsNotFound(err) || err != nil { + return err + } + // Get a list of ManagedCluster resources, degraded if error is returned - managedClusterClientConfigs, managedClusterClientConfigValidationErr, managedClusterClientConfigValidationErrReason := c.ValidateManagedClusterClientConfigs(ctx, operatorConfig, controllerContext.Recorder()) + managedClusterClientConfigs, managedClusterClientConfigValidationErr, managedClusterClientConfigValidationErrReason := c.ValidateManagedClusterClientConfigs(ctx, operatorConfig, controllerContext.Recorder(), managedClusters) statusHandler.AddConditions(status.HandleProgressingOrDegraded("ManagedClusterValidation", managedClusterClientConfigValidationErrReason, managedClusterClientConfigValidationErr)) if managedClusterClientConfigValidationErr != nil { return statusHandler.FlushAndReturn(managedClusterClientConfigValidationErr) @@ -145,7 +151,7 @@ func (c *ManagedClusterController) Sync(ctx context.Context, controllerContext f } // Create managed cluster views for oauth clients - managedClusterViewOAuthClients, managedClusterViewOAuthClientErr, managedClusterViewOAuthClientErrReason := c.SyncManagedClusterViewOAuthClient(ctx, operatorConfig) + managedClusterViewOAuthClients, managedClusterViewOAuthClientErr, managedClusterViewOAuthClientErrReason := c.SyncManagedClusterViewOAuthClient(ctx, operatorConfig, managedClusters) statusHandler.AddConditions(status.HandleProgressingOrDegraded("ManagedClusterViewOAuthClientSync", managedClusterViewOAuthClientErrReason, managedClusterViewOAuthClientErr)) // Create managed cluster actions for oauth clients @@ -153,7 +159,7 @@ func (c *ManagedClusterController) Sync(ctx context.Context, controllerContext f statusHandler.AddConditions(status.HandleProgressingOrDegraded("ManagedClusterActionCreateOAuthClientSync", managedClusterActionCreateOAuthClientErrReason, managedClusterActionCreateOAuthClientErr)) // Create managed cluster views for ingress cert - managedClusterViewsIngressCert, managedClusterViewIngressCertErr, managedClusterViewIngressCertErrReason := c.SyncManagedClusterViewIngressCert(ctx, operatorConfig) + managedClusterViewsIngressCert, managedClusterViewIngressCertErr, managedClusterViewIngressCertErrReason := c.SyncManagedClusterViewIngressCert(ctx, operatorConfig, managedClusters) statusHandler.AddConditions(status.HandleProgressingOrDegraded("ManagedClusterViewIngressCertSync", managedClusterViewIngressCertErrReason, managedClusterViewIngressCertErr)) // Create config maps for each managed cluster ingress cert bundle @@ -167,19 +173,7 @@ func (c *ManagedClusterController) Sync(ctx context.Context, controllerContext f } // Return slice of clusterv1.ClientConfigs that have been validated or error and reaons if unable to list ManagedClusters -func (c *ManagedClusterController) ValidateManagedClusterClientConfigs(ctx context.Context, operatorConfig *operatorv1.Console, recorder events.Recorder) (map[string]*clusterv1.ClientConfig, error, string) { - managedClusters, err := c.listManagedClusters(ctx) - - // Not found means API is not on the cluster - if apierrors.IsNotFound(err) { - return nil, nil, "" - } - - // Any other list request failure means operator is degraded - if err != nil { - return nil, err, "FailedList" - } - +func (c *ManagedClusterController) ValidateManagedClusterClientConfigs(ctx context.Context, operatorConfig *operatorv1.Console, recorder events.Recorder, managedClusters *clusterv1.ManagedClusterList) (map[string]*clusterv1.ClientConfig, error, string) { validatedClientConfigs := map[string]*clusterv1.ClientConfig{} for _, managedCluster := range managedClusters.Items { clusterName := managedCluster.GetName() @@ -278,17 +272,12 @@ func (c *ManagedClusterController) SyncManagedClusterConfigMap(clientConfigs map return nil, "" } -func (c *ManagedClusterController) SyncManagedClusterViewOAuthClient(ctx context.Context, operatorConfig *operatorv1.Console) ([]*unstructured.Unstructured, error, string) { - managedClusters, listErr := c.listManagedClusters(ctx) - if listErr != nil || len(managedClusters.Items) == 0 { - return nil, listErr, "FailedList" - } - +func (c *ManagedClusterController) SyncManagedClusterViewOAuthClient(ctx context.Context, operatorConfig *operatorv1.Console, managedClusters *clusterv1.ManagedClusterList) ([]*unstructured.Unstructured, error, string) { errs := []string{} managedClusterOAuthClientViews := []*unstructured.Unstructured{} for _, managedCluster := range managedClusters.Items { mcvOAuth := managedclusterviewsub.DefaultViewOAuthClient(operatorConfig, managedCluster.Name) - gvr := managedclusterviewsub.GetGVR() + gvr := managedclusterviewsub.GetGroupVersionResource() oAuthResp, oAuthErr := c.dynamicClient.Resource(gvr).Namespace(managedCluster.Name).Create(ctx, mcvOAuth, metav1.CreateOptions{}) if oAuthErr != nil && apierrors.IsAlreadyExists(oAuthErr) { @@ -341,7 +330,7 @@ func (c *ManagedClusterController) SyncManagedClusterActionCreateOAuthClient(ctx redirects := oauthsub.GetRedirectURIs(oauthClient) for _, managedClusterName := range managedClusterList { mca := managedclusteractionsub.DefaultCreateOAuthClient(operatorConfig, managedClusterName, secretString, redirects) - gvr := managedclusteractionsub.GetGVR() + gvr := managedclusteractionsub.GetGroupVersionResource() opt := metav1.CreateOptions{} oAuthCreateResp, oAuthCreateErr := c.dynamicClient.Resource(gvr).Namespace(managedClusterName).Create(ctx, mca, opt) if oAuthCreateErr != nil && apierrors.IsAlreadyExists(oAuthCreateErr) { @@ -367,17 +356,12 @@ func (c *ManagedClusterController) SyncManagedClusterActionCreateOAuthClient(ctx return managedClusterActionCreateOAuthClients, nil, "" } -func (c *ManagedClusterController) SyncManagedClusterViewIngressCert(ctx context.Context, operatorConfig *operatorv1.Console) ([]*unstructured.Unstructured, error, string) { - managedClusters, listErr := c.listManagedClusters(ctx) - if listErr != nil || len(managedClusters.Items) == 0 { - return nil, listErr, "FailedList" - } - +func (c *ManagedClusterController) SyncManagedClusterViewIngressCert(ctx context.Context, operatorConfig *operatorv1.Console, managedClusters *clusterv1.ManagedClusterList) ([]*unstructured.Unstructured, error, string) { errs := []string{} managedClusterIngressCertViews := []*unstructured.Unstructured{} for _, managedCluster := range managedClusters.Items { mcvIngress := managedclusterviewsub.DefaultViewIngressCert(operatorConfig, managedCluster.Name) - gvr := managedclusterviewsub.GetGVR() + gvr := managedclusterviewsub.GetGroupVersionResource() ingressResp, ingressErr := c.dynamicClient.Resource(gvr).Namespace(managedCluster.Name).Create(ctx, mcvIngress, metav1.CreateOptions{}) if ingressErr != nil && apierrors.IsAlreadyExists(ingressErr) { diff --git a/pkg/console/subresource/managedclusteraction/managed_cluster_action.go b/pkg/console/subresource/managedclusteraction/oauth-client.go similarity index 86% rename from pkg/console/subresource/managedclusteraction/managed_cluster_action.go rename to pkg/console/subresource/managedclusteraction/oauth-client.go index 1545434347..cdad03b843 100644 --- a/pkg/console/subresource/managedclusteraction/managed_cluster_action.go +++ b/pkg/console/subresource/managedclusteraction/oauth-client.go @@ -14,11 +14,11 @@ import ( func DefaultCreateOAuthClient(cr *operatorv1.Console, cn string, sec string, redirects []string) *unstructured.Unstructured { managedClusterAction := CreateOAuthClientStub(cn) - withInfo(managedClusterAction, cn, sec, redirects) + withDefaultCreateOAuthClientInfo(managedClusterAction, cn, sec, redirects) return managedClusterAction } -func withInfo(mca *unstructured.Unstructured, cn string, sec string, redirects []string) { +func withDefaultCreateOAuthClientInfo(mca *unstructured.Unstructured, cn string, sec string, redirects []string) { unstructured.SetNestedField(mca.Object, cn, "metadata", "namespace") unstructured.SetNestedField(mca.Object, sec, "spec", "kube", "template", "secret") unstructured.SetNestedStringSlice(mca.Object, redirects, "spec", "kube", "template", "redirectURIs") @@ -36,7 +36,7 @@ func GetName(mca *unstructured.Unstructured) (string, error) { return name, nil } -func GetGVR() schema.GroupVersionResource { +func GetGroupVersionResource() schema.GroupVersionResource { return schema.GroupVersionResource{ Group: "action.open-cluster-management.io", Version: "v1beta1", diff --git a/pkg/console/subresource/managedclusterview/default-ingress-cert.go b/pkg/console/subresource/managedclusterview/default-ingress-cert.go new file mode 100644 index 0000000000..9ee904c4da --- /dev/null +++ b/pkg/console/subresource/managedclusterview/default-ingress-cert.go @@ -0,0 +1,35 @@ +package managedclusterview + +import ( + operatorv1 "github.com/openshift/api/operator/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + + // openshift + "github.com/openshift/console-operator/pkg/api" + "github.com/openshift/console-operator/pkg/console/assets" + "github.com/openshift/console-operator/pkg/console/subresource/util" + // acm - TODO conflicts adding package to go.mod with several dependencies + // managedclusterviewv1beta1 "github.com/open-cluster-management/multicloud-operators-foundation/pkg/apis/action/v1beta1" +) + +func DefaultViewIngressCert(cr *operatorv1.Console, cn string) *unstructured.Unstructured { + managedClusterView := ViewIngressCertStub(cn) + withDefaultViewIngressCertInfo(managedClusterView, cn) + return managedClusterView +} + +func withDefaultViewIngressCertInfo(mcv *unstructured.Unstructured, cn string) { + unstructured.SetNestedField(mcv.Object, cn, "metadata", "namespace") +} + +func ViewIngressCertStub(cn string) *unstructured.Unstructured { + return util.ReadUnstructuredOrDie(assets.MustAsset("managedclusterviews/console-managed-cluster-view-ingress-cert.yaml")) +} + +func GetCertBundle(mcv *unstructured.Unstructured) (string, error) { + cert, found, err := unstructured.NestedString(mcv.Object, "status", "result", "data", api.ManagedClusterIngressCertKey) + if err != nil || !found || cert == "" { + return "", err + } + return cert, nil +} diff --git a/pkg/console/subresource/managedclusterview/managed_cluster_view.go b/pkg/console/subresource/managedclusterview/oauth-client.go similarity index 69% rename from pkg/console/subresource/managedclusterview/managed_cluster_view.go rename to pkg/console/subresource/managedclusterview/oauth-client.go index c5d1f2be54..879e0c31f8 100644 --- a/pkg/console/subresource/managedclusterview/managed_cluster_view.go +++ b/pkg/console/subresource/managedclusterview/oauth-client.go @@ -6,33 +6,23 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" // openshift - "github.com/openshift/console-operator/pkg/api" + "github.com/openshift/console-operator/pkg/console/assets" "github.com/openshift/console-operator/pkg/console/subresource/util" // acm - TODO conflicts adding package to go.mod with several dependencies // managedclusterviewv1beta1 "github.com/open-cluster-management/multicloud-operators-foundation/pkg/apis/action/v1beta1" ) -func DefaultViewIngressCert(cr *operatorv1.Console, cn string) *unstructured.Unstructured { - managedClusterView := ViewIngressCertStub(cn) - withInfo(managedClusterView, cn) - return managedClusterView -} - func DefaultViewOAuthClient(cr *operatorv1.Console, cn string) *unstructured.Unstructured { managedClusterView := ViewOAuthClientStub(cn) - withInfo(managedClusterView, cn) + withDefaultViewOAuthClientInfo(managedClusterView, cn) return managedClusterView } -func withInfo(mcv *unstructured.Unstructured, cn string) { +func withDefaultViewOAuthClientInfo(mcv *unstructured.Unstructured, cn string) { unstructured.SetNestedField(mcv.Object, cn, "metadata", "namespace") } -func ViewIngressCertStub(cn string) *unstructured.Unstructured { - return util.ReadUnstructuredOrDie(assets.MustAsset("managedclusterviews/console-managed-cluster-view-ingress-cert.yaml")) -} - func ViewOAuthClientStub(cn string) *unstructured.Unstructured { return util.ReadUnstructuredOrDie(assets.MustAsset("managedclusterviews/console-managed-cluster-view-oauth-client.yaml")) } @@ -68,18 +58,10 @@ func GetNamespace(mcv *unstructured.Unstructured) (string, error) { return namespace, nil } -func GetGVR() schema.GroupVersionResource { +func GetGroupVersionResource() schema.GroupVersionResource { return schema.GroupVersionResource{ Group: "view.open-cluster-management.io", Version: "v1beta1", Resource: "managedclusterviews", } } - -func GetCertBundle(mcv *unstructured.Unstructured) (string, error) { - cert, found, err := unstructured.NestedString(mcv.Object, "status", "result", "data", api.ManagedClusterIngressCertKey) - if err != nil || !found || cert == "" { - return "", err - } - return cert, nil -} diff --git a/pkg/console/subresource/util/util.go b/pkg/console/subresource/util/util.go index d91d14d5f8..529c2d9b8b 100644 --- a/pkg/console/subresource/util/util.go +++ b/pkg/console/subresource/util/util.go @@ -116,6 +116,7 @@ func HTTPS(host string) string { return secured } +// TODO remove when we update library-go to a version that includes this // borrowed from library-go // https://github.com/openshift/library-go/blob/master/pkg/operator/resource/resourceread/unstructured.go func ReadUnstructuredOrDie(objBytes []byte) *unstructured.Unstructured {