diff --git a/charts/gardener/gardenlet/charts/runtime/templates/configmap-componentconfig.yaml b/charts/gardener/gardenlet/charts/runtime/templates/configmap-componentconfig.yaml index 64695616b7b..abdffcc801a 100644 --- a/charts/gardener/gardenlet/charts/runtime/templates/configmap-componentconfig.yaml +++ b/charts/gardener/gardenlet/charts/runtime/templates/configmap-componentconfig.yaml @@ -161,10 +161,6 @@ data: {{- if .Values.global.gardenlet.config.featureGates }} featureGates: {{ toYaml .Values.global.gardenlet.config.featureGates | indent 6 }} - {{- end }} - {{- if .Values.global.gardenlet.config.seedSelector }} - seedSelector: -{{ toYaml .Values.global.gardenlet.config.seedSelector | indent 6 }} {{- end }} {{- if .Values.global.gardenlet.config.seedConfig }} seedConfig: diff --git a/charts/gardener/gardenlet/values.yaml b/charts/gardener/gardenlet/values.yaml index 91438eeb686..97b83c5fdd9 100644 --- a/charts/gardener/gardenlet/values.yaml +++ b/charts/gardener/gardenlet/values.yaml @@ -155,7 +155,6 @@ global: # labels: # istio: ingressgateway-handler-2 - # seedSelector: {} # seedConfig: {} # logging: # fluentBit: diff --git a/cmd/gardenlet/app/gardenlet.go b/cmd/gardenlet/app/gardenlet.go index 8296020ca8a..d52c8b66e87 100644 --- a/cmd/gardenlet/app/gardenlet.go +++ b/cmd/gardenlet/app/gardenlet.go @@ -323,7 +323,6 @@ func NewGardenlet(ctx context.Context, cfg *config.GardenletConfiguration) (*Gar } seedClientMapBuilder := clientmapbuilder.NewSeedClientMapBuilder(). - WithInCluster(cfg.SeedSelector == nil). WithClientConnectionConfig(&cfg.SeedClientConnection.ClientConnectionConfiguration) shootClientMapBuilder := clientmapbuilder.NewShootClientMapBuilder(). WithClientConnectionConfig(&cfg.ShootClientConnection.ClientConnectionConfiguration) diff --git a/docs/concepts/gardenlet.md b/docs/concepts/gardenlet.md index 2a8e6bbbf45..fd5971bfada 100644 --- a/docs/concepts/gardenlet.md +++ b/docs/concepts/gardenlet.md @@ -111,28 +111,34 @@ for example, using command `kubectl certificate approve seed-csr-<...>`). If that doesn’t happen within 15 minutes, the gardenlet repeats the process and creates another CSR. -## Seed Config versus Seed Selector - -The usage of the gardenlet is flexible: - -| Usage | Description | -|:---|:---| -| `seedConfig` | Run one gardenlet per seed cluster inside the seed cluster itself.| -| `seedSelector` | Use one gardenlet to manage multiple seed clusters. The gardenlet can run outside of the seed cluster.| - -> For production use it’s recommended to go for the `seedConfig` option, -> because it makes scaling easier and leads to a better distribution of responsibilities. - -* Provide a `seedConfig` that contains information about the seed cluster itself - if you want the gardenlet in the standard way, - see [the example gardenlet configuration](../../example/20-componentconfig-gardenlet.yaml). - Once bootstrapped, the gardenlet creates and updates its `Seed` object itself. - -* Provide a `seedSelector` that incorporates a label selector for the - targeted seed clusters if you want the gardenlet to manage multiple seeds, - see [the example gardenlet configuration](../../example/20-componentconfig-gardenlet.yaml). - In this case, you have to create the `Seed` objects - together with a `kubeconfig` pointing to the cluster yourself. +## Configuring the Seed to work with + +The Gardenlet works with a single seed, which must be configured in the +`GardenletConfiguration` under `.seedConfig`. This must be a copy of the +`Seed` resource, for example (see `example/20-componentconfig-gardenlet.yaml` +for a more complete example): + +```yaml +apiVersion: gardenlet.config.gardener.cloud/v1alpha1 +kind: GardenletConfiguration +seedConfig: + metadata: + name: my-seed + spec: + provider: + type: aws + # ... + secretRef: + name: my-seed-secret + namespace: garden +``` + +When using `make start-gardenlet`, the corresponding script will automatically +fetch the seed cluster's `kubeconfig` based on the `seedConfig.spec.secretRef` +and set the environment accordingly. + +On startup, gardenlet registers a `Seed` resource using the given template +in `seedConfig` if it's not present already. ## Component Configuration @@ -166,13 +172,7 @@ It’s used as a liveness probe in the `Deployment` of the gardenlet. If the gardenlet fails to renew its lease then the endpoint returns `500 Internal Server Error`, otherwise it returns `200 OK`. -> ⚠️
In case the gardenlet is managing multiple seeds -> (that is, a seed selector is used) then the `/healthz` -> reports `500 Internal Server Error` if there is at least one seed -> for which it couldn’t renew its lease. Only if it can renew the lease -> for all seeds it reports `200 OK`. - -Please note, that the `/healthz` only indicates whether the gardenlet +Please note that the `/healthz` only indicates whether the gardenlet could successfully probe the Seed's API server and renew the lease with the Garden cluster. It does *not* show that the Gardener extension API server (with the Gardener resource groups) diff --git a/docs/deployment/deploy_gardenlet_manually.md b/docs/deployment/deploy_gardenlet_manually.md index eb6f4252e00..3564b45f9c6 100755 --- a/docs/deployment/deploy_gardenlet_manually.md +++ b/docs/deployment/deploy_gardenlet_manually.md @@ -2,16 +2,16 @@ Manually deploying a gardenlet is required in the following cases: -- The Kubernetes cluster to be registered as a seed cluster has no public endpoint, - because it is behind a firewall. +- The Kubernetes cluster to be registered as a seed cluster has no public endpoint, + because it is behind a firewall. The gardenlet must then be deployed into the cluster itself. -- The Kubernetes cluster to be registered as a seed cluster is managed externally +- The Kubernetes cluster to be registered as a seed cluster is managed externally (the Kubernetes cluster is not a shoot cluster, so [Automatic Deployment of Gardenlets](deploy_gardenlet_automatically.md) cannot be used). -- The gardenlet runs outside of the Kubernetes cluster - that should be registered as a seed cluster. - (The gardenlet is not restricted to run in the seed cluster or +- The gardenlet runs outside of the Kubernetes cluster + that should be registered as a seed cluster. + (The gardenlet is not restricted to run in the seed cluster or to be deployed into a Kubernetes cluster at all). > Once you’ve deployed a gardenlet manually, for example, behind a firewall, you can deploy new gardenlets automatically. The manually deployed gardenlet is then used as a template for the new gardenlets. More information: [Automatic Deployment of Gardenlets](deploy_gardenlet_automatically.md). @@ -19,15 +19,15 @@ Manually deploying a gardenlet is required in the following cases: ## Prerequisites ### Kubernetes cluster that should be registered as a seed cluster - + - Verify that the cluster has a [supported Kubernetes version](../usage/supported_k8s_versions.md). - -- Determine the nodes, pods, and services CIDR of the cluster. + +- Determine the nodes, pods, and services CIDR of the cluster. You need to configure this information in the `Seed` configuration. Gardener uses this information to check that the shoot cluster isn’t created with overlapping CIDR ranges. - Every Seed cluster needs an Ingress controller which distributes external requests to internal components like grafana and prometheus. Gardener supports two approaches to achieve this: - + a. Gardener managed Ingress controller and DNS records. For this configure the following lines in your [Seed resource](../../example/50-seed.yaml): ```yaml spec: @@ -49,7 +49,7 @@ spec: b. Self-managed DNS record and Ingress controller: -:warning: +:warning: There should exist a DNS record `*.ingress.` where `` is the value of the `.dns.ingressDomain` field of [a Seed cluster resource](../../example/50-seed.yaml) (or the [respective Gardenlet configuration](../../example/20-componentconfig-gardenlet.yaml#L84-L85)). *This is how it could be done for the Nginx ingress controller* @@ -77,27 +77,27 @@ spec: ### `kubeconfig` for the Seed Cluster -The `kubeconfig` is required to deploy the gardenlet Helm chart to the seed cluster. -The gardenlet requires certain privileges to be able to operate. -These privileges are described in RBAC resources in the gardenlet Helm chart (see [charts/gardener/gardenlet/charts/runtime/templates](../../charts/gardener/gardenlet/charts/runtime/templates)). -The Helm chart contains a service account `gardenlet` +The `kubeconfig` is required to deploy the gardenlet Helm chart to the seed cluster. +The gardenlet requires certain privileges to be able to operate. +These privileges are described in RBAC resources in the gardenlet Helm chart (see [charts/gardener/gardenlet/charts/runtime/templates](../../charts/gardener/gardenlet/charts/runtime/templates)). +The Helm chart contains a service account `gardenlet` that the gardenlet deployment uses by default to talk to the Seed API server. -> If the gardenlet isn’t deployed in the seed cluster, -> the gardenlet can be configured to use a `kubeconfig`, -> which also requires the above-mentioned privileges, from a mounted directory. -> The `kubeconfig` is specified in section `seedClientConnection.kubeconfig` +> If the gardenlet isn’t deployed in the seed cluster, +> the gardenlet can be configured to use a `kubeconfig`, +> which also requires the above-mentioned privileges, from a mounted directory. +> The `kubeconfig` is specified in section `seedClientConnection.kubeconfig` > of the [Gardenlet configuration](../../example/20-componentconfig-gardenlet.yaml). -> This configuration option isn’t used in the following, -> as this procedure only describes the recommended setup option -> where the gardenlet is running in the seed cluster itself. +> This configuration option isn’t used in the following, +> as this procedure only describes the recommended setup option +> where the gardenlet is running in the seed cluster itself. ## Procedure Overview 1. Prepare the garden cluster: 1. [Create a bootstrap token secret in the `kube-system` namespace of the garden cluster](#create-a-bootstrap-token-secret-in-the-kube-system-namespace-of-the-garden-cluster) 1. [Create RBAC roles for the gardenlet to allow bootstrapping in the garden cluster](#create-rbac-roles-for-the-gardenlet-to-allow-bootstrapping-in-the-garden-cluster) - + 1. [Prepare the gardenlet Helm chart](#prepare-the-gardenlet-helm-chart). 1. [Automatically register shoot cluster as a seed cluster](#automatically-register-shoot-cluster-as-a-seed-cluster). 1. [Deploy the gardenlet](#deploy-the-gardenlet) @@ -105,32 +105,32 @@ that the gardenlet deployment uses by default to talk to the Seed API server. ## Create a bootstrap token secret in the `kube-system` namespace of the garden cluster -The gardenlet needs to talk to the [Gardener API server](../concepts/apiserver.md) residing in the garden cluster. +The gardenlet needs to talk to the [Gardener API server](../concepts/apiserver.md) residing in the garden cluster. -The gardenlet can be configured with an already existing garden cluster `kubeconfig` in one of the following ways: +The gardenlet can be configured with an already existing garden cluster `kubeconfig` in one of the following ways: - - Either by specifying `gardenClientConnection.kubeconfig` + - Either by specifying `gardenClientConnection.kubeconfig` in the [Gardenlet configuration](../../example/20-componentconfig-gardenlet.yaml) or - - by supplying the environment variable `GARDEN_KUBECONFIG` pointing to + - by supplying the environment variable `GARDEN_KUBECONFIG` pointing to a mounted `kubeconfig` file). -The preferred way however, is to use the gardenlets ability to request -a signed certificate for the garden cluster by leveraging +The preferred way however, is to use the gardenlets ability to request +a signed certificate for the garden cluster by leveraging [Kubernetes Certificate Signing Requests](https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/). -The gardenlet performs a TLS bootstrapping process that is similar to the +The gardenlet performs a TLS bootstrapping process that is similar to the [Kubelet TLS Bootstrapping](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/). -Make sure that the API server of the garden cluster has -[bootstrap token authentication](https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/#enabling-bootstrap-token-authentication) +Make sure that the API server of the garden cluster has +[bootstrap token authentication](https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/#enabling-bootstrap-token-authentication) enabled. -The client credentials required for the gardenlets TLS bootstrapping process, +The client credentials required for the gardenlets TLS bootstrapping process, need to be either `token` or `certificate` (OIDC isn’t supported) and have permissions to create a Certificate Signing Request ([CSR](https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/)). -It’s recommended to use [bootstrap tokens](https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/) +It’s recommended to use [bootstrap tokens](https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/) due to their desirable security properties (such as a limited token lifetime). -Therefore, first create a bootstrap token secret for the garden cluster: +Therefore, first create a bootstrap token secret for the garden cluster: ``` yaml apiVersion: v1 @@ -158,20 +158,20 @@ stringData: usage-bootstrap-signing: "true" ``` -When you later prepare the gardenlet Helm chart, +When you later prepare the gardenlet Helm chart, a `kubeconfig` based on this token is shared with the gardenlet upon deployment. ## Create RBAC roles for the gardenlet to allow bootstrapping in the garden cluster - -This step is only required if the gardenlet you deploy is the first gardenlet -in the Gardener installation. -Additionally, when using the [control plane chart](../../charts/gardener/controlplane), -the following resources are already contained in the Helm chart, -that is, if you use it you can skip these steps as the needed RBAC roles already exist. + +This step is only required if the gardenlet you deploy is the first gardenlet +in the Gardener installation. +Additionally, when using the [control plane chart](../../charts/gardener/controlplane), +the following resources are already contained in the Helm chart, +that is, if you use it you can skip these steps as the needed RBAC roles already exist. The gardenlet uses the configured bootstrap `kubeconfig` in `gardenClientConnection.bootstrapKubeconfig` to request a signed certificate for the user `gardener.cloud:system:seed:` in the group `gardener.cloud:system:seeds`. -Create a `ClusterRole` and `ClusterRoleBinding` that grant full admin permissions to authenticated gardenlets. +Create a `ClusterRole` and `ClusterRoleBinding` that grant full admin permissions to authenticated gardenlets. Create the following resources in the garden cluster: @@ -243,17 +243,17 @@ Please take a look into [this document](gardenlet_api_access.md). ## Prepare the gardenlet Helm chart -This section only describes the minimal configuration, -using the global configuration values of the gardenlet Helm chart. -For an overview over all values, see the [configuration values](../../charts/gardener/gardenlet/values.yaml). +This section only describes the minimal configuration, +using the global configuration values of the gardenlet Helm chart. +For an overview over all values, see the [configuration values](../../charts/gardener/gardenlet/values.yaml). We refer to the global configuration values as _gardenlet configuration_ in the remaining procedure. 1. Create a gardenlet configuration `gardenlet-values.yaml` based on [this template](https://github.com/gardener/gardener/blob/master/charts/gardener/gardenlet/values.yaml). - + 2. Create a bootstrap `kubeconfig` based on the bootstrap token created in the garden cluster. Replace the `` with `token-id.token-secret` (from our previous example: `07401b.f395accd246ae52d`) from the bootstrap token secret. - + ```yaml apiVersion: v1 kind: Config @@ -275,7 +275,7 @@ We refer to the global configuration values as _gardenlet configuration_ in the ``` 3. In section `gardenClientConnection.bootstrapKubeconfig` of your gardenlet configuration, provide the bootstrap `kubeconfig` together with a name and namespace to the gardenlet Helm chart. - + ```yaml gardenClientConnection: bootstrapKubeconfig: @@ -284,14 +284,14 @@ We refer to the global configuration values as _gardenlet configuration_ in the kubeconfig: | # will be base64 encoded by helm ``` - + The bootstrap `kubeconfig` is stored in the specified secret. - -4. In section `gardenClientConnection.kubeconfigSecret` of your gardenlet configuration, - define a name and a namespace where the gardenlet stores - the real `kubeconfig` that it creates during the bootstrap process. If the secret doesn't exist, - the gardenlet creates it for you. - + +4. In section `gardenClientConnection.kubeconfigSecret` of your gardenlet configuration, + define a name and a namespace where the gardenlet stores + the real `kubeconfig` that it creates during the bootstrap process. If the secret doesn't exist, + the gardenlet creates it for you. + ```yaml gardenClientConnection: kubeconfigSecret: @@ -301,15 +301,15 @@ We refer to the global configuration values as _gardenlet configuration_ in the ## Automatically register shoot cluster as a seed cluster -A seed cluster can either be registered by manually creating -the [`Seed` resource](../../example/50-seed.yaml) -or automatically by the gardenlet. -This functionality is useful for managed seed clusters, -as the gardenlet in the garden cluster deploys a copy of itself -into the cluster with automatic registration of the `Seed` configured. +A seed cluster can either be registered by manually creating +the [`Seed` resource](../../example/50-seed.yaml) +or automatically by the gardenlet. +This functionality is useful for managed seed clusters, +as the gardenlet in the garden cluster deploys a copy of itself +into the cluster with automatic registration of the `Seed` configured. However, it can also be used to have a streamlined seed cluster registration process when manually deploying the gardenlet. -> This procedure doesn’t describe all the possible configurations +> This procedure doesn’t describe all the possible configurations > for the `Seed` resource. For more information, see: > * [Example Seed resource](../../example/50-seed.yaml) > * [Configurable Seed settings](../usage/seed_settings.md). @@ -317,12 +317,9 @@ However, it can also be used to have a streamlined seed cluster registration pro ### Adjust the gardenlet component configuration 1. Supply the `Seed` resource in section `seedConfig` of your gardenlet configuration `gardenlet-values.yaml`. - - > Note that with the `seedConfig` supplied, the gardenlet is only responsible to create and reconcile this one configured seed (in the previous example: `sweet-seed`). The gardenlet can also be configured to reconcile (but not create!) multiple Seeds [based on a label selector](../concepts/gardenlet.md#seed-config-vs-seed-selector), which is only recommended [for a development setup](../development/local_setup.md#appendix). - 1. Add the `seedConfig` to your gardenlet configuration `gardenlet-values.yaml`. The field `seedConfig.spec.provider.type` specifies the infrastructure provider type (for example, `aws`) of the seed cluster. -For all supported infrastructure providers, see [Known Extension Implementations](../../extensions/README.md#known-extension-implementations). +For all supported infrastructure providers, see [Known Extension Implementations](../../extensions/README.md#known-extension-implementations). ```yaml .... @@ -346,18 +343,18 @@ For all supported infrastructure providers, see [Known Extension Implementations ### Optional: Enable backup and restore -The seed cluster can be set up with backup and restore -for the main `etcds` of shoot clusters. +The seed cluster can be set up with backup and restore +for the main `etcds` of shoot clusters. Gardener uses [etcd-backup-restore](https://github.com/gardener/etcd-backup-restore) -that [integrates with different storage providers](https://github.com/gardener/etcd-backup-restore/blob/master/doc/usage/getting_started.md#usage) +that [integrates with different storage providers](https://github.com/gardener/etcd-backup-restore/blob/master/doc/usage/getting_started.md#usage) to store the shoot cluster's main `etcd` backups. Make sure to obtain client credentials that have sufficient permissions with the chosen storage provider. Create a secret in the garden cluster with client credentials for the storage provider. -The format of the secret is cloud provider specific and can be found -in the repository of the respective Gardener extension. -For example, the secret for AWS S3 can be found in the AWS provider extension +The format of the secret is cloud provider specific and can be found +in the repository of the respective Gardener extension. +For example, the secret for AWS S3 can be found in the AWS provider extension ([30-etcd-backup-secret.yaml](https://github.com/gardener/gardener-extension-provider-aws/blob/master/example/30-etcd-backup-secret.yaml)). ```yaml @@ -388,12 +385,12 @@ seedConfig: ## Deploy the gardenlet -> The gardenlet doesn’t have to run in the same Kubernetes cluster as the seed cluster -> it’s registering and reconciling, but it is in most cases advantageous -> to use in-cluster communication to talk to the Seed API server. +> The gardenlet doesn’t have to run in the same Kubernetes cluster as the seed cluster +> it’s registering and reconciling, but it is in most cases advantageous +> to use in-cluster communication to talk to the Seed API server. > Running a gardenlet outside of the cluster is mostly used for local development. -The `gardenlet-values.yaml` looks something like this +The `gardenlet-values.yaml` looks something like this (with automatic Seed registration and backup for shoot clusters enabled): ```yaml @@ -418,7 +415,7 @@ global: server: name: my-kubernetes-cluster .... - + kubeconfigSecret: name: gardenlet-kubeconfig namespace: garden @@ -467,37 +464,37 @@ This helm chart creates: ## Check that the gardenlet is successfully deployed 1. Check that the gardenlets certificate bootstrap was successful. - + Check if the secret `gardenlet-kubeconfig` in the namespace `garden` in the seed cluster is created and contains a `kubeconfig` with a valid certificate. - + 1. Get the `kubeconfig` from the created secret. - + ``` $ kubectl -n garden get secret gardenlet-kubeconfig -o json | jq -r .data.kubeconfig | base64 -d ``` - + 1. Test against the garden cluster and verify it’s working. - + 1. Extract the `client-certificate-data` from the user `gardenlet`. - + 1. View the certificate: - + ``` $ openssl x509 -in ./gardenlet-cert -noout -text ``` - - Check that the certificate is valid for a year (that is the lifetime of new certificates). - + + Check that the certificate is valid for a year (that is the lifetime of new certificates). + 2. Check that the bootstrap secret `gardenlet-bootstrap-kubeconfig` has been deleted from the seed cluster in namespace `garden`. - + 3. Check that the seed cluster is registered and `READY` in the garden cluster. - + Check that the seed cluster `sweet-seed` exists and all conditions indicate that it’s available. If so, the [Gardenlet is sending regular heartbeats](../concepts/gardenlet.md#heartbeats) and the [seed bootstrapping](../usage/seed_bootstrapping.md) was successful. - + Check that the conditions on the `Seed` resource look similar to the following: - + ```bash $ kubectl get seed sweet-seed -o json | jq .status.conditions [ diff --git a/docs/usage/managed_seed.md b/docs/usage/managed_seed.md index e97b1d1abdf..104339ff6ce 100644 --- a/docs/usage/managed_seed.md +++ b/docs/usage/managed_seed.md @@ -8,8 +8,8 @@ An existing shoot can be registered as a seed by creating a `ManagedSeed` resour * `gardenlet` deployment parameters, such as the number of replicas, the image, etc. * The `GardenletConfiguration` resource that contains controllers configuration, feature gates, and a `seedConfig` section that contains the `Seed` spec and parts of its metadata. * Additional configuration parameters, such as the garden connection bootstrap mechanism (see [TLS Bootstrapping](../concepts/gardenlet.md#tls-bootstrapping)), and whether to merge the provided configuration with the configuration of the parent `gardenlet`. - -Either the `seedTemplate` or the `gardenlet` section must be specified, but not both: + +Either the `seedTemplate` or the `gardenlet` section must be specified, but not both: * If the `seedTemplate` section is specified, `gardenlet` is not deployed to the shoot, and a new `Seed` resource is created based on the template. * If the `gardenlet` section is specified, `gardenlet` is deployed to the shoot, and it registers a new seed upon startup based on the `seedConfig` section of the `GardenletConfiguration` resource. @@ -17,9 +17,9 @@ Either the `seedTemplate` or the `gardenlet` section must be specified, but not Note the following important aspects: * Unlike the `Seed` resource, the `ManagedSeed` resource is namespaced. Currently, managed seeds are restricted to the `garden` namespace. -* The newly created `Seed` resource always has the same name as the `ManagedSeed` resource. Attempting to specify a different name in `seedTemplate` or `seedConfig` will fail. +* The newly created `Seed` resource always has the same name as the `ManagedSeed` resource. Attempting to specify a different name in `seedTemplate` or `seedConfig` will fail. * The `ManagedSeed` resource must always refer to an existing shoot. Attempting to create a `ManagedSeed` referring to a non-existing shoot will fail. -* A shoot that is being referred to by a `ManagedSeed` cannot be deleted. Attempting to delete such a shoot will fail. +* A shoot that is being referred to by a `ManagedSeed` cannot be deleted. Attempting to delete such a shoot will fail. * You can omit practically everything from the `seedTemplate` or `gardenlet` section, including all or most of the `Seed` spec fields. Proper defaults will be supplied in all cases, based either on the most common use cases or the information already available in the `Shoot` resource. * Some `Seed` spec fields, for example the provider type and region, networking CIDRs for pods, services, and nodes, etc., must be the same as the corresponding `Shoot` spec fields of the shoot that is being registered as seed. Attempting to use different values (except empty ones, so that they are supplied by the defaulting mechanims) will fail. @@ -55,9 +55,6 @@ spec: shoot: name: crazy-botany seedTemplate: - metadata: - labels: - seed.gardener.cloud/gardenlet: local spec: dns: ingressDomain: "" @@ -69,8 +66,6 @@ spec: region: "" ``` -Note the `seed.gardener.cloud/gardenlet: local` label above. It stands for the label that is used in a `seedSelector` field of a `gardenlet` that takes care of multiple seeds. This label can be omitted if the `seedSelector` field selects all seeds. If there is no gardenlet running outside the cluster and selecting the seed, it won't be reconciled and no shoots will be scheduled on it. - For an example that uses non-default configuration, see [55-managed-seed-seedtemplate.yaml](../../example/55-managedseed-seedtemplate.yaml) ## Migrating from the `use-as-seed` Annotation to `ManagedSeeds` @@ -97,6 +92,6 @@ Option | Description `apiServer.autoscaler.maxReplicas` | Controls the maximum number of `kube-apiserver` replicas for the shooted seed cluster. `apiServer.replicas` | Controls how many `kube-apiserver` replicas the shooted seed cluster gets by default. -For backward compatibility, it is still possible to specify these options via the `shoot.gardener.cloud/managed-seed-api-server` annotation, using exactly the same syntax as before. +For backward compatibility, it is still possible to specify these options via the `shoot.gardener.cloud/managed-seed-api-server` annotation, using exactly the same syntax as before. If you use any of these fields in any or your `use-as-seed` annotations, instead of removing the annotation completely as mentioned above, simply rename it to `managed-seed-api-server`, keeping these fields, and removing everything else. diff --git a/docs/usage/shooted_seed.md b/docs/usage/shooted_seed.md index 0100c35643c..0a38a2d9d12 100644 --- a/docs/usage/shooted_seed.md +++ b/docs/usage/shooted_seed.md @@ -56,7 +56,7 @@ It is strongly recommended to use such resources directly to register shoots as Option | Description --- | --- `true` | Registers the cluster as a seed cluster. Automatically deploys the gardenlet into the shoot cluster, unless specified otherwise (e.g. setting the `no-gardenlet` flag). -`no-gardenlet` | Prevents the automatic deployment of the gardenlet into the shoot cluster. Instead, the `Seed` object will be created with the assumption that another gardenlet will be responsible for managing it (according to its `seedSelector` configuration). +`no-gardenlet` | Prevents the automatic deployment of the gardenlet into the shoot cluster. Instead, the `Seed` object will be created with the assumption that another gardenlet will be responsible for managing it (according to its `seedConfig` configuration). `disable-capacity-reservation` | Set `spec.settings.excessCapacity.enabled` in the seed cluster to false (see [/example/50-seed.yaml](../../example/50-seed.yaml)). `invisible` | Set `spec.settings.scheduling.visible` in the seed cluster to false (see [/example/50-seed.yaml](../../example/50-seed.yaml)) `visible` | Set `spec.settings.scheduling.visible` in the seed cluster to true (see [/example/50-seed.yaml](../../example/50-seed.yaml)) (**default**). diff --git a/example/55-managedseed-seedtemplate.yaml b/example/55-managedseed-seedtemplate.yaml index 6c1ed1b0088..3f8ed7c1834 100644 --- a/example/55-managedseed-seedtemplate.yaml +++ b/example/55-managedseed-seedtemplate.yaml @@ -8,10 +8,7 @@ spec: name: crazy-botany # seedTemplate is a template for a Seed object, that should be used to register a given cluster as a Seed. # When seedTemplate is specified, the ManagedSeed controller will not deploy a gardenlet into the cluster - # and an existing gardenlet reconciling the new Seed is required. + # and an existing gardenlet reconciling the new Seed is required. seedTemplate: -# metadata: -# labels: -# seed.gardener.cloud/gardenlet: local # Label to use in seedSelector of the existing gardenlet spec: # Seed spec # diff --git a/landscaper/pkg/gardenlet/apis/imports/validation/validation.go b/landscaper/pkg/gardenlet/apis/imports/validation/validation.go index 191fdfdd34c..2afe95327ef 100644 --- a/landscaper/pkg/gardenlet/apis/imports/validation/validation.go +++ b/landscaper/pkg/gardenlet/apis/imports/validation/validation.go @@ -71,10 +71,6 @@ func ValidateLandscaperImports(imports *imports.Imports) field.ErrorList { func validateGardenletConfiguration(gardenletConfig *gardenletconfig.GardenletConfiguration, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} - if gardenletConfig.SeedSelector != nil { - allErrs = append(allErrs, field.Forbidden(fldPath.Child("seedSelector"), "seed selector is forbidden, provide a seedConfig instead.")) - } - if gardenletConfig.SeedConfig == nil { return append(allErrs, field.Required(fldPath.Child("seedConfig"), "the seed configuration has to be provided. This is used to automatically register the seed.")) } diff --git a/landscaper/pkg/gardenlet/apis/imports/validation/validation_test.go b/landscaper/pkg/gardenlet/apis/imports/validation/validation_test.go index 6a12aa645e2..3a5b3779794 100644 --- a/landscaper/pkg/gardenlet/apis/imports/validation/validation_test.go +++ b/landscaper/pkg/gardenlet/apis/imports/validation/validation_test.go @@ -115,31 +115,6 @@ var _ = Describe("ValidateLandscaperImports", func() { }) Context("validate Gardenlet configuration", func() { - It("should validate that the Seed selector is not set", func() { - // only pick one required Gardenlet component configuration to show that the configuration is indeed verified - // neither seedSelector nor seedConfig are provided. One of them has to be set to - // pass the validation of the GardenletConfiguration - gardenletConfiguration.SeedSelector = &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "x": "y", - }, - } - gardenletConfiguration.SeedConfig = nil - landscaperGardenletImport.ComponentConfiguration = &gardenletConfiguration - - errorList := ValidateLandscaperImports(landscaperGardenletImport) - Expect(errorList).To(ConsistOf( - PointTo(MatchFields(IgnoreExtras, Fields{ - "Type": Equal(field.ErrorTypeForbidden), - "Field": Equal("componentConfiguration.seedSelector"), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "Type": Equal(field.ErrorTypeRequired), - "Field": Equal("componentConfiguration.seedConfig"), - })), - )) - }) - It("should validate that the kubeconfig in the GardenClientConnection is not set", func() { gardenletConfiguration.GardenClientConnection = &gardenletconfigv1alpha1.GardenClientConnection{ ClientConnectionConfiguration: componentbaseconfigv1alpha1.ClientConnectionConfiguration{ diff --git a/pkg/apis/seedmanagement/validation/managedseed.go b/pkg/apis/seedmanagement/validation/managedseed.go index 8b225de3109..3433dbf5f23 100644 --- a/pkg/apis/seedmanagement/validation/managedseed.go +++ b/pkg/apis/seedmanagement/validation/managedseed.go @@ -293,11 +293,6 @@ func validateImage(image *seedmanagement.Image, fldPath *field.Path) field.Error func validateGardenletConfiguration(gardenletConfig *config.GardenletConfiguration, bootstrap seedmanagement.Bootstrap, mergeWithParent bool, fldPath *field.Path, inTemplate bool) field.ErrorList { allErrs := field.ErrorList{} - // Ensure seed selector is not specified - if gardenletConfig.SeedSelector != nil { - allErrs = append(allErrs, field.Forbidden(fldPath.Child("seedSelector"), "seed selector is forbidden")) - } - // Ensure name is not specified since it will be set by the controller if gardenletConfig.SeedConfig != nil && gardenletConfig.SeedConfig.Name != "" { allErrs = append(allErrs, field.Forbidden(fldPath.Child("seedConfig", "metadata", "name"), "seed name is forbidden")) diff --git a/pkg/client/kubernetes/clientmap/builder/deleg_builder.go b/pkg/client/kubernetes/clientmap/builder/deleg_builder.go index 625ccfc3241..c864c990825 100644 --- a/pkg/client/kubernetes/clientmap/builder/deleg_builder.go +++ b/pkg/client/kubernetes/clientmap/builder/deleg_builder.go @@ -27,7 +27,7 @@ import ( // based on the type of the key (e.g. a call with keys.ForShoot() will be delegated to the ShootClientMap). type DelegatingClientMapBuilder struct { gardenClientMapFunc func(logger logrus.FieldLogger) (clientmap.ClientMap, error) - seedClientMapFunc func(gardenClients clientmap.ClientMap, logger logrus.FieldLogger) (clientmap.ClientMap, error) + seedClientMapFunc func(logger logrus.FieldLogger) (clientmap.ClientMap, error) shootClientMapFunc func(gardenClients, seedClients clientmap.ClientMap, logger logrus.FieldLogger) (clientmap.ClientMap, error) plantClientMapFunc func(gardenClients clientmap.ClientMap, logger logrus.FieldLogger) (clientmap.ClientMap, error) @@ -69,7 +69,7 @@ func (b *DelegatingClientMapBuilder) WithGardenClientMapBuilder(builder *GardenC // WithSeedClientMap sets the ClientMap that should be used for Seed clients. func (b *DelegatingClientMapBuilder) WithSeedClientMap(clientMap clientmap.ClientMap) *DelegatingClientMapBuilder { - b.seedClientMapFunc = func(_ clientmap.ClientMap, _ logrus.FieldLogger) (clientmap.ClientMap, error) { + b.seedClientMapFunc = func(_ logrus.FieldLogger) (clientmap.ClientMap, error) { return clientMap, nil } return b @@ -77,10 +77,9 @@ func (b *DelegatingClientMapBuilder) WithSeedClientMap(clientMap clientmap.Clien // WithSeedClientMapBuilder sets a ClientMap builder that should be used to build a ClientMap for Seed clients. func (b *DelegatingClientMapBuilder) WithSeedClientMapBuilder(builder *SeedClientMapBuilder) *DelegatingClientMapBuilder { - b.seedClientMapFunc = func(gardenClients clientmap.ClientMap, logger logrus.FieldLogger) (clientmap.ClientMap, error) { + b.seedClientMapFunc = func(logger logrus.FieldLogger) (clientmap.ClientMap, error) { return builder. WithLogger(logger.WithField("ClientMap", "SeedClientMap")). - WithGardenClientMap(gardenClients). Build() } return b @@ -139,7 +138,7 @@ func (b *DelegatingClientMapBuilder) Build() (clientmap.ClientMap, error) { var seedClients, shootClients, plantClients clientmap.ClientMap if b.seedClientMapFunc != nil { - seedClients, err = b.seedClientMapFunc(gardenClients, b.logger) + seedClients, err = b.seedClientMapFunc(b.logger) if err != nil { return nil, fmt.Errorf("failed to construct seed ClientMap: %w", err) } diff --git a/pkg/client/kubernetes/clientmap/builder/deleg_builder_test.go b/pkg/client/kubernetes/clientmap/builder/deleg_builder_test.go index e8eb83cc7d9..cef647deeb3 100644 --- a/pkg/client/kubernetes/clientmap/builder/deleg_builder_test.go +++ b/pkg/client/kubernetes/clientmap/builder/deleg_builder_test.go @@ -73,7 +73,7 @@ var _ = Describe("DelegatingClientMapBuilder", func() { Context("#seedClientMapFunc", func() { It("should be set correctly by WithSeedClientMap", func() { builder := NewDelegatingClientMapBuilder().WithSeedClientMap(fakeSeedClientMap) - Expect(builder.seedClientMapFunc(nil, nil)).To(BeIdenticalTo(fakeSeedClientMap)) + Expect(builder.seedClientMapFunc(nil)).To(BeIdenticalTo(fakeSeedClientMap)) }) It("should be set correctly by WithSeedClientMapBuilder", func() { @@ -154,7 +154,7 @@ var _ = Describe("DelegatingClientMapBuilder", func() { builder := NewDelegatingClientMapBuilder(). WithLogger(fakeLogger). WithGardenClientMap(fakeGardenClientMap) - builder.seedClientMapFunc = func(clientmap.ClientMap, logrus.FieldLogger) (clientmap.ClientMap, error) { + builder.seedClientMapFunc = func(logrus.FieldLogger) (clientmap.ClientMap, error) { return nil, fakeErr } clientMap, err := builder.Build() diff --git a/pkg/client/kubernetes/clientmap/builder/seed_builder.go b/pkg/client/kubernetes/clientmap/builder/seed_builder.go index 0b7dd1e8a0c..b9965c8f78b 100644 --- a/pkg/client/kubernetes/clientmap/builder/seed_builder.go +++ b/pkg/client/kubernetes/clientmap/builder/seed_builder.go @@ -15,23 +15,18 @@ package builder import ( - "context" "fmt" "github.com/sirupsen/logrus" baseconfig "k8s.io/component-base/config" - "github.com/gardener/gardener/pkg/client/kubernetes" "github.com/gardener/gardener/pkg/client/kubernetes/clientmap" "github.com/gardener/gardener/pkg/client/kubernetes/clientmap/internal" - "github.com/gardener/gardener/pkg/client/kubernetes/clientmap/keys" ) // SeedClientMapBuilder can build a ClientMap which can be used to construct a ClientMap for requesting and storing // clients for Seed clusters. type SeedClientMapBuilder struct { - gardenClientFunc func(ctx context.Context) (kubernetes.Interface, error) - inCluster bool clientConnectionConfig *baseconfig.ClientConnectionConfiguration logger logrus.FieldLogger @@ -48,29 +43,6 @@ func (b *SeedClientMapBuilder) WithLogger(logger logrus.FieldLogger) *SeedClient return b } -// WithGardenClientMap sets the ClientMap that should be used to retrieve Garden clients. -func (b *SeedClientMapBuilder) WithGardenClientMap(clientMap clientmap.ClientMap) *SeedClientMapBuilder { - b.gardenClientFunc = func(ctx context.Context) (kubernetes.Interface, error) { - return clientMap.GetClient(ctx, keys.ForGarden()) - } - return b -} - -// WithGardenClientSet sets the ClientSet that should be used as the Garden client. -func (b *SeedClientMapBuilder) WithGardenClientSet(clientSet kubernetes.Interface) *SeedClientMapBuilder { - b.gardenClientFunc = func(ctx context.Context) (kubernetes.Interface, error) { - return clientSet, nil - } - return b -} - -// WithInCluster sets the inCluster attribute of the builder. If true, the created ClientSets will use in-cluster communication -// (using the provided ClientConnectionConfig.Kubeconfig or fallback to mounted ServiceAccount if unset). -func (b *SeedClientMapBuilder) WithInCluster(inCluster bool) *SeedClientMapBuilder { - b.inCluster = inCluster - return b -} - // WithClientConnectionConfig sets the ClientConnectionConfiguration that should be used by ClientSets created by this ClientMap. func (b *SeedClientMapBuilder) WithClientConnectionConfig(cfg *baseconfig.ClientConnectionConfiguration) *SeedClientMapBuilder { b.clientConnectionConfig = cfg @@ -82,16 +54,11 @@ func (b *SeedClientMapBuilder) Build() (clientmap.ClientMap, error) { if b.logger == nil { return nil, fmt.Errorf("logger is required but not set") } - if b.gardenClientFunc == nil { - return nil, fmt.Errorf("garden client is required but not set") - } if b.clientConnectionConfig == nil { return nil, fmt.Errorf("clientConnectionConfig is required but not set") } return internal.NewSeedClientMap(&internal.SeedClientSetFactory{ - GetGardenClient: b.gardenClientFunc, - InCluster: b.inCluster, ClientConnectionConfig: *b.clientConnectionConfig, }, b.logger), nil } diff --git a/pkg/client/kubernetes/clientmap/builder/seed_builder_test.go b/pkg/client/kubernetes/clientmap/builder/seed_builder_test.go index 2559c7e59f0..49bf8174514 100644 --- a/pkg/client/kubernetes/clientmap/builder/seed_builder_test.go +++ b/pkg/client/kubernetes/clientmap/builder/seed_builder_test.go @@ -15,11 +15,6 @@ package builder import ( - "context" - - fakeclientmap "github.com/gardener/gardener/pkg/client/kubernetes/clientmap/fake" - "github.com/gardener/gardener/pkg/client/kubernetes/clientmap/keys" - fakeclientset "github.com/gardener/gardener/pkg/client/kubernetes/fake" "github.com/gardener/gardener/pkg/logger" . "github.com/onsi/ginkgo" @@ -29,23 +24,14 @@ import ( ) var _ = Describe("SeedClientMapBuilder", func() { - var ( - ctx context.Context - - fakeLogger logrus.FieldLogger - fakeGardenClientMap *fakeclientmap.ClientMap - fakeGardenClientSet *fakeclientset.ClientSet + fakeLogger logrus.FieldLogger clientConnectionConfig *baseconfig.ClientConnectionConfiguration ) BeforeEach(func() { - ctx = context.TODO() - fakeLogger = logger.NewNopLogger() - fakeGardenClientSet = fakeclientset.NewClientSet() - fakeGardenClientMap = fakeclientmap.NewClientMapBuilder().WithClientSetForKey(keys.ForGarden(), fakeGardenClientSet).Build() clientConnectionConfig = &baseconfig.ClientConnectionConfiguration{} }) @@ -57,25 +43,6 @@ var _ = Describe("SeedClientMapBuilder", func() { }) }) - Context("#gardenClientFunc", func() { - It("should be correctly set by WithGardenClientSet", func() { - builder := NewSeedClientMapBuilder().WithGardenClientSet(fakeGardenClientSet) - Expect(builder.gardenClientFunc(ctx)).To(BeEquivalentTo(fakeGardenClientSet)) - }) - - It("should be correctly set by WithGardenClientMap", func() { - builder := NewSeedClientMapBuilder().WithGardenClientMap(fakeGardenClientMap) - Expect(builder.gardenClientFunc(ctx)).To(BeEquivalentTo(fakeGardenClientSet)) - }) - }) - - Context("#inCluster", func() { - It("should be correctly set by WithInCluster", func() { - builder := NewSeedClientMapBuilder().WithInCluster(true) - Expect(builder.inCluster).To(BeTrue()) - }) - }) - Context("#clientConnectionConfig", func() { It("should be correctly set by WithClientConnectionConfig", func() { builder := NewSeedClientMapBuilder().WithClientConnectionConfig(clientConnectionConfig) @@ -90,14 +57,8 @@ var _ = Describe("SeedClientMapBuilder", func() { Expect(clientMap).To(BeNil()) }) - It("should fail if garden ClientMap was not set", func() { - clientMap, err := NewSeedClientMapBuilder().WithLogger(fakeLogger).Build() - Expect(err).To(MatchError("garden client is required but not set")) - Expect(clientMap).To(BeNil()) - }) - It("should fail if clientConnectionConfig was not set", func() { - clientMap, err := NewSeedClientMapBuilder().WithLogger(fakeLogger).WithGardenClientSet(fakeGardenClientSet).Build() + clientMap, err := NewSeedClientMapBuilder().WithLogger(fakeLogger).Build() Expect(err).To(MatchError("clientConnectionConfig is required but not set")) Expect(clientMap).To(BeNil()) }) @@ -105,7 +66,6 @@ var _ = Describe("SeedClientMapBuilder", func() { It("should succeed to build ClientMap", func() { clientSet, err := NewSeedClientMapBuilder(). WithLogger(fakeLogger). - WithGardenClientMap(fakeGardenClientMap). WithClientConnectionConfig(clientConnectionConfig). Build() Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/client/kubernetes/clientmap/internal/seed_clientmap.go b/pkg/client/kubernetes/clientmap/internal/seed_clientmap.go index 6f720a7e479..793eaf5c475 100644 --- a/pkg/client/kubernetes/clientmap/internal/seed_clientmap.go +++ b/pkg/client/kubernetes/clientmap/internal/seed_clientmap.go @@ -19,14 +19,11 @@ import ( "fmt" "github.com/sirupsen/logrus" - corev1 "k8s.io/api/core/v1" baseconfig "k8s.io/component-base/config" "sigs.k8s.io/controller-runtime/pkg/client" - gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1" "github.com/gardener/gardener/pkg/client/kubernetes" "github.com/gardener/gardener/pkg/client/kubernetes/clientmap" - "github.com/gardener/gardener/pkg/utils" ) // seedClientMap is a ClientMap for requesting and storing clients for Seed clusters. @@ -43,92 +40,34 @@ func NewSeedClientMap(factory *SeedClientSetFactory, logger logrus.FieldLogger) // SeedClientSetFactory is a ClientSetFactory that can produce new ClientSets to Seed clusters. type SeedClientSetFactory struct { - // GetGardenClient is a func that will be used to get a client to the garden cluster to retrieve the Seed's - // kubeconfig secret (if InCluster=false). - GetGardenClient func(ctx context.Context) (kubernetes.Interface, error) - // If InCluster is set to true, the created ClientSets will use in-cluster communication - // (using ClientConnectionConfig.Kubeconfig or fallback to mounted ServiceAccount if unset). - InCluster bool // ClientConnectionConfiguration is the configuration that will be used by created ClientSets. ClientConnectionConfig baseconfig.ClientConnectionConfiguration } -// CalculateClientSetHash returns "" if the gardenlet uses in-cluster communication. Otherwise, it calculates a SHA256 -// hash of the kubeconfig in the seed secret. +// CalculateClientSetHash always returns "" and nil. func (f *SeedClientSetFactory) CalculateClientSetHash(ctx context.Context, k clientmap.ClientSetKey) (string, error) { - key, ok := k.(SeedClientSetKey) - if !ok { - return "", fmt.Errorf("unsupported ClientSetKey: expected %T got %T", SeedClientSetKey(""), k) - } - - if f.InCluster { - return "", nil - } - - secretRef, gardenClient, err := f.getSeedSecretRef(ctx, key) - if err != nil { - return "", err - } - - kubeconfigSecret := &corev1.Secret{} - if err := gardenClient.Client().Get(ctx, client.ObjectKey{Namespace: secretRef.Namespace, Name: secretRef.Name}, kubeconfigSecret); err != nil { - return "", err - } - - return utils.ComputeSHA256Hex(kubeconfigSecret.Data[kubernetes.KubeConfig]), nil + return "", nil } // NewClientSet creates a new ClientSet for a Seed cluster. func (f *SeedClientSetFactory) NewClientSet(ctx context.Context, k clientmap.ClientSetKey) (kubernetes.Interface, error) { - key, ok := k.(SeedClientSetKey) + _, ok := k.(SeedClientSetKey) if !ok { - return nil, fmt.Errorf("unsupported ClientSetKey: expected %T got %T", SeedClientSetKey(""), k) - } - - if f.InCluster { - return NewClientFromFile( - "", - f.ClientConnectionConfig.Kubeconfig, - kubernetes.WithClientConnectionOptions(f.ClientConnectionConfig), - kubernetes.WithClientOptions( - client.Options{ - Scheme: kubernetes.SeedScheme, - }, - ), - ) + return nil, fmt.Errorf("unsupported ClientSetKey: expected %T, but got %T", SeedClientSetKey(""), k) } - secretRef, gardenClient, err := f.getSeedSecretRef(ctx, key) - if err != nil { - return nil, err - } - - return NewClientFromSecret(ctx, gardenClient.Client(), secretRef.Namespace, secretRef.Name, + return NewClientFromFile( + "", + f.ClientConnectionConfig.Kubeconfig, kubernetes.WithClientConnectionOptions(f.ClientConnectionConfig), - kubernetes.WithClientOptions(client.Options{ - Scheme: kubernetes.SeedScheme, - }), + kubernetes.WithClientOptions( + client.Options{ + Scheme: kubernetes.SeedScheme, + }, + ), ) } -func (f *SeedClientSetFactory) getSeedSecretRef(ctx context.Context, key SeedClientSetKey) (*corev1.SecretReference, kubernetes.Interface, error) { - gardenClient, err := f.GetGardenClient(ctx) - if err != nil { - return nil, nil, fmt.Errorf("failed to get garden client: %w", err) - } - - seed := &gardencorev1beta1.Seed{} - if err := gardenClient.Client().Get(ctx, client.ObjectKey{Name: key.Key()}, seed); err != nil { - return nil, nil, fmt.Errorf("failed to get Seed object %q: %w", key.Key(), err) - } - - if seed.Spec.SecretRef == nil { - return nil, nil, fmt.Errorf("seed %q does not have a secretRef", key.Key()) - } - - return seed.Spec.SecretRef, gardenClient, nil -} - // SeedClientSetKey is a ClientSetKey for a Seed cluster. type SeedClientSetKey string diff --git a/pkg/client/kubernetes/clientmap/internal/seed_clientmap_test.go b/pkg/client/kubernetes/clientmap/internal/seed_clientmap_test.go index ef914eace67..001bcbe4dda 100644 --- a/pkg/client/kubernetes/clientmap/internal/seed_clientmap_test.go +++ b/pkg/client/kubernetes/clientmap/internal/seed_clientmap_test.go @@ -26,13 +26,11 @@ import ( fakeclientset "github.com/gardener/gardener/pkg/client/kubernetes/fake" . "github.com/gardener/gardener/pkg/client/kubernetes/test" "github.com/gardener/gardener/pkg/logger" - mockclient "github.com/gardener/gardener/pkg/mock/controller-runtime/client" "github.com/golang/mock/gomock" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" baseconfig "k8s.io/component-base/config" "sigs.k8s.io/controller-runtime/pkg/client" @@ -40,10 +38,8 @@ import ( var _ = Describe("SeedClientMap", func() { var ( - ctx context.Context - ctrl *gomock.Controller - c *mockclient.MockClient - fakeGardenClient *fakeclientset.ClientSet + ctx context.Context + ctrl *gomock.Controller cm clientmap.ClientMap key clientmap.ClientSetKey @@ -56,8 +52,6 @@ var _ = Describe("SeedClientMap", func() { BeforeEach(func() { ctx = context.TODO() ctrl = gomock.NewController(GinkgoT()) - c = mockclient.NewMockClient(ctrl) - fakeGardenClient = fakeclientset.NewClientSetBuilder().WithClient(c).Build() seed = &gardencorev1beta1.Seed{ ObjectMeta: metav1.ObjectMeta{ @@ -81,9 +75,6 @@ var _ = Describe("SeedClientMap", func() { Burst: 43, } factory = &internal.SeedClientSetFactory{ - GetGardenClient: func(ctx context.Context) (kubernetes.Interface, error) { - return fakeGardenClient, nil - }, ClientConnectionConfig: clientConnectionConfig, } cm = internal.NewSeedClientMap(factory, logger.NewNopLogger()) @@ -94,15 +85,7 @@ var _ = Describe("SeedClientMap", func() { }) Context("#GetClient", func() { - It("should fail if ClientSetKey type is unsupported", func() { - key = fakeKey{} - cs, err := cm.GetClient(ctx, key) - Expect(cs).To(BeNil()) - Expect(err).To(MatchError(ContainSubstring("unsupported ClientSetKey"))) - }) - - It("should fail if NewClientFromFile fails (in-cluster)", func() { - factory.InCluster = true + It("should fail if NewClientFromSecret fails", func() { fakeErr := fmt.Errorf("fake") internal.NewClientFromFile = func(masterURL, kubeconfigPath string, fns ...kubernetes.ConfigFunc) (kubernetes.Interface, error) { return nil, fakeErr @@ -113,8 +96,7 @@ var _ = Describe("SeedClientMap", func() { Expect(err).To(MatchError(fmt.Sprintf("error creating new ClientSet for key %q: fake", key.Key()))) }) - It("should correctly construct a new ClientSet (in-cluster)", func() { - factory.InCluster = true + It("should correctly construct a new ClientSet", func() { fakeCS := fakeclientset.NewClientSet() internal.NewClientFromFile = func(masterURL, kubeconfigPath string, fns ...kubernetes.ConfigFunc) (kubernetes.Interface, error) { Expect(masterURL).To(BeEmpty()) @@ -130,134 +112,13 @@ var _ = Describe("SeedClientMap", func() { Expect(err).NotTo(HaveOccurred()) Expect(cs).To(BeIdenticalTo(fakeCS)) }) - - It("should fail if GetGardenClient fails", func() { - fakeErr := fmt.Errorf("fake") - factory.GetGardenClient = func(ctx context.Context) (kubernetes.Interface, error) { - return nil, fakeErr - } - - cs, err := cm.GetClient(ctx, key) - Expect(cs).To(BeNil()) - Expect(err).To(MatchError(ContainSubstring("failed to get garden client: fake"))) - }) - - It("should fail if it cannot get Seed object", func() { - c.EXPECT().Get(ctx, client.ObjectKey{Name: seed.Name}, gomock.AssignableToTypeOf(&gardencorev1beta1.Seed{})). - Return(apierrors.NewNotFound(gardencorev1beta1.Resource("seed"), seed.Name)) - - cs, err := cm.GetClient(ctx, key) - Expect(cs).To(BeNil()) - Expect(err).To(MatchError(ContainSubstring("failed to get Seed object"))) - }) - - It("should fail if Seed object does not have a secretRef", func() { - seed.Spec.SecretRef = nil - c.EXPECT().Get(ctx, client.ObjectKey{Name: seed.Name}, gomock.AssignableToTypeOf(&gardencorev1beta1.Seed{})). - DoAndReturn(func(ctx context.Context, key client.ObjectKey, obj client.Object) error { - seed.DeepCopyInto(obj.(*gardencorev1beta1.Seed)) - return nil - }) - - cs, err := cm.GetClient(ctx, key) - Expect(cs).To(BeNil()) - Expect(err).To(MatchError(ContainSubstring("does not have a secretRef"))) - }) - - It("should fail if NewClientFromSecret fails", func() { - fakeErr := fmt.Errorf("fake") - c.EXPECT().Get(ctx, client.ObjectKey{Name: seed.Name}, gomock.AssignableToTypeOf(&gardencorev1beta1.Seed{})). - DoAndReturn(func(ctx context.Context, key client.ObjectKey, obj client.Object) error { - seed.DeepCopyInto(obj.(*gardencorev1beta1.Seed)) - return nil - }) - internal.NewClientFromSecret = func(ctx context.Context, c client.Client, namespace, secretName string, fns ...kubernetes.ConfigFunc) (kubernetes.Interface, error) { - return nil, fakeErr - } - - cs, err := cm.GetClient(ctx, key) - Expect(cs).To(BeNil()) - Expect(err).To(MatchError(fmt.Sprintf("error creating new ClientSet for key %q: fake", key.Key()))) - }) - - It("should correctly construct a new ClientSet", func() { - fakeCS := fakeclientset.NewClientSet() - c.EXPECT().Get(ctx, client.ObjectKey{Name: seed.Name}, gomock.AssignableToTypeOf(&gardencorev1beta1.Seed{})). - DoAndReturn(func(ctx context.Context, key client.ObjectKey, obj client.Object) error { - seed.DeepCopyInto(obj.(*gardencorev1beta1.Seed)) - return nil - }).Times(2) - c.EXPECT().Get(ctx, client.ObjectKey{Namespace: seed.Spec.SecretRef.Namespace, Name: seed.Spec.SecretRef.Name}, gomock.AssignableToTypeOf(&corev1.Secret{})). - DoAndReturn(func(ctx context.Context, key client.ObjectKey, obj client.Object) error { - return nil - }) - internal.NewClientFromSecret = func(ctx context.Context, c client.Client, namespace, secretName string, fns ...kubernetes.ConfigFunc) (kubernetes.Interface, error) { - Expect(c).To(BeIdenticalTo(fakeGardenClient.Client())) - Expect(namespace).To(Equal(seed.Spec.SecretRef.Namespace)) - Expect(secretName).To(Equal(seed.Spec.SecretRef.Name)) - Expect(fns).To(ConsistOfConfigFuncs( - kubernetes.WithClientConnectionOptions(clientConnectionConfig), - kubernetes.WithClientOptions(client.Options{Scheme: kubernetes.SeedScheme}), - )) - return fakeCS, nil - } - - cs, err := cm.GetClient(ctx, key) - Expect(err).NotTo(HaveOccurred()) - Expect(cs).To(BeIdenticalTo(fakeCS)) - }) }) Context("#CalculateClientSetHash", func() { - It("should fail if ClientSetKey type is unsupported", func() { + It("should always return the same identifier", func() { key = fakeKey{} hash, err := factory.CalculateClientSetHash(ctx, key) Expect(hash).To(BeEmpty()) - Expect(err).To(MatchError(ContainSubstring("unsupported ClientSetKey"))) - }) - - It("should fail if getSeedSecretRef fails", func() { - fakeErr := fmt.Errorf("fake") - factory.GetGardenClient = func(ctx context.Context) (kubernetes.Interface, error) { - return nil, fakeErr - } - - hash, err := factory.CalculateClientSetHash(ctx, key) - Expect(hash).To(BeEmpty()) - Expect(err).To(MatchError(ContainSubstring("failed to get garden client: fake"))) - }) - - It("should fail if Get Seed Secret fails", func() { - fakeErr := fmt.Errorf("fake") - c.EXPECT().Get(ctx, client.ObjectKey{Name: seed.Name}, gomock.AssignableToTypeOf(&gardencorev1beta1.Seed{})). - DoAndReturn(func(ctx context.Context, key client.ObjectKey, obj client.Object) error { - seed.DeepCopyInto(obj.(*gardencorev1beta1.Seed)) - return nil - }) - c.EXPECT().Get(ctx, client.ObjectKey{Namespace: seed.Spec.SecretRef.Namespace, Name: seed.Spec.SecretRef.Name}, gomock.AssignableToTypeOf(&corev1.Secret{})). - DoAndReturn(func(ctx context.Context, key client.ObjectKey, obj client.Object) error { - return fakeErr - }) - - hash, err := factory.CalculateClientSetHash(ctx, key) - Expect(hash).To(BeEmpty()) - Expect(err).To(MatchError("fake")) - }) - - It("should correctly calculate hash", func() { - c.EXPECT().Get(ctx, client.ObjectKey{Name: seed.Name}, gomock.AssignableToTypeOf(&gardencorev1beta1.Seed{})). - DoAndReturn(func(ctx context.Context, key client.ObjectKey, obj client.Object) error { - seed.DeepCopyInto(obj.(*gardencorev1beta1.Seed)) - return nil - }) - c.EXPECT().Get(ctx, client.ObjectKey{Namespace: seed.Spec.SecretRef.Namespace, Name: seed.Spec.SecretRef.Name}, gomock.AssignableToTypeOf(&corev1.Secret{})). - DoAndReturn(func(ctx context.Context, key client.ObjectKey, obj client.Object) error { - (&corev1.Secret{}).DeepCopyInto(obj.(*corev1.Secret)) - return nil - }) - - hash, err := factory.CalculateClientSetHash(ctx, key) - Expect(hash).To(Equal("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")) Expect(err).NotTo(HaveOccurred()) }) }) diff --git a/pkg/controllerutils/seedfilter.go b/pkg/controllerutils/seedfilter.go index 8c92cafe431..5d08790c20f 100644 --- a/pkg/controllerutils/seedfilter.go +++ b/pkg/controllerutils/seedfilter.go @@ -21,41 +21,27 @@ import ( gardencorev1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants" operationsv1alpha1 "github.com/gardener/gardener/pkg/apis/operations/v1alpha1" seedmanagementv1alpha1 "github.com/gardener/gardener/pkg/apis/seedmanagement/v1alpha1" - gardencorelisters "github.com/gardener/gardener/pkg/client/core/listers/core/v1beta1" "github.com/gardener/gardener/pkg/gardenlet/apis/config" confighelper "github.com/gardener/gardener/pkg/gardenlet/apis/config/helper" kutil "github.com/gardener/gardener/pkg/utils/kubernetes" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" "sigs.k8s.io/controller-runtime/pkg/client" ) -// LabelsMatchFor checks whether the given label selector matches for the given set of labels. -func LabelsMatchFor(l map[string]string, labelSelector *metav1.LabelSelector) bool { - selector, err := metav1.LabelSelectorAsSelector(labelSelector) - if err != nil { - return false - } - return selector.Matches(labels.Set(l)) -} - -// SeedFilterFunc returns a filtering func for the seeds and the given label selector. -func SeedFilterFunc(seedName string, labelSelector *metav1.LabelSelector) func(obj interface{}) bool { +// SeedFilterFunc returns a filtering func for the seeds. +func SeedFilterFunc(seedName string) func(obj interface{}) bool { return func(obj interface{}) bool { seed, ok := obj.(*gardencorev1beta1.Seed) if !ok { return false } - if len(seedName) > 0 { - return seed.Name == seedName - } - return LabelsMatchFor(seed.Labels, labelSelector) + + return seed.Name == seedName } } -// ShootFilterFunc returns a filtering func for the seeds and the given label selector. -func ShootFilterFunc(seedName string, seedLister gardencorelisters.SeedLister, labelSelector *metav1.LabelSelector) func(obj interface{}) bool { +// ShootFilterFunc returns a filtering func for the seeds. +func ShootFilterFunc(seedName string) func(obj interface{}) bool { return func(obj interface{}) bool { shoot, ok := obj.(*gardencorev1beta1.Shoot) if !ok { @@ -64,67 +50,34 @@ func ShootFilterFunc(seedName string, seedLister gardencorelisters.SeedLister, l if shoot.Spec.SeedName == nil { return false } - if len(seedName) > 0 { - if shoot.Status.SeedName == nil || *shoot.Spec.SeedName == *shoot.Status.SeedName { - return *shoot.Spec.SeedName == seedName - } - return *shoot.Status.SeedName == seedName - } + if shoot.Status.SeedName == nil || *shoot.Spec.SeedName == *shoot.Status.SeedName { - return SeedLabelsMatch(seedLister, *shoot.Spec.SeedName, labelSelector) + return *shoot.Spec.SeedName == seedName } - return SeedLabelsMatch(seedLister, *shoot.Status.SeedName, labelSelector) - } -} - -// ShootIsManagedByThisGardenlet checks if the given shoot is managed by this gardenlet by comparing it with the seed name from the GardenletConfiguration -// or by checking whether the seed labels match the seed selector from the GardenletConfiguration. -func ShootIsManagedByThisGardenlet(shoot *gardencorev1beta1.Shoot, gc *config.GardenletConfiguration, seedLister gardencorelisters.SeedLister) bool { - seedName := confighelper.SeedNameFromSeedConfig(gc.SeedConfig) - if len(seedName) > 0 { - return *shoot.Spec.SeedName == seedName - } - return SeedLabelsMatch(seedLister, *shoot.Spec.SeedName, gc.SeedSelector) -} -// SeedLabelsMatch fetches the given seed via a lister by its name and then checks whether the given label selector matches -// the seed labels. -func SeedLabelsMatch(seedLister gardencorelisters.SeedLister, seedName string, labelSelector *metav1.LabelSelector) bool { - seed, err := seedLister.Get(seedName) - if err != nil { - return false + return *shoot.Status.SeedName == seedName } - - return LabelsMatchFor(seed.Labels, labelSelector) } -// seedLabelsMatchWithClient fetches the given seed by its name from the client and then checks whether the given -// label selector matches the seed labels. -func seedLabelsMatchWithClient(ctx context.Context, c client.Reader, seedName string, labelSelector *metav1.LabelSelector) bool { - seed := &gardencorev1beta1.Seed{} - if err := c.Get(ctx, client.ObjectKey{Name: seedName}, seed); err != nil { - return false - } - - return LabelsMatchFor(seed.Labels, labelSelector) +// ShootIsManagedByThisGardenlet checks if the given shoot is managed by this gardenlet by comparing it with the seed name from the GardenletConfiguration. +func ShootIsManagedByThisGardenlet(shoot *gardencorev1beta1.Shoot, gc *config.GardenletConfiguration) bool { + return *shoot.Spec.SeedName == confighelper.SeedNameFromSeedConfig(gc.SeedConfig) } -// ControllerInstallationFilterFunc returns a filtering func for the seeds and the given label selector. -func ControllerInstallationFilterFunc(seedName string, seedLister gardencorelisters.SeedLister, labelSelector *metav1.LabelSelector) func(obj interface{}) bool { +// ControllerInstallationFilterFunc returns a filtering func for the seeds. +func ControllerInstallationFilterFunc(seedName string) func(obj interface{}) bool { return func(obj interface{}) bool { controllerInstallation, ok := obj.(*gardencorev1beta1.ControllerInstallation) if !ok { return false } - if len(seedName) > 0 { - return controllerInstallation.Spec.SeedRef.Name == seedName - } - return SeedLabelsMatch(seedLister, controllerInstallation.Spec.SeedRef.Name, labelSelector) + + return controllerInstallation.Spec.SeedRef.Name == seedName } } -// BackupBucketFilterFunc returns a filtering func for the seeds and the given label selector. -func BackupBucketFilterFunc(ctx context.Context, c client.Reader, seedName string, labelSelector *metav1.LabelSelector) func(obj interface{}) bool { +// BackupBucketFilterFunc returns a filtering func for the seeds. +func BackupBucketFilterFunc(seedName string) func(obj interface{}) bool { return func(obj interface{}) bool { backupBucket, ok := obj.(*gardencorev1beta1.BackupBucket) if !ok { @@ -133,15 +86,13 @@ func BackupBucketFilterFunc(ctx context.Context, c client.Reader, seedName strin if backupBucket.Spec.SeedName == nil { return false } - if len(seedName) > 0 { - return *backupBucket.Spec.SeedName == seedName - } - return seedLabelsMatchWithClient(ctx, c, *backupBucket.Spec.SeedName, labelSelector) + + return *backupBucket.Spec.SeedName == seedName } } -// BackupEntryFilterFunc returns a filtering func for the seeds and the given label selector. -func BackupEntryFilterFunc(ctx context.Context, c client.Reader, seedName string, labelSelector *metav1.LabelSelector) func(obj interface{}) bool { +// BackupEntryFilterFunc returns a filtering func for the seeds. +func BackupEntryFilterFunc(seedName string) func(obj interface{}) bool { return func(obj interface{}) bool { backupEntry, ok := obj.(*gardencorev1beta1.BackupEntry) if !ok { @@ -150,31 +101,24 @@ func BackupEntryFilterFunc(ctx context.Context, c client.Reader, seedName string if backupEntry.Spec.SeedName == nil { return false } - if len(seedName) > 0 { - if backupEntry.Status.SeedName == nil || *backupEntry.Spec.SeedName == *backupEntry.Status.SeedName { - return *backupEntry.Spec.SeedName == seedName - } - return *backupEntry.Status.SeedName == seedName - } + if backupEntry.Status.SeedName == nil || *backupEntry.Spec.SeedName == *backupEntry.Status.SeedName { - return seedLabelsMatchWithClient(ctx, c, *backupEntry.Spec.SeedName, labelSelector) + return *backupEntry.Spec.SeedName == seedName } - return seedLabelsMatchWithClient(ctx, c, *backupEntry.Status.SeedName, labelSelector) + + return *backupEntry.Status.SeedName == seedName } } -// BackupEntryIsManagedByThisGardenlet checks if the given BackupEntry is managed by this gardenlet by comparing it with the seed name from the GardenletConfiguration -// or by checking whether the seed labels match the seed selector from the GardenletConfiguration. -func BackupEntryIsManagedByThisGardenlet(ctx context.Context, c client.Reader, backupEntry *gardencorev1beta1.BackupEntry, gc *config.GardenletConfiguration) bool { +// BackupEntryIsManagedByThisGardenlet checks if the given BackupEntry is managed by this gardenlet by comparing it with the seed name from the GardenletConfiguration. +func BackupEntryIsManagedByThisGardenlet(backupEntry *gardencorev1beta1.BackupEntry, gc *config.GardenletConfiguration) bool { seedName := confighelper.SeedNameFromSeedConfig(gc.SeedConfig) - if len(seedName) > 0 { - return backupEntry.Spec.SeedName != nil && *backupEntry.Spec.SeedName == seedName - } - return seedLabelsMatchWithClient(ctx, c, *backupEntry.Spec.SeedName, gc.SeedSelector) + + return backupEntry.Spec.SeedName != nil && *backupEntry.Spec.SeedName == seedName } -// BastionFilterFunc returns a filtering func for the seeds and the given label selector. -func BastionFilterFunc(ctx context.Context, c client.Reader, seedName string, labelSelector *metav1.LabelSelector) func(obj interface{}) bool { +// BastionFilterFunc returns a filtering func for the seeds. +func BastionFilterFunc(seedName string) func(obj interface{}) bool { return func(obj interface{}) bool { bastion, ok := obj.(*operationsv1alpha1.Bastion) if !ok { @@ -183,25 +127,20 @@ func BastionFilterFunc(ctx context.Context, c client.Reader, seedName string, la if bastion.Spec.SeedName == nil { return false } - if len(seedName) > 0 { - return *bastion.Spec.SeedName == seedName - } - return seedLabelsMatchWithClient(ctx, c, *bastion.Spec.SeedName, labelSelector) + + return *bastion.Spec.SeedName == seedName } } -// BastionIsManagedByThisGardenlet checks if the given Bastion is managed by this gardenlet by comparing it with the seed name from the GardenletConfiguration -// or by checking whether the seed labels match the seed selector from the GardenletConfiguration. -func BastionIsManagedByThisGardenlet(ctx context.Context, c client.Reader, bastion *operationsv1alpha1.Bastion, gc *config.GardenletConfiguration) bool { +// BastionIsManagedByThisGardenlet checks if the given Bastion is managed by this gardenlet by comparing it with the seed name from the GardenletConfiguration. +func BastionIsManagedByThisGardenlet(bastion *operationsv1alpha1.Bastion, gc *config.GardenletConfiguration) bool { seedName := confighelper.SeedNameFromSeedConfig(gc.SeedConfig) - if len(seedName) > 0 { - return bastion.Spec.SeedName != nil && *bastion.Spec.SeedName == seedName - } - return seedLabelsMatchWithClient(ctx, c, *bastion.Spec.SeedName, gc.SeedSelector) + + return bastion.Spec.SeedName != nil && *bastion.Spec.SeedName == seedName } // ManagedSeedFilterFunc returns a filtering func for ManagedSeeds that checks if the ManagedSeed references a Shoot scheduled on a Seed, for which the gardenlet is responsible.. -func ManagedSeedFilterFunc(ctx context.Context, c client.Reader, seedName string, labelSelector *metav1.LabelSelector) func(obj interface{}) bool { +func ManagedSeedFilterFunc(ctx context.Context, c client.Reader, seedName string) func(obj interface{}) bool { return func(obj interface{}) bool { managedSeed, ok := obj.(*seedmanagementv1alpha1.ManagedSeed) if !ok { @@ -217,22 +156,18 @@ func ManagedSeedFilterFunc(ctx context.Context, c client.Reader, seedName string if shoot.Spec.SeedName == nil { return false } - if len(seedName) > 0 { - if shoot.Status.SeedName == nil || *shoot.Spec.SeedName == *shoot.Status.SeedName { - return *shoot.Spec.SeedName == seedName - } - return *shoot.Status.SeedName == seedName - } + if shoot.Status.SeedName == nil || *shoot.Spec.SeedName == *shoot.Status.SeedName { - return seedLabelsMatchWithClient(ctx, c, *shoot.Spec.SeedName, labelSelector) + return *shoot.Spec.SeedName == seedName } - return seedLabelsMatchWithClient(ctx, c, *shoot.Status.SeedName, labelSelector) + + return *shoot.Status.SeedName == seedName } } // SeedOfManagedSeedFilterFunc returns a filtering func for Seeds that checks if the Seed is owned by a ManagedSeed // that references a Shoot scheduled on a Seed, for which the gardenlet is responsible. -func SeedOfManagedSeedFilterFunc(ctx context.Context, c client.Reader, seedName string, labelSelector *metav1.LabelSelector) func(obj interface{}) bool { +func SeedOfManagedSeedFilterFunc(ctx context.Context, c client.Reader, seedName string) func(obj interface{}) bool { return func(obj interface{}) bool { seed, ok := obj.(*gardencorev1beta1.Seed) if !ok { @@ -242,6 +177,6 @@ func SeedOfManagedSeedFilterFunc(ctx context.Context, c client.Reader, seedName if err := c.Get(ctx, kutil.Key(gardencorev1beta1constants.GardenNamespace, seed.Name), managedSeed); err != nil { return false } - return ManagedSeedFilterFunc(ctx, c, seedName, labelSelector)(managedSeed) + return ManagedSeedFilterFunc(ctx, c, seedName)(managedSeed) } } diff --git a/pkg/controllerutils/seedfilter_test.go b/pkg/controllerutils/seedfilter_test.go index 771f513d23d..f1e3cf85db3 100644 --- a/pkg/controllerutils/seedfilter_test.go +++ b/pkg/controllerutils/seedfilter_test.go @@ -52,7 +52,6 @@ var _ = Describe("seedfilter", func() { managedSeed *seedmanagementv1alpha1.ManagedSeed shoot *gardencorev1beta1.Shoot - seed *gardencorev1beta1.Seed seedOfManagedSeed *gardencorev1beta1.Seed ) @@ -85,14 +84,6 @@ var _ = Describe("seedfilter", func() { SeedName: pointer.String(seedName), }, } - seed = &gardencorev1beta1.Seed{ - ObjectMeta: metav1.ObjectMeta{ - Name: seedName, - Labels: map[string]string{ - "test-label": "test", - }, - }, - } seedOfManagedSeed = &gardencorev1beta1.Seed{ ObjectMeta: metav1.ObjectMeta{ Name: name, @@ -122,15 +113,6 @@ var _ = Describe("seedfilter", func() { ) } - expectGetSeed = func() { - c.EXPECT().Get(ctx, kutil.Key(seedName), gomock.AssignableToTypeOf(&gardencorev1beta1.Seed{})).DoAndReturn( - func(_ context.Context, _ client.ObjectKey, s *gardencorev1beta1.Seed) error { - *s = *seed - return nil - }, - ) - } - expectGetManagedSeed = func() { c.EXPECT().Get(ctx, kutil.Key(namespace, name), gomock.AssignableToTypeOf(&seedmanagementv1alpha1.ManagedSeed{})).DoAndReturn( func(_ context.Context, _ client.ObjectKey, ms *seedmanagementv1alpha1.ManagedSeed) error { @@ -151,93 +133,59 @@ var _ = Describe("seedfilter", func() { Describe("#ManagedSeedFilterFunc", func() { It("should return false if the specified object is not a managed seed", func() { - f := controllerutils.ManagedSeedFilterFunc(ctx, c, seedName, nil) + f := controllerutils.ManagedSeedFilterFunc(ctx, c, seedName) Expect(f(shoot)).To(BeFalse()) }) It("should return false with a shoot that is not found", func() { expectGetShootNotFound() - f := controllerutils.ManagedSeedFilterFunc(ctx, c, seedName, nil) + f := controllerutils.ManagedSeedFilterFunc(ctx, c, seedName) Expect(f(managedSeed)).To(BeFalse()) }) It("should return false with a shoot that is not yet scheduled on a seed", func() { shoot.Spec.SeedName = nil expectGetShoot() - f := controllerutils.ManagedSeedFilterFunc(ctx, c, seedName, nil) + f := controllerutils.ManagedSeedFilterFunc(ctx, c, seedName) Expect(f(managedSeed)).To(BeFalse()) }) It("should return true with a shoot that is scheduled on the specified seed", func() { expectGetShoot() - f := controllerutils.ManagedSeedFilterFunc(ctx, c, seedName, nil) + f := controllerutils.ManagedSeedFilterFunc(ctx, c, seedName) Expect(f(managedSeed)).To(BeTrue()) }) It("should return true with a shoot that is scheduled on the specified seed (status different from spec)", func() { shoot.Spec.SeedName = pointer.String("foo") expectGetShoot() - f := controllerutils.ManagedSeedFilterFunc(ctx, c, seedName, nil) + f := controllerutils.ManagedSeedFilterFunc(ctx, c, seedName) Expect(f(managedSeed)).To(BeTrue()) }) It("should return false with a shoot that is scheduled on a different seed", func() { expectGetShoot() - f := controllerutils.ManagedSeedFilterFunc(ctx, c, "foo", nil) - Expect(f(managedSeed)).To(BeFalse()) - }) - - It("should return true with a shoot that is scheduled on a seed selected by the specified label selector", func() { - expectGetShoot() - expectGetSeed() - f := controllerutils.ManagedSeedFilterFunc(ctx, c, "", &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "test-label": "test", - }, - }) - Expect(f(managedSeed)).To(BeTrue()) - }) - - It("should return true with a shoot that is scheduled on a seed selected by the specified label selector (status different from spec)", func() { - shoot.Spec.SeedName = pointer.String("foo") - expectGetShoot() - expectGetSeed() - f := controllerutils.ManagedSeedFilterFunc(ctx, c, "", &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "test-label": "test", - }, - }) - Expect(f(managedSeed)).To(BeTrue()) - }) - - It("should return false with a shoot that is scheduled on a seed not selected by the specified label selector", func() { - expectGetShoot() - expectGetSeed() - f := controllerutils.ManagedSeedFilterFunc(ctx, c, "", &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "foo": "bar", - }, - }) + f := controllerutils.ManagedSeedFilterFunc(ctx, c, "foo") Expect(f(managedSeed)).To(BeFalse()) }) }) Describe("#SeedOfManagedSeedFilterFunc", func() { It("should return false if the specified object is not a seed", func() { - f := controllerutils.SeedOfManagedSeedFilterFunc(ctx, c, seedName, nil) + f := controllerutils.SeedOfManagedSeedFilterFunc(ctx, c, seedName) Expect(f(shoot)).To(BeFalse()) }) It("should return false if the seed is not owned by a managed seed", func() { expectGetManagedSeedNotFound() - f := controllerutils.SeedOfManagedSeedFilterFunc(ctx, c, seedName, nil) + f := controllerutils.SeedOfManagedSeedFilterFunc(ctx, c, seedName) Expect(f(seedOfManagedSeed)).To(BeFalse()) }) It("should return false with a shoot that is not found", func() { expectGetManagedSeed() expectGetShootNotFound() - f := controllerutils.SeedOfManagedSeedFilterFunc(ctx, c, seedName, nil) + f := controllerutils.SeedOfManagedSeedFilterFunc(ctx, c, seedName) Expect(f(seedOfManagedSeed)).To(BeFalse()) }) @@ -245,14 +193,14 @@ var _ = Describe("seedfilter", func() { expectGetManagedSeed() shoot.Spec.SeedName = nil expectGetShoot() - f := controllerutils.SeedOfManagedSeedFilterFunc(ctx, c, seedName, nil) + f := controllerutils.SeedOfManagedSeedFilterFunc(ctx, c, seedName) Expect(f(seedOfManagedSeed)).To(BeFalse()) }) It("should return true with a shoot that is scheduled on the specified seed", func() { expectGetManagedSeed() expectGetShoot() - f := controllerutils.SeedOfManagedSeedFilterFunc(ctx, c, seedName, nil) + f := controllerutils.SeedOfManagedSeedFilterFunc(ctx, c, seedName) Expect(f(seedOfManagedSeed)).To(BeTrue()) }) @@ -260,69 +208,20 @@ var _ = Describe("seedfilter", func() { expectGetManagedSeed() shoot.Spec.SeedName = pointer.String("foo") expectGetShoot() - f := controllerutils.SeedOfManagedSeedFilterFunc(ctx, c, seedName, nil) + f := controllerutils.SeedOfManagedSeedFilterFunc(ctx, c, seedName) Expect(f(seedOfManagedSeed)).To(BeTrue()) }) It("should return false with a shoot that is scheduled on a different seed", func() { expectGetManagedSeed() expectGetShoot() - f := controllerutils.SeedOfManagedSeedFilterFunc(ctx, c, "foo", nil) - Expect(f(seedOfManagedSeed)).To(BeFalse()) - }) - - It("should return true with a shoot that is scheduled on a seed selected by the specified label selector", func() { - expectGetManagedSeed() - expectGetShoot() - expectGetSeed() - f := controllerutils.SeedOfManagedSeedFilterFunc(ctx, c, "", &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "test-label": "test", - }, - }) - Expect(f(seedOfManagedSeed)).To(BeTrue()) - }) - - It("should return true with a shoot that is scheduled on a seed selected by the specified label selector (status different from spec)", func() { - expectGetManagedSeed() - shoot.Spec.SeedName = pointer.String("foo") - expectGetShoot() - expectGetSeed() - f := controllerutils.SeedOfManagedSeedFilterFunc(ctx, c, "", &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "test-label": "test", - }, - }) - Expect(f(seedOfManagedSeed)).To(BeTrue()) - }) - - It("should return false with a shoot that is scheduled on a seed not selected by the specified label selector", func() { - expectGetManagedSeed() - expectGetShoot() - expectGetSeed() - f := controllerutils.SeedOfManagedSeedFilterFunc(ctx, c, "", &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "foo": "bar", - }, - }) + f := controllerutils.SeedOfManagedSeedFilterFunc(ctx, c, "foo") Expect(f(seedOfManagedSeed)).To(BeFalse()) }) }) Describe("BackupEntry", func() { - var ( - backupEntry *gardencorev1beta1.BackupEntry - seedLabelSelector = &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "test-label": "test", - }, - } - otherSeedLabelSelector = &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "test-label": "new-test", - }, - } - ) + var backupEntry *gardencorev1beta1.BackupEntry BeforeEach(func() { backupEntry = &gardencorev1beta1.BackupEntry{ @@ -335,13 +234,13 @@ var _ = Describe("seedfilter", func() { Describe("#BackupEntryFilterFunc", func() { It("should return false if the specified object is not a BackupEntry", func() { - f := controllerutils.BackupEntryFilterFunc(ctx, c, seedName, nil) + f := controllerutils.BackupEntryFilterFunc(seedName) Expect(f(shoot)).To(BeFalse()) }) DescribeTable("filter BackupEntry by seedName", func(specSeedName, statusSeedName *string, filterSeedName string, match gomegatypes.GomegaMatcher) { - f := controllerutils.BackupEntryFilterFunc(ctx, c, filterSeedName, nil) + f := controllerutils.BackupEntryFilterFunc(filterSeedName) backupEntry.Spec.SeedName = specSeedName backupEntry.Status.SeedName = statusSeedName Expect(f(backupEntry)).To(match) @@ -354,20 +253,6 @@ var _ = Describe("seedfilter", func() { Entry("BackupEntry.Spec.SeedName matches and BackupEntry.Status.SeedName is nil", pointer.String(seedName), nil, seedName, BeTrue()), Entry("BackupEntry.Spec.SeedName does not match but BackupEntry.Status.SeedName matches", pointer.String(otherSeed), pointer.String(seedName), seedName, BeTrue()), ) - - DescribeTable("filter BackupEntry by Seed label selector", - func(specSeedName, statusSeedName *string, labelSelector *metav1.LabelSelector, match gomegatypes.GomegaMatcher) { - expectGetSeed() - f := controllerutils.BackupEntryFilterFunc(ctx, c, "", labelSelector) - backupEntry.Spec.SeedName = specSeedName - backupEntry.Status.SeedName = statusSeedName - Expect(f(backupEntry)).To(match) - }, - Entry("BackupEntry.Spec.SeedName does not match and BackupEntry.Status.SeedName is nil", pointer.String(seedName), nil, otherSeedLabelSelector, BeFalse()), - Entry("BackupEntry.Spec.SeedName and BackupEntry.Status.SeedName do not match", pointer.String(seedName), pointer.String(seedName), otherSeedLabelSelector, BeFalse()), - Entry("BackupEntry.Spec.SeedName matches and BackupEntry.Status.SeedName is nil", pointer.String(seedName), nil, seedLabelSelector, BeTrue()), - Entry("BackupEntry.Spec.SeedName does not match but BackupEntry.Status.SeedName matches", pointer.String(otherSeed), pointer.String(seedName), seedLabelSelector, BeTrue()), - ) }) Describe("#BackupEntryIsManagedByThisGardenlet", func() { @@ -383,24 +268,11 @@ var _ = Describe("seedfilter", func() { }, }, } - Expect(controllerutils.BackupEntryIsManagedByThisGardenlet(ctx, c, backupEntry, gc)).To(match) + Expect(controllerutils.BackupEntryIsManagedByThisGardenlet(backupEntry, gc)).To(match) }, Entry("BackupEntry is not managed by this seed", otherSeed, BeFalse()), Entry("BackupEntry is managed by this seed", seedName, BeTrue()), ) - - DescribeTable("check BackupEntry by seed label selector", - func(labelSelector *metav1.LabelSelector, match gomegatypes.GomegaMatcher) { - backupEntry.Spec.SeedName = pointer.String(seedName) - gc := &config.GardenletConfiguration{ - SeedSelector: labelSelector, - } - expectGetSeed() - Expect(controllerutils.BackupEntryIsManagedByThisGardenlet(ctx, c, backupEntry, gc)).To(match) - }, - Entry("BackupEntry is not managed by this seed", otherSeedLabelSelector, BeFalse()), - Entry("BackupEntry is managed by this seed", seedLabelSelector, BeTrue()), - ) }) }) }) diff --git a/pkg/gardenlet/apis/config/types.go b/pkg/gardenlet/apis/config/types.go index 5f1eff2fbc1..bef67defc8e 100644 --- a/pkg/gardenlet/apis/config/types.go +++ b/pkg/gardenlet/apis/config/types.go @@ -54,13 +54,8 @@ type GardenletConfiguration struct { // "github.com/gardener/gardener/pkg/gardenlet/features/features.go". // Default: nil FeatureGates map[string]bool - // SeedConfig contains configuration for the seed cluster. Must not be set if seed selector is set. - // In this case the gardenlet creates the `Seed` object itself based on the provided config. + // SeedConfig contains configuration for the seed cluster. SeedConfig *SeedConfig - // SeedSelector contains an optional list of labels on `Seed` resources that shall be managed by - // this gardenlet instance. In this case the `Seed` object is not managed by the Gardenlet and must - // be created by an operator/administrator. - SeedSelector *metav1.LabelSelector // Logging contains an optional configurations for the logging stack deployed // by the Gardenlet in the seed clusters. Logging *Logging diff --git a/pkg/gardenlet/apis/config/v1alpha1/types.go b/pkg/gardenlet/apis/config/v1alpha1/types.go index 0700f666614..0fc20033219 100644 --- a/pkg/gardenlet/apis/config/v1alpha1/types.go +++ b/pkg/gardenlet/apis/config/v1alpha1/types.go @@ -66,15 +66,9 @@ type GardenletConfiguration struct { // Default: nil // +optional FeatureGates map[string]bool `json:"featureGates,omitempty"` - // SeedConfig contains configuration for the seed cluster. Must not be set if seed selector is set. - // In this case the gardenlet creates the `Seed` object itself based on the provided config. + // SeedConfig contains configuration for the seed cluster. // +optional SeedConfig *SeedConfig `json:"seedConfig,omitempty"` - // SeedSelector contains an optional list of labels on `Seed` resources that shall be managed by - // this gardenlet instance. In this case the `Seed` object is not managed by the Gardenlet and must - // be created by an operator/administrator. - // +optional - SeedSelector *metav1.LabelSelector `json:"seedSelector,omitempty"` // Logging contains an optional configurations for the logging stack deployed // by the Gardenlet in the seed clusters. // +optional diff --git a/pkg/gardenlet/apis/config/v1alpha1/zz_generated.conversion.go b/pkg/gardenlet/apis/config/v1alpha1/zz_generated.conversion.go index e052a51df1f..1e01f1d863e 100644 --- a/pkg/gardenlet/apis/config/v1alpha1/zz_generated.conversion.go +++ b/pkg/gardenlet/apis/config/v1alpha1/zz_generated.conversion.go @@ -710,7 +710,6 @@ func autoConvert_v1alpha1_GardenletConfiguration_To_config_GardenletConfiguratio } else { out.SeedConfig = nil } - out.SeedSelector = (*v1.LabelSelector)(unsafe.Pointer(in.SeedSelector)) if in.Logging != nil { in, out := &in.Logging, &out.Logging *out = new(config.Logging) @@ -782,7 +781,6 @@ func autoConvert_config_GardenletConfiguration_To_v1alpha1_GardenletConfiguratio } else { out.SeedConfig = nil } - out.SeedSelector = (*v1.LabelSelector)(unsafe.Pointer(in.SeedSelector)) if in.Logging != nil { in, out := &in.Logging, &out.Logging *out = new(Logging) diff --git a/pkg/gardenlet/apis/config/v1alpha1/zz_generated.deepcopy.go b/pkg/gardenlet/apis/config/v1alpha1/zz_generated.deepcopy.go index 61959181738..1af200fe8f6 100644 --- a/pkg/gardenlet/apis/config/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/gardenlet/apis/config/v1alpha1/zz_generated.deepcopy.go @@ -358,11 +358,6 @@ func (in *GardenletConfiguration) DeepCopyInto(out *GardenletConfiguration) { *out = new(SeedConfig) (*in).DeepCopyInto(*out) } - if in.SeedSelector != nil { - in, out := &in.SeedSelector, &out.SeedSelector - *out = new(v1.LabelSelector) - (*in).DeepCopyInto(*out) - } if in.Logging != nil { in, out := &in.Logging, &out.Logging *out = new(Logging) diff --git a/pkg/gardenlet/apis/config/validation/validation.go b/pkg/gardenlet/apis/config/validation/validation.go index 6f50bf5820c..39d289408e8 100644 --- a/pkg/gardenlet/apis/config/validation/validation.go +++ b/pkg/gardenlet/apis/config/validation/validation.go @@ -46,8 +46,8 @@ func ValidateGardenletConfiguration(cfg *config.GardenletConfiguration, fldPath } } - if !inTemplate && (cfg.SeedConfig == nil && cfg.SeedSelector == nil) || (cfg.SeedConfig != nil && cfg.SeedSelector != nil) { - allErrs = append(allErrs, field.Invalid(fldPath.Child("seedConfig"), cfg, "either seed config or seed selector is required")) + if !inTemplate && cfg.SeedConfig == nil { + allErrs = append(allErrs, field.Invalid(fldPath.Child("seedConfig"), cfg, "seed config must be set")) } if cfg.SeedConfig != nil { diff --git a/pkg/gardenlet/apis/config/validation/validation_test.go b/pkg/gardenlet/apis/config/validation/validation_test.go index 1a0ba6c8ae9..66ed052dcb4 100644 --- a/pkg/gardenlet/apis/config/validation/validation_test.go +++ b/pkg/gardenlet/apis/config/validation/validation_test.go @@ -242,9 +242,8 @@ var _ = Describe("GardenletConfiguration", func() { }) }) - Context("seed selector/config", func() { - It("should forbid specifying neither a seed selector nor a seed config", func() { - cfg.SeedSelector = nil + Context("seed config", func() { + It("should require a seedConfig", func() { cfg.SeedConfig = nil errorList := ValidateGardenletConfiguration(cfg, nil, false) @@ -254,17 +253,6 @@ var _ = Describe("GardenletConfiguration", func() { "Field": Equal("seedConfig"), })))) }) - - It("should forbid specifying both a seed selector and a seed config", func() { - cfg.SeedSelector = &metav1.LabelSelector{} - - errorList := ValidateGardenletConfiguration(cfg, nil, false) - - Expect(errorList).To(ConsistOf(PointTo(MatchFields(IgnoreExtras, Fields{ - "Type": Equal(field.ErrorTypeInvalid), - "Field": Equal("seedConfig"), - })))) - }) }) Context("seed template", func() { diff --git a/pkg/gardenlet/apis/config/zz_generated.deepcopy.go b/pkg/gardenlet/apis/config/zz_generated.deepcopy.go index c5f8d03efde..fd402a47843 100644 --- a/pkg/gardenlet/apis/config/zz_generated.deepcopy.go +++ b/pkg/gardenlet/apis/config/zz_generated.deepcopy.go @@ -358,11 +358,6 @@ func (in *GardenletConfiguration) DeepCopyInto(out *GardenletConfiguration) { *out = new(SeedConfig) (*in).DeepCopyInto(*out) } - if in.SeedSelector != nil { - in, out := &in.SeedSelector, &out.SeedSelector - *out = new(v1.LabelSelector) - (*in).DeepCopyInto(*out) - } if in.Logging != nil { in, out := &in.Logging, &out.Logging *out = new(Logging) diff --git a/pkg/gardenlet/bootstrap/certificate/certificate_rotation.go b/pkg/gardenlet/bootstrap/certificate/certificate_rotation.go index 396340a0a53..f16cac4113b 100644 --- a/pkg/gardenlet/bootstrap/certificate/certificate_rotation.go +++ b/pkg/gardenlet/bootstrap/certificate/certificate_rotation.go @@ -24,7 +24,6 @@ import ( "time" corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/client" @@ -58,7 +57,6 @@ type Manager struct { gardenClientConnection *config.GardenClientConnection targetClusterName string seedName string - seedSelector *metav1.LabelSelector } // NewCertificateRotation creates a certificate manager that can be used to rotate gardenlet's client certificate for the Garden cluster @@ -73,7 +71,6 @@ func NewCertificateManager(clientMap clientmap.ClientMap, seedClient client.Clie gardenClientConnection: config.GardenClientConnection, seedName: seedName, targetClusterName: gardenletTargetClusterName, - seedSelector: config.SeedSelector, } } @@ -103,14 +100,12 @@ func (cr *Manager) ScheduleCertificateRotation(ctx context.Context, gardenletCan if err != nil { msg := fmt.Sprintf("Failed to rotate the kubeconfig for the Garden API Server. Certificate expires in %s (%s): %v", certificateExpirationTime.UTC().Sub(time.Now().UTC()).Round(time.Second).String(), certificateExpirationTime.Round(time.Second).String(), err) cr.logger.Error(msg) - seeds, err := cr.getTargetedSeeds(ctx) + seed, err := cr.getTargetedSeed(ctx) if err != nil { - cr.logger.Warnf("failed to record event on seeds announcing the failed certificate rotation: %v", err) + cr.logger.Warnf("failed to record event on seed announcing the failed certificate rotation: %v", err) return } - for _, seed := range seeds { - recorder.Event(&seed, corev1.EventTypeWarning, EventGardenletCertificateRotationFailed, msg) - } + recorder.Event(seed, corev1.EventTypeWarning, EventGardenletCertificateRotationFailed, msg) return } @@ -119,6 +114,21 @@ func (cr *Manager) ScheduleCertificateRotation(ctx context.Context, gardenletCan }, time.Second, ctx.Done()) } +// getTargetedSeed returns the Seed that this Gardenlet is reconciling +func (cr *Manager) getTargetedSeed(ctx context.Context) (*gardencorev1beta1.Seed, error) { + gardenClient, err := cr.clientMap.GetClient(ctx, keys.ForGarden()) + if err != nil { + return nil, err + } + + seed := &gardencorev1beta1.Seed{} + if err := gardenClient.Client().Get(ctx, client.ObjectKey{Name: cr.seedName}, seed); err != nil { + return nil, err + } + + return seed, nil +} + // waitForCertificateRotation determines and waits for the certificate rotation deadline. // Reschedules the certificate rotation in case the underlying certificate expiration date has changed in the meanwhile. func waitForCertificateRotation(ctx context.Context, logger logrus.FieldLogger, seedClient client.Client, gardenClientConnection *config.GardenClientConnection, now func() time.Time) (*pkix.Name, []string, []net.IP, *time.Time, error) { @@ -222,34 +232,3 @@ func rotateCertificate(ctx context.Context, logger logrus.FieldLogger, clientMap return nil } - -// getTargetedSeeds returns the Seeds that this Gardenlet is reconciling -func getTargetedSeeds(ctx context.Context, gardenClient client.Client, seedSelector *metav1.LabelSelector, seedName string) ([]gardencorev1beta1.Seed, error) { - if seedSelector != nil { - seedLabelSelector, err := metav1.LabelSelectorAsSelector(seedSelector) - if err != nil { - return nil, err - } - - seeds := &gardencorev1beta1.SeedList{} - err = gardenClient.List(ctx, seeds, client.MatchingLabelsSelector{Selector: seedLabelSelector}) - if err != nil { - return nil, err - } - return seeds.Items, nil - } - - seed := &gardencorev1beta1.Seed{} - if err := gardenClient.Get(ctx, client.ObjectKey{Name: seedName}, seed); err != nil { - return nil, err - } - return []gardencorev1beta1.Seed{*seed}, nil -} - -func (cr *Manager) getTargetedSeeds(ctx context.Context) ([]gardencorev1beta1.Seed, error) { - gardenClient, err := cr.clientMap.GetClient(ctx, keys.ForGarden()) - if err != nil { - return nil, err - } - return getTargetedSeeds(ctx, gardenClient.Client(), cr.seedSelector, cr.seedName) -} diff --git a/pkg/gardenlet/bootstrap/certificate/certificate_rotation_test.go b/pkg/gardenlet/bootstrap/certificate/certificate_rotation_test.go index 3ca80d3a271..78c3d6f703a 100644 --- a/pkg/gardenlet/bootstrap/certificate/certificate_rotation_test.go +++ b/pkg/gardenlet/bootstrap/certificate/certificate_rotation_test.go @@ -345,57 +345,6 @@ users: }) }) - Describe("#getTargetedSeeds", func() { - It("should return a single Seed", func() { - mockSeedClient.EXPECT().Get(ctx, kutil.Key(seedName), gomock.AssignableToTypeOf(&gardencorev1beta1.Seed{})).DoAndReturn(func(_ context.Context, _ client.ObjectKey, seed *gardencorev1beta1.Seed) error { - seed.ObjectMeta = metav1.ObjectMeta{ - Name: seedName, - } - return nil - }) - - seeds, err := getTargetedSeeds(ctx, mockSeedClient, nil, seedName) - Expect(err).ToNot(HaveOccurred()) - Expect(seeds).To(HaveLen(1)) - Expect(seeds[0]).To(Equal(gardencorev1beta1.Seed{ - ObjectMeta: metav1.ObjectMeta{ - Name: seedName, - }, - })) - }) - - It("should return all Seed matched by seedSelector", func() { - items := []gardencorev1beta1.Seed{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "seed-one", - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "seed-two", - }, - }, - } - - seedSelector := &metav1.LabelSelector{MatchLabels: map[string]string{ - "seed-kind": "promiscuous", - }} - - seedLabelSelector, err := metav1.LabelSelectorAsSelector(seedSelector) - Expect(err).To(BeNil()) - mockSeedClient.EXPECT().List(ctx, gomock.AssignableToTypeOf(&gardencorev1beta1.SeedList{}), client.MatchingLabelsSelector{Selector: seedLabelSelector}).DoAndReturn(func(_ context.Context, list *gardencorev1beta1.SeedList, _ ...client.ListOption) error { - *list = gardencorev1beta1.SeedList{Items: items} - return nil - }) - - seeds, err := getTargetedSeeds(ctx, mockSeedClient, seedSelector, seedName) - Expect(err).ToNot(HaveOccurred()) - Expect(seeds).To(HaveLen(2)) - Expect(seeds).To(Equal(items)) - }) - }) - Describe("#waitForCertificateRotation", func() { var ( testKubeconfig string diff --git a/pkg/gardenlet/controller/backupbucket/backup_bucket.go b/pkg/gardenlet/controller/backupbucket/backup_bucket.go index 98189357d44..be59725743b 100644 --- a/pkg/gardenlet/controller/backupbucket/backup_bucket.go +++ b/pkg/gardenlet/controller/backupbucket/backup_bucket.go @@ -82,7 +82,7 @@ func NewBackupBucketController(ctx context.Context, clientMap clientmap.ClientMa } controller.backupBucketInformer.AddEventHandler(cache.FilteringResourceEventHandler{ - FilterFunc: controllerutils.BackupBucketFilterFunc(ctx, controller.gardenClient, confighelper.SeedNameFromSeedConfig(controller.config.SeedConfig), controller.config.SeedSelector), + FilterFunc: controllerutils.BackupBucketFilterFunc(confighelper.SeedNameFromSeedConfig(controller.config.SeedConfig)), Handler: cache.ResourceEventHandlerFuncs{ AddFunc: controller.backupBucketAdd, UpdateFunc: controller.backupBucketUpdate, diff --git a/pkg/gardenlet/controller/backupentry/backup_entry.go b/pkg/gardenlet/controller/backupentry/backup_entry.go index c2aa0f2a93d..e015e9b4d2a 100644 --- a/pkg/gardenlet/controller/backupentry/backup_entry.go +++ b/pkg/gardenlet/controller/backupentry/backup_entry.go @@ -77,7 +77,7 @@ func NewBackupEntryController(ctx context.Context, clientMap clientmap.ClientMap } controller.backupEntryInformer.AddEventHandler(cache.FilteringResourceEventHandler{ - FilterFunc: controllerutils.BackupEntryFilterFunc(ctx, controller.gardenClient, confighelper.SeedNameFromSeedConfig(controller.config.SeedConfig), controller.config.SeedSelector), + FilterFunc: controllerutils.BackupEntryFilterFunc(confighelper.SeedNameFromSeedConfig(controller.config.SeedConfig)), Handler: cache.ResourceEventHandlerFuncs{ AddFunc: controller.backupEntryAdd, UpdateFunc: controller.backupEntryUpdate, diff --git a/pkg/gardenlet/controller/backupentry/backup_entry_reconciler.go b/pkg/gardenlet/controller/backupentry/backup_entry_reconciler.go index 9601fc3a726..49e9f27d337 100644 --- a/pkg/gardenlet/controller/backupentry/backup_entry_reconciler.go +++ b/pkg/gardenlet/controller/backupentry/backup_entry_reconciler.go @@ -85,7 +85,7 @@ func (r *reconciler) Reconcile(ctx context.Context, request reconcile.Request) ( return r.migrateBackupEntry(ctx, gardenClient, be) } - if !controllerutils.BackupEntryIsManagedByThisGardenlet(ctx, gardenClient.Client(), be, r.config) { + if !controllerutils.BackupEntryIsManagedByThisGardenlet(be, r.config) { r.logger.Debugf("Skipping because BackupEntry is not managed by this gardenlet in seed %s", *be.Spec.SeedName) return reconcile.Result{}, nil } diff --git a/pkg/gardenlet/controller/bastion/bastion.go b/pkg/gardenlet/controller/bastion/bastion.go index 33f2317b574..7ea669cfef4 100644 --- a/pkg/gardenlet/controller/bastion/bastion.go +++ b/pkg/gardenlet/controller/bastion/bastion.go @@ -76,7 +76,7 @@ func NewBastionController(ctx context.Context, clientMap clientmap.ClientMap, co } bastionInformer.AddEventHandler(cache.FilteringResourceEventHandler{ - FilterFunc: controllerutils.BastionFilterFunc(ctx, gardenClient.Client(), confighelper.SeedNameFromSeedConfig(config.SeedConfig), config.SeedSelector), + FilterFunc: controllerutils.BastionFilterFunc(confighelper.SeedNameFromSeedConfig(config.SeedConfig)), Handler: cache.ResourceEventHandlerFuncs{ AddFunc: controller.bastionAdd, UpdateFunc: controller.bastionUpdate, diff --git a/pkg/gardenlet/controller/bastion/bastion_reconciler.go b/pkg/gardenlet/controller/bastion/bastion_reconciler.go index d76824554b5..4e4ea27033a 100644 --- a/pkg/gardenlet/controller/bastion/bastion_reconciler.go +++ b/pkg/gardenlet/controller/bastion/bastion_reconciler.go @@ -88,7 +88,7 @@ func (r *reconciler) Reconcile(ctx context.Context, request reconcile.Request) ( return reconcile.Result{}, err } - if !controllerutils.BastionIsManagedByThisGardenlet(ctx, gardenClient.Client(), bastion, r.config) { + if !controllerutils.BastionIsManagedByThisGardenlet(bastion, r.config) { logger.WithField("bastion-seed", *bastion.Spec.SeedName).Debug("Skipping because Bastion is not managed by this gardenlet") return reconcile.Result{}, nil } diff --git a/pkg/gardenlet/controller/controllerinstallation/controllerinstallation.go b/pkg/gardenlet/controller/controllerinstallation/controllerinstallation.go index df32ad56923..61936b734d5 100644 --- a/pkg/gardenlet/controller/controllerinstallation/controllerinstallation.go +++ b/pkg/gardenlet/controller/controllerinstallation/controllerinstallation.go @@ -99,7 +99,7 @@ func NewController(clientMap clientmap.ClientMap, gardenCoreInformerFactory gard } controllerInstallationInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{ - FilterFunc: controllerutils.ControllerInstallationFilterFunc(confighelper.SeedNameFromSeedConfig(config.SeedConfig), seedLister, config.SeedSelector), + FilterFunc: controllerutils.ControllerInstallationFilterFunc(confighelper.SeedNameFromSeedConfig(config.SeedConfig)), Handler: cache.ResourceEventHandlerFuncs{ AddFunc: controller.controllerInstallationAdd, UpdateFunc: controller.controllerInstallationUpdate, @@ -108,7 +108,7 @@ func NewController(clientMap clientmap.ClientMap, gardenCoreInformerFactory gard }) controllerInstallationInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{ - FilterFunc: controllerutils.ControllerInstallationFilterFunc(confighelper.SeedNameFromSeedConfig(config.SeedConfig), seedLister, config.SeedSelector), + FilterFunc: controllerutils.ControllerInstallationFilterFunc(confighelper.SeedNameFromSeedConfig(config.SeedConfig)), Handler: cache.ResourceEventHandlerFuncs{ AddFunc: controller.controllerInstallationCareAdd, }, diff --git a/pkg/gardenlet/controller/factory.go b/pkg/gardenlet/controller/factory.go index df3bd7cd5f1..70712c618b4 100644 --- a/pkg/gardenlet/controller/factory.go +++ b/pkg/gardenlet/controller/factory.go @@ -115,11 +115,9 @@ func (f *GardenletControllerFactory) Run(ctx context.Context) error { return fmt.Errorf("timed out waiting for Garden core caches to sync") } - // Register Seed object if desired - if f.cfg.SeedConfig != nil { - if err := f.registerSeed(ctx, k8sGardenClient); err != nil { - return fmt.Errorf("failed to register the seed: %+v", err) - } + // Register Seed object + if err := f.registerSeed(ctx, k8sGardenClient); err != nil { + return fmt.Errorf("failed to register the seed: %+v", err) } imageVector, err := imagevector.ReadGlobalImageVectorWithEnvOverride(filepath.Join(charts.Path, DefaultImageVector)) diff --git a/pkg/gardenlet/controller/federatedseed/seed_control.go b/pkg/gardenlet/controller/federatedseed/seed_control.go index 7b28de3e2ab..191ab18fc98 100644 --- a/pkg/gardenlet/controller/federatedseed/seed_control.go +++ b/pkg/gardenlet/controller/federatedseed/seed_control.go @@ -138,7 +138,7 @@ func (c *Controller) seedDelete(obj interface{}) { // Run starts the FederatedSeed Controller func (c *Controller) Run(ctx context.Context, workers int) { c.seedInformer.AddEventHandler(cache.FilteringResourceEventHandler{ - FilterFunc: controllerutils.SeedFilterFunc(confighelper.SeedNameFromSeedConfig(c.config.SeedConfig), c.config.SeedSelector), + FilterFunc: controllerutils.SeedFilterFunc(confighelper.SeedNameFromSeedConfig(c.config.SeedConfig)), Handler: cache.ResourceEventHandlerFuncs{ AddFunc: c.seedAdd, UpdateFunc: c.seedUpdate, diff --git a/pkg/gardenlet/controller/managedseed/managedseed.go b/pkg/gardenlet/controller/managedseed/managedseed.go index 2bafdb5aa0d..fb55dde7d89 100644 --- a/pkg/gardenlet/controller/managedseed/managedseed.go +++ b/pkg/gardenlet/controller/managedseed/managedseed.go @@ -110,7 +110,7 @@ func (c *Controller) Run(ctx context.Context, workers int) { var waitGroup sync.WaitGroup c.managedSeedInformer.AddEventHandler(cache.FilteringResourceEventHandler{ - FilterFunc: controllerutils.ManagedSeedFilterFunc(ctx, c.gardenClient.Cache(), confighelper.SeedNameFromSeedConfig(c.config.SeedConfig), c.config.SeedSelector), + FilterFunc: controllerutils.ManagedSeedFilterFunc(ctx, c.gardenClient.Cache(), confighelper.SeedNameFromSeedConfig(c.config.SeedConfig)), Handler: cache.ResourceEventHandlerFuncs{ AddFunc: c.managedSeedAdd, UpdateFunc: c.managedSeedUpdate, @@ -120,7 +120,7 @@ func (c *Controller) Run(ctx context.Context, workers int) { // Add event handler for controlled seeds c.seedInformer.AddEventHandler(cache.FilteringResourceEventHandler{ - FilterFunc: controllerutils.SeedOfManagedSeedFilterFunc(ctx, c.gardenClient.Cache(), confighelper.SeedNameFromSeedConfig(c.config.SeedConfig), c.config.SeedSelector), + FilterFunc: controllerutils.SeedOfManagedSeedFilterFunc(ctx, c.gardenClient.Cache(), confighelper.SeedNameFromSeedConfig(c.config.SeedConfig)), Handler: &kutils.ControlledResourceEventHandler{ ControllerTypes: []kutils.ControllerType{ { diff --git a/pkg/gardenlet/controller/managedseed/managedseed_actuator.go b/pkg/gardenlet/controller/managedseed/managedseed_actuator.go index 77eb4218ab2..8eb4de402d2 100644 --- a/pkg/gardenlet/controller/managedseed/managedseed_actuator.go +++ b/pkg/gardenlet/controller/managedseed/managedseed_actuator.go @@ -633,9 +633,6 @@ func (a *actuator) prepareGardenletChartValues( // Set the seed name gardenletConfig.SeedConfig.SeedTemplate.Name = objectMeta.Name - // Ensure seed selector is not set - gardenletConfig.SeedSelector = nil - // Get gardenlet chart values return a.vp.GetGardenletChartValues( ensureGardenletEnvironment(deployment, shoot.Spec.DNS), diff --git a/pkg/gardenlet/controller/managedseed/managedseed_actuator_test.go b/pkg/gardenlet/controller/managedseed/managedseed_actuator_test.go index 269a43fb9b8..8ea3f592464 100644 --- a/pkg/gardenlet/controller/managedseed/managedseed_actuator_test.go +++ b/pkg/gardenlet/controller/managedseed/managedseed_actuator_test.go @@ -490,7 +490,6 @@ var _ = Describe("Actuator", func() { Kubeconfig: "kubeconfig", }, } - mergedGardenletConfig.SeedSelector = &metav1.LabelSelector{} vh.EXPECT().MergeGardenletDeployment(managedSeed.Spec.Gardenlet.Deployment, shoot).Return(mergedDeployment, nil) vh.EXPECT().MergeGardenletConfiguration(managedSeed.Spec.Gardenlet.Config.Object).Return(mergedGardenletConfig, nil) @@ -552,7 +551,7 @@ var _ = Describe("Actuator", func() { }, Spec: seedTemplate.Spec, })) - Expect(gc.SeedSelector).To(BeNil()) + return gardenletChartValues, nil }, ) diff --git a/pkg/gardenlet/controller/seed/seed.go b/pkg/gardenlet/controller/seed/seed.go index e84f699dcb7..cb1bb103fd8 100644 --- a/pkg/gardenlet/controller/seed/seed.go +++ b/pkg/gardenlet/controller/seed/seed.go @@ -20,9 +20,7 @@ import ( "time" "github.com/prometheus/client_golang/prometheus" - apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/record" "k8s.io/client-go/util/workqueue" @@ -64,9 +62,6 @@ type Controller struct { workerCh chan int numberOfRunningWorkers int - - lock sync.Mutex - leaseMap map[string]bool } // NewSeedController takes a Kubernetes client for the Garden clusters , a struct @@ -106,11 +101,10 @@ func NewSeedController( seedLeaseQueue: workqueue.NewNamedRateLimitingQueue(workqueue.NewItemExponentialFailureRateLimiter(time.Millisecond, 2*time.Second), "seed-lease"), seedExtensionCheckQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "seed-extension-check"), workerCh: make(chan int), - leaseMap: make(map[string]bool), } seedInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{ - FilterFunc: controllerutils.SeedFilterFunc(confighelper.SeedNameFromSeedConfig(config.SeedConfig), config.SeedSelector), + FilterFunc: controllerutils.SeedFilterFunc(confighelper.SeedNameFromSeedConfig(config.SeedConfig)), Handler: cache.ResourceEventHandlerFuncs{ AddFunc: seedController.seedAdd, UpdateFunc: seedController.seedUpdate, @@ -119,14 +113,14 @@ func NewSeedController( }) seedInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{ - FilterFunc: controllerutils.SeedFilterFunc(confighelper.SeedNameFromSeedConfig(config.SeedConfig), config.SeedSelector), + FilterFunc: controllerutils.SeedFilterFunc(confighelper.SeedNameFromSeedConfig(config.SeedConfig)), Handler: cache.ResourceEventHandlerFuncs{ AddFunc: seedController.seedLeaseAdd, }, }) controllerInstallationInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{ - FilterFunc: controllerutils.ControllerInstallationFilterFunc(confighelper.SeedNameFromSeedConfig(config.SeedConfig), seedLister, config.SeedSelector), + FilterFunc: controllerutils.ControllerInstallationFilterFunc(confighelper.SeedNameFromSeedConfig(config.SeedConfig)), Handler: cache.ResourceEventHandlerFuncs{ AddFunc: seedController.controllerInstallationOfSeedAdd, UpdateFunc: seedController.controllerInstallationOfSeedUpdate, @@ -167,9 +161,6 @@ func (c *Controller) Run(ctx context.Context, workers int) { controllerutils.DeprecatedCreateWorker(ctx, c.seedExtensionCheckQueue, "Seed Extension Check", c.reconcileSeedExtensionCheckKey, &waitGroup, c.workerCh) } - // health management - go c.startHealthManagement(ctx) - // Shutdown handling <-ctx.Done() c.seedQueue.ShutDown() @@ -188,71 +179,6 @@ func (c *Controller) Run(ctx context.Context, workers int) { waitGroup.Wait() } -func (c *Controller) startHealthManagement(ctx context.Context) { - var ( - seedName = confighelper.SeedNameFromSeedConfig(c.config.SeedConfig) - seedLabelSelector labels.Selector - expectedHealthReports int - err error - ) - - if seedName != "" { - expectedHealthReports = 1 - } else { - seedLabelSelector, err = metav1.LabelSelectorAsSelector(c.config.SeedSelector) - if err != nil { - panic(err) - } - } - - for { - select { - case <-ctx.Done(): - return - case <-time.After(LeaseResyncGracePeriodSeconds / 2 * time.Second): - - isHealthy := true - - if len(seedName) > 0 { - if _, err := c.k8sGardenCoreInformers.Core().V1beta1().Seeds().Lister().Get(seedName); err != nil { - if apierrors.IsNotFound(err) { - // the Seed configured for the Gardenlet does not exist. - // Do not expect an existing lease - expectedHealthReports = 0 - } else { - logger.Logger.Errorf("error when getting the seed %q for health management: %+v", seedName, err) - isHealthy = false - } - } - } else { - seedList, err := c.k8sGardenCoreInformers.Core().V1beta1().Seeds().Lister().List(seedLabelSelector) - if err != nil { - logger.Logger.Errorf("error while listing seeds for health management: %+v", err) - isHealthy = false - } - expectedHealthReports = len(seedList) - } - - c.lock.Lock() - - if len(c.leaseMap) != expectedHealthReports { - isHealthy = false - } else { - for _, status := range c.leaseMap { - if !status { - isHealthy = false - break - } - } - } - - c.leaseMap = make(map[string]bool) - c.lock.Unlock() - c.healthManager.Set(isHealthy) - } - } -} - // RunningWorkers returns the number of running workers. func (c *Controller) RunningWorkers() int { return c.numberOfRunningWorkers diff --git a/pkg/gardenlet/controller/seed/seed_lease_control.go b/pkg/gardenlet/controller/seed/seed_lease_control.go index 100e998792a..2b779d4ac75 100644 --- a/pkg/gardenlet/controller/seed/seed_lease_control.go +++ b/pkg/gardenlet/controller/seed/seed_lease_control.go @@ -71,9 +71,7 @@ func (c *Controller) reconcileSeedLeaseKey(key string) error { } if err := c.checkSeedConnection(ctx, seed); err != nil { - c.lock.Lock() - c.leaseMap[seed.Name] = false - c.lock.Unlock() + c.healthManager.Set(false) return fmt.Errorf("[SEED LEASE] cannot establish connection with Seed %s: %v", key, err) } @@ -83,9 +81,7 @@ func (c *Controller) reconcileSeedLeaseKey(key string) error { ) if err := c.seedLeaseControl.Sync(seedCopy.Name, *seedOwnerReference); err != nil { - c.lock.Lock() - c.leaseMap[seed.Name] = false - c.lock.Unlock() + c.healthManager.Set(false) return err } @@ -94,9 +90,7 @@ func (c *Controller) reconcileSeedLeaseKey(key string) error { return fmt.Errorf("failed to get garden client: %w", err) } - c.lock.Lock() - c.leaseMap[seed.Name] = true - c.lock.Unlock() + c.healthManager.Set(true) bldr, err := helper.NewConditionBuilder(gardencorev1beta1.SeedGardenletReady) if err != nil { diff --git a/pkg/gardenlet/controller/seed/seed_lease_control_test.go b/pkg/gardenlet/controller/seed/seed_lease_control_test.go index 15c44acf145..4e4bcf47afb 100644 --- a/pkg/gardenlet/controller/seed/seed_lease_control_test.go +++ b/pkg/gardenlet/controller/seed/seed_lease_control_test.go @@ -27,6 +27,7 @@ import ( "github.com/gardener/gardener/pkg/client/kubernetes/clientmap/keys" mock "github.com/gardener/gardener/pkg/client/kubernetes/mock" "github.com/gardener/gardener/pkg/gardenlet/apis/config" + "github.com/gardener/gardener/pkg/healthz" "github.com/gardener/gardener/pkg/logger" mockrest "github.com/gardener/gardener/pkg/mock/client-go/rest" mockio "github.com/gardener/gardener/pkg/mock/go/io" @@ -111,6 +112,9 @@ var _ = Describe("SeedLeaseControlReconcile", func() { err: syncFail, } + healthManager := healthz.NewDefaultHealthz() + healthManager.Start() + clientMap := fakeclientmap.NewClientMap(). AddClient(keys.ForGarden(), k8sGardenClient). AddClient(keys.ForSeed(seed), k8sGardenClient) @@ -120,7 +124,7 @@ var _ = Describe("SeedLeaseControlReconcile", func() { seedLeaseQueue: seedLeaseQueue, config: gardenletConfig, seedLeaseControl: seedLeaseControl, - leaseMap: make(map[string]bool), + healthManager: healthManager, } Expect(indexer.Add(seed)).NotTo(HaveOccurred()) }) @@ -149,7 +153,7 @@ var _ = Describe("SeedLeaseControlReconcile", func() { It("returns error if connection to Seed is unsuccessful", func() { err := controller.reconcileSeedLeaseKey(seedName) Expect(err).To(HaveOccurred()) - Expect(controller.leaseMap).To(HaveKeyWithValue(seedName, false)) + Expect(controller.healthManager.Get()).To(BeFalse()) }) }) @@ -161,7 +165,7 @@ var _ = Describe("SeedLeaseControlReconcile", func() { It("propagates the error when lease fails to update", func() { err := controller.reconcileSeedLeaseKey(seedName) Expect(err).To(HaveOccurred()) - Expect(controller.leaseMap).To(HaveKeyWithValue(seedName, false)) + Expect(controller.healthManager.Get()).To(BeFalse()) }) }) @@ -169,7 +173,7 @@ var _ = Describe("SeedLeaseControlReconcile", func() { It("updates the lease without error", func() { err := controller.reconcileSeedLeaseKey(seedName) Expect(err).NotTo(HaveOccurred()) - Expect(controller.leaseMap).To(HaveKeyWithValue(seedName, true)) + Expect(controller.healthManager.Get()).To(BeTrue()) }) }) @@ -186,7 +190,7 @@ var _ = Describe("SeedLeaseControlReconcile", func() { It("updated seed Condition if already exists", func() { err := controller.reconcileSeedLeaseKey(seedName) Expect(err).NotTo(HaveOccurred()) - Expect(controller.leaseMap).To(HaveKeyWithValue(seedName, true)) + Expect(controller.healthManager.Get()).To(BeTrue()) }) }) }) diff --git a/pkg/gardenlet/controller/shoot/shoot.go b/pkg/gardenlet/controller/shoot/shoot.go index cee8942fe10..8725d0b24a3 100644 --- a/pkg/gardenlet/controller/shoot/shoot.go +++ b/pkg/gardenlet/controller/shoot/shoot.go @@ -111,7 +111,7 @@ func NewShootController(clientMap clientmap.ClientMap, k8sGardenCoreInformers ga } shootInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{ - FilterFunc: controllerutils.ShootFilterFunc(confighelper.SeedNameFromSeedConfig(config.SeedConfig), seedLister, config.SeedSelector), + FilterFunc: controllerutils.ShootFilterFunc(confighelper.SeedNameFromSeedConfig(config.SeedConfig)), Handler: cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { shootController.shootAdd(obj, false) @@ -122,7 +122,7 @@ func NewShootController(clientMap clientmap.ClientMap, k8sGardenCoreInformers ga }) shootInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{ - FilterFunc: controllerutils.ShootFilterFunc(confighelper.SeedNameFromSeedConfig(config.SeedConfig), seedLister, config.SeedSelector), + FilterFunc: controllerutils.ShootFilterFunc(confighelper.SeedNameFromSeedConfig(config.SeedConfig)), Handler: cache.ResourceEventHandlerFuncs{ AddFunc: shootController.shootCareAdd, UpdateFunc: shootController.shootCareUpdate, @@ -130,7 +130,7 @@ func NewShootController(clientMap clientmap.ClientMap, k8sGardenCoreInformers ga }) shootInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{ - FilterFunc: controllerutils.ShootFilterFunc(confighelper.SeedNameFromSeedConfig(config.SeedConfig), seedLister, config.SeedSelector), + FilterFunc: controllerutils.ShootFilterFunc(confighelper.SeedNameFromSeedConfig(config.SeedConfig)), Handler: cache.ResourceEventHandlerFuncs{ AddFunc: shootController.seedRegistrationAdd, UpdateFunc: shootController.seedRegistrationUpdate, @@ -168,7 +168,7 @@ func (c *Controller) Run(ctx context.Context, shootWorkers, shootCareWorkers int } // Update Shoots before starting the workers. - shootFilterFunc := controllerutils.ShootFilterFunc(confighelper.SeedNameFromSeedConfig(c.config.SeedConfig), c.seedLister, c.config.SeedSelector) + shootFilterFunc := controllerutils.ShootFilterFunc(confighelper.SeedNameFromSeedConfig(c.config.SeedConfig)) shoots, err := c.shootLister.List(labels.Everything()) if err != nil { logger.Logger.Errorf("Failed to fetch shoots resources: %v", err.Error()) diff --git a/pkg/gardenlet/controller/shoot/shoot_care_control.go b/pkg/gardenlet/controller/shoot/shoot_care_control.go index d7fc819dd77..b99bbe3c155 100644 --- a/pkg/gardenlet/controller/shoot/shoot_care_control.go +++ b/pkg/gardenlet/controller/shoot/shoot_care_control.go @@ -198,7 +198,7 @@ func (s *careReconciler) Reconcile(ctx context.Context, req reconcile.Request) ( } // if shoot is no longer managed by this gardenlet (e.g., due to migration to another seed) then don't requeue - if !controllerutils.ShootIsManagedByThisGardenlet(shootObj, s.config, s.k8sGardenCoreInformers.Seeds().Lister()) { + if !controllerutils.ShootIsManagedByThisGardenlet(shootObj, s.config) { return reconcile.Result{}, nil } diff --git a/pkg/gardenlet/controller/shoot/shoot_control.go b/pkg/gardenlet/controller/shoot/shoot_control.go index c68cae7ba60..da080bfd38a 100644 --- a/pkg/gardenlet/controller/shoot/shoot_control.go +++ b/pkg/gardenlet/controller/shoot/shoot_control.go @@ -234,7 +234,7 @@ func (c *Controller) reconcileShootRequest(ctx context.Context, req reconcile.Re } // if shoot is no longer managed by this gardenlet (e.g., due to migration to another seed) then don't requeue - if !controllerutils.ShootIsManagedByThisGardenlet(shoot, c.config, c.seedLister) { + if !controllerutils.ShootIsManagedByThisGardenlet(shoot, c.config) { log.Debugf("Skipping because Shoot is not managed by this gardenlet in seed %s", *shoot.Spec.SeedName) return reconcile.Result{}, nil }