diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 9e8f76a7..b35d53b4 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,5 +9,18 @@ updates: directories: - "/" # Location of package manifests - "/hack/runtime-migrator" + groups: + k8s: + patterns: + - "k8s.io*" + update-types: + - "minor" + - "patch" + gardener: + patterns: + - "github.com/gardener/*" + update-types: + - "minor" + - "patch" schedule: interval: "weekly" diff --git a/cmd/main.go b/cmd/main.go index cbe7554f..a1d15634 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -46,6 +46,7 @@ import ( clientgoscheme "k8s.io/client-go/kubernetes/scheme" _ "k8s.io/client-go/plugin/pkg/client/auth" "k8s.io/client-go/rest" + "k8s.io/client-go/util/flowcontrol" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/healthz" @@ -66,11 +67,20 @@ func init() { //+kubebuilder:scaffold:scheme } -const defaultMinimalRotationTimeRatio = 0.6 -const defaultExpirationTime = 24 * time.Hour -const defaultGardenerRequestTimeout = 60 * time.Second -const defaultControlPlaneRequeueDuration = 10 * time.Second -const defaultGardenerRequeueDuration = 15 * time.Second +// Default values for the Runtime controller configuration +const ( + defaultControlPlaneRequeueDuration = 10 * time.Second + defaultGardenerRequestTimeout = 3 * time.Second + defaultGardenerRateLimiterQPS = 5 + defaultGardenerRateLimiterBurst = 5 + defaultMinimalRotationTimeRatio = 0.6 + defaultExpirationTime = 24 * time.Hour + defaultGardenerReconciliationTimeout = 60 * time.Second + defaultGardenerRequeueDuration = 15 * time.Second + defaultShootCreateRequeueDuration = 60 * time.Second + defaultShootDeleteRequeueDuration = 90 * time.Second + defaultShootReconcileRequeueDuration = 30 * time.Second +) func main() { var metricsAddr string @@ -80,7 +90,10 @@ func main() { var gardenerProjectName string var minimalRotationTimeRatio float64 var expirationTime time.Duration - var gardenerRequestTimeout time.Duration + var gardenerCtrlReconciliationTimeout time.Duration + var runtimeCtrlGardenerRequestTimeout time.Duration + var runtimeCtrlGardenerRateLimiterQPS int + var runtimeCtrlGardenerRateLimiterBurst int var converterConfigFilepath string var shootSpecDumpEnabled bool var auditLogMandatory bool @@ -94,7 +107,10 @@ func main() { flag.StringVar(&gardenerProjectName, "gardener-project-name", "gardener-project", "Name of the Gardener project") flag.Float64Var(&minimalRotationTimeRatio, "minimal-rotation-time", defaultMinimalRotationTimeRatio, "The ratio determines what is the minimal time that needs to pass to rotate certificate.") flag.DurationVar(&expirationTime, "kubeconfig-expiration-time", defaultExpirationTime, "Dynamic kubeconfig expiration time") - flag.DurationVar(&gardenerRequestTimeout, "gardener-request-timeout", defaultGardenerRequestTimeout, "Timeout duration for requests to Gardener") + flag.DurationVar(&gardenerCtrlReconciliationTimeout, "gardener-ctrl-reconcilation-timeout", defaultGardenerReconciliationTimeout, "Timeout duration for reconlication for Gardener Cluster Controller") + flag.DurationVar(&runtimeCtrlGardenerRequestTimeout, "gardener-request-timeout", defaultGardenerRequestTimeout, "Timeout duration for Gardener client for Runtime Controller") + flag.IntVar(&runtimeCtrlGardenerRateLimiterQPS, "gardener-ratelimiter-qps", defaultGardenerRateLimiterQPS, "Gardener client rate limiter QPS for Runtime Controller") + flag.IntVar(&runtimeCtrlGardenerRateLimiterBurst, "gardener-ratelimiter-burst", defaultGardenerRateLimiterBurst, "Gardener client rate limiter burst for Runtime Controller") flag.StringVar(&converterConfigFilepath, "converter-config-filepath", "/converter-config/converter_config.json", "A file path to the gardener shoot converter configuration.") flag.BoolVar(&shootSpecDumpEnabled, "shoot-spec-dump-enabled", false, "Feature flag to allow persisting specs of created shoots") flag.BoolVar(&auditLogMandatory, "audit-log-mandatory", true, "Feature flag to enable strict mode for audit log configuration") @@ -137,7 +153,7 @@ func main() { } gardenerNamespace := fmt.Sprintf("garden-%s", gardenerProjectName) - gardenerClient, shootClient, dynamicKubeconfigClient, err := initGardenerClients(gardenerKubeconfigPath, gardenerNamespace) + gardenerClient, shootClient, dynamicKubeconfigClient, err := initGardenerClients(gardenerKubeconfigPath, gardenerNamespace, runtimeCtrlGardenerRequestTimeout, runtimeCtrlGardenerRateLimiterQPS, runtimeCtrlGardenerRateLimiterBurst) if err != nil { setupLog.Error(err, "unable to initialize gardener clients", "controller", "GardenerCluster") @@ -158,7 +174,7 @@ func main() { logger, rotationPeriod, minimalRotationTimeRatio, - gardenerRequestTimeout, + gardenerCtrlReconciliationTimeout, metrics, ).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "GardenerCluster") @@ -188,14 +204,17 @@ func main() { } cfg := fsm.RCCfg{ - GardenerRequeueDuration: defaultGardenerRequeueDuration, - ControlPlaneRequeueDuration: defaultControlPlaneRequeueDuration, - Finalizer: infrastructuremanagerv1.Finalizer, - ShootNamesapace: gardenerNamespace, - Config: config, - AuditLogMandatory: auditLogMandatory, - Metrics: metrics, - AuditLogging: auditLogDataMap, + GardenerRequeueDuration: defaultGardenerRequeueDuration, + RequeueDurationShootCreate: defaultShootCreateRequeueDuration, + RequeueDurationShootDelete: defaultShootDeleteRequeueDuration, + RequeueDurationShootReconcile: defaultShootReconcileRequeueDuration, + ControlPlaneRequeueDuration: defaultControlPlaneRequeueDuration, + Finalizer: infrastructuremanagerv1.Finalizer, + ShootNamesapace: gardenerNamespace, + Config: config, + AuditLogMandatory: auditLogMandatory, + Metrics: metrics, + AuditLogging: auditLogDataMap, } if shootSpecDumpEnabled { cfg.PVCPath = "/testdata/kim" @@ -234,12 +253,15 @@ func main() { } } -func initGardenerClients(kubeconfigPath string, namespace string) (client.Client, gardener_apis.ShootInterface, client.SubResourceClient, error) { +func initGardenerClients(kubeconfigPath string, namespace string, timeout time.Duration, rlQPS, rlBurst int) (client.Client, gardener_apis.ShootInterface, client.SubResourceClient, error) { restConfig, err := gardener.NewRestConfigFromFile(kubeconfigPath) if err != nil { return nil, nil, nil, err } + restConfig.Timeout = timeout + restConfig.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(float32(rlQPS), rlBurst) + gardenerClientSet, err := gardener_apis.NewForConfig(restConfig) if err != nil { return nil, nil, nil, err diff --git a/go.mod b/go.mod index 0b0afde6..493dca05 100644 --- a/go.mod +++ b/go.mod @@ -5,20 +5,20 @@ go 1.23.1 require ( github.com/Masterminds/semver/v3 v3.3.0 github.com/gardener/gardener v1.106.1 - github.com/gardener/gardener-extension-provider-aws v1.57.1 - github.com/gardener/gardener-extension-provider-gcp v1.39.0 + github.com/gardener/gardener-extension-provider-aws v1.58.3 + github.com/gardener/gardener-extension-provider-gcp v1.40.1 github.com/gardener/gardener-extension-provider-openstack v1.42.1 - github.com/gardener/oidc-webhook-authenticator v0.32.0 + github.com/gardener/oidc-webhook-authenticator v0.33.0 github.com/go-logr/logr v1.4.2 - github.com/go-playground/validator/v10 v10.22.1 + github.com/go-playground/validator/v10 v10.23.0 github.com/onsi/ginkgo/v2 v2.20.2 github.com/onsi/gomega v1.34.2 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.20.5 github.com/stretchr/testify v1.9.0 - k8s.io/api v0.31.2 - k8s.io/apimachinery v0.31.2 - k8s.io/client-go v0.31.2 + k8s.io/api v0.31.3 + k8s.io/apimachinery v0.31.3 + k8s.io/client-go v0.31.3 k8s.io/utils v0.0.0-20240921022957-49e7df575cb6 sigs.k8s.io/controller-runtime v0.19.1 sigs.k8s.io/yaml v1.4.0 diff --git a/go.sum b/go.sum index ae4ffa26..bc584fae 100644 --- a/go.sum +++ b/go.sum @@ -24,14 +24,14 @@ github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uq github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gardener/gardener v1.106.1 h1:nbWHqV/rV5Q/7nfuMD5mudWmRnBYZfaJC3O0QaVqwYI= github.com/gardener/gardener v1.106.1/go.mod h1:l5TUgzs/Gv8SbuUFW/hCnfID6oo1/DRrGXx/IbjwQi8= -github.com/gardener/gardener-extension-provider-aws v1.57.1 h1:9CLTxWw1q1TGTlW+8fJEj/ilxkZurcv2KmebLrgH5lU= -github.com/gardener/gardener-extension-provider-aws v1.57.1/go.mod h1:7eonlUnJVODAER50EvdTrvZUVBL+peNOxfYNjyOzOks= -github.com/gardener/gardener-extension-provider-gcp v1.39.0 h1:fLx5tiu6EUa1VJzkqLltnlkDm+l5xLCJuQ13h8o3Uhg= -github.com/gardener/gardener-extension-provider-gcp v1.39.0/go.mod h1:0+YVRmwO0Scvm7M3AZoxq2k30tHxRUgAbQZbmhUs920= +github.com/gardener/gardener-extension-provider-aws v1.58.3 h1:YDv5s5BEVpPQ+x70tHOcwf762/vo/I6OvwjeT3FD3AU= +github.com/gardener/gardener-extension-provider-aws v1.58.3/go.mod h1:EFrr2XNSCCEzC6U8Y/wUxCri3Y8zwgaRvFxEPkMOJww= +github.com/gardener/gardener-extension-provider-gcp v1.40.1 h1:ErTgztMj/6zLSN8sFJXQ2D3ZNyGD1t+GZjAcCBIP+mU= +github.com/gardener/gardener-extension-provider-gcp v1.40.1/go.mod h1:7Ra8FdadX+y2xcSwJ1Y4gLOYoS5dcY28lIbNamafVqA= github.com/gardener/gardener-extension-provider-openstack v1.42.1 h1:Umj1dOFn0bLsNQR3dZup3+20j5UtSSAOm3ms5LkaZt0= github.com/gardener/gardener-extension-provider-openstack v1.42.1/go.mod h1:77m0Wte0mF1HiQxi3ixLqCyHoJKRs9INCAI/9CKF7Xc= -github.com/gardener/oidc-webhook-authenticator v0.32.0 h1:neLYl+t62wkCVtgSIQbbckj+2zHD24kg81d0fADY4xg= -github.com/gardener/oidc-webhook-authenticator v0.32.0/go.mod h1:a5jrgVLDX0jpQYFPRHlpr2mp3ZKFm6LNhrXPKzep1b4= +github.com/gardener/oidc-webhook-authenticator v0.33.0 h1:2qMM9dol/S3Paz1GUxFb6ZXqWEKK/dfy/XFrbjNXZGk= +github.com/gardener/oidc-webhook-authenticator v0.33.0/go.mod h1:a5jrgVLDX0jpQYFPRHlpr2mp3ZKFm6LNhrXPKzep1b4= github.com/go-jose/go-jose/v4 v4.0.3 h1:o8aphO8Hv6RPmH+GfzVuyf7YXSBibp+8YyHdOoDESGo= github.com/go-jose/go-jose/v4 v4.0.3/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= @@ -52,8 +52,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA= -github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-playground/validator/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL8sThn8IHr/sO+o= +github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -189,14 +189,14 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0= -k8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk= +k8s.io/api v0.31.3 h1:umzm5o8lFbdN/hIXbrK9oRpOproJO62CV1zqxXrLgk8= +k8s.io/api v0.31.3/go.mod h1:UJrkIp9pnMOI9K2nlL6vwpxRzzEX5sWgn8kGQe92kCE= k8s.io/apiextensions-apiserver v0.31.1 h1:L+hwULvXx+nvTYX/MKM3kKMZyei+UiSXQWciX/N6E40= k8s.io/apiextensions-apiserver v0.31.1/go.mod h1:tWMPR3sgW+jsl2xm9v7lAyRF1rYEK71i9G5dRtkknoQ= -k8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw= -k8s.io/apimachinery v0.31.2/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/client-go v0.31.2 h1:Y2F4dxU5d3AQj+ybwSMqQnpZH9F30//1ObxOKlTI9yc= -k8s.io/client-go v0.31.2/go.mod h1:NPa74jSVR/+eez2dFsEIHNa+3o09vtNaWwWwb1qSxSs= +k8s.io/apimachinery v0.31.3 h1:6l0WhcYgasZ/wk9ktLq5vLaoXJJr5ts6lkaQzgeYPq4= +k8s.io/apimachinery v0.31.3/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/client-go v0.31.3 h1:CAlZuM+PH2cm+86LOBemaJI/lQ5linJ6UFxKX/SoG+4= +k8s.io/client-go v0.31.3/go.mod h1:2CgjPUTpv3fE5dNygAr2NcM8nhHzXvxB8KL5gYc3kJs= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20240521193020-835d969ad83a h1:zD1uj3Jf+mD4zmA7W+goE5TxDkI7OGJjBNBzq5fJtLA= diff --git a/hack/runtime-migrator/README.md b/hack/runtime-migrator/README.md index 4c71ca1f..f0874ba4 100644 --- a/hack/runtime-migrator/README.md +++ b/hack/runtime-migrator/README.md @@ -20,83 +20,133 @@ go build -o ./bin/runtime-migrator ./cmd ## Usage ```bash -cat input/runtimeIds.json | ./runtime-migrator \ +cat ./runtime-migrator \ -gardener-kubeconfig-path=/Users/myuser/gardener-kubeconfig.yml \ -gardener-project-name=kyma-dev \ -kcp-kubeconfig-path=/Users/myuser/kcp-kubeconfig.yml \ -output-path=/tmp/ \ -dry-run=true \ + -input-file-path=input/runtimeIds.json \ -input-type=json ``` The above **execution example** will: -1. take the stdin input (json with runtimeIds array) +1. take the input from the `input/runtimeIds.json` file (json with runtime identifiers array) 1. proceed only with Runtime CRs creation for clusters listed in the input -1. save output files in the `/tmp/` directory. The output directory contains the following: - - `migration.json` - the output file with the migration results +1. save output files in the `/tmp/` directory. The output directory contains the following: + - `migration-results.json` - the output file with the migration results - `runtimes` - the directory with the Runtime CRs files - `comparison-results` - the directory with the files generated during the comparison process 1. They will not be applied on the KCP cluster (`dry-run` mode) +The input can be also provided in the form of a text file: +```bash +cat ./runtime-migrator \ + -gardener-kubeconfig-path=/Users/myuser/gardener-kubeconfig.yml \ + -gardener-project-name=kyma-stage \ + -kcp-kubeconfig-path=/Users/myuser/kcp-kubeconfig.yml \ + -output-path=/tmp/ \ + -dry-run=true \ + -input-file-path=/Users/myuser/migrator-input/runtimeIds.txt \ + -input-type=txt +``` ### Output example ``` -2024/10/28 13:38:49 INFO Starting runtime-migrator -2024/10/28 13:38:49 gardener-kubeconfig-path: /Users/i326211/Downloads/kubeconfig-garden-kyma-dev.yaml -2024/10/28 13:38:49 kcp-kubeconfig-path: /Users/i326211/dev/config/sap -2024/10/28 13:38:49 gardener-project-name: kyma-dev -2024/10/28 13:38:49 output-path: /tmp/ -2024/10/28 13:38:49 dry-run: true -2024/10/28 13:38:49 input-type: json -2024/10/28 13:38:49 -2024/10/28 13:38:49 INFO Migrating runtimes -2024/10/28 13:38:49 INFO Reading runtimeIds from stdin -2024/10/28 13:38:49 INFO Migrating runtime with ID: 80dfc8d7-6687-41b4-982c-2292afce5ac9 -2024/10/28 13:39:01 WARN Runtime CR can cause unwanted update in Gardener. Please verify the runtime CR. runtimeID=80dfc8d7-6687-41b4-982c-2292afce5ac9 -2024/10/28 13:39:01 INFO Migration completed. Successfully migrated runtimes: 0, Failed migrations: 0, Differences detected: 1 -2024/10/28 13:39:01 INFO Migration results saved in: /tmp/migration-2024-10-28T13:38:49+01:00/migration-results.json +2024/11/21 14:53:24 INFO Starting runtime-migrator +2024/11/21 14:53:24 gardener-kubeconfig-path: /Users/myuser/gardener-kubeconfig.yml +2024/11/21 14:53:24 kcp-kubeconfig-path: /Users/myuser/kcp-kubeconfig.yml +2024/11/21 14:53:24 gardener-project-name: kyma-stage +2024/11/21 14:53:24 output-path: /tmp/ +2024/11/21 14:53:24 dry-run: true +2024/11/21 14:53:24 input-type: txt +2024/11/21 14:53:24 input-file-path: /Users/myuser/migrator-input/runtimeIds.txt +2024/11/21 14:53:24 +2024/11/21 14:53:24 INFO Migrating runtimes +2024/11/21 14:53:24 INFO Reading runtimeIds from input file +2024/11/21 14:53:29 INFO Runtime processed successfully runtimeID=1df09b5b-0347-459d-aa0a-715db8fcaad7 +2024/11/21 14:53:32 INFO Runtime processed successfully runtimeID=ea439a5e-aa59-4e3e-8bfb-9bab1b31371e +2024/11/21 14:53:33 INFO Runtime processed successfully runtimeID=d6eeafee-ffd5-4f23-97dc-a1df197b3b30 +2024/11/21 14:53:37 WARN Runtime CR can cause unwanted update in Gardener runtimeID=99a38a99-e8d7-4b98-a6f2-5a54ed389c4d +2024/11/21 14:53:37 ERROR Failed to find shoot: no shoot with given runtimeID found runtimeID=0a61a3c4-0ea8-4e39-860a-7853f0b6d180 +2024/11/21 14:53:40 ERROR Failed to verify runtime runtimeID=6daf5f59-b0ab-44af-bb8e-7735fd609449 +2024/11/21 14:53:40 INFO Migration completed. Successfully migrated runtimes: 3, Failed migrations: 2, Differences detected: 1 +2024/11/21 14:53:40 INFO Migration results saved in: /tmp/migration-2024-11-21T14:53:24+01:00/migration-results.json ``` -The above example shows that the migration process detected a potential problem with Runtime CR. In such a case, Runtime CR that may cause unwanted updates on Gardener will not be applied to the cluster and will require manual intervention. -The migration results are saved in the `/tmp/migration-2024-10-28T13:38:49+01:00/migration-results.json` file. +The migration results are saved in the `/tmp/migration-2024-11-21T14:53:24+01:00/migration-results.json` file. +The runtime custom resources are saved in the `/tmp/migration-2024-11-21T14:53:24+01:00/runtimes` directory. The `migration-results.json` file contains the following content: ```json [ - { - "runtimeId": "80dfc8d7-6687-41b4-982c-2292afce5ac9", - "shootName": "c6069ce", - "status": "ValidationError", - "errorMessage": "Runtime may cause unwanted update in Gardener. Please verify the runtime CR.", - "runtimeCRFilePath": "/tmp/migration-2024-10-28T13:38:49+01:00/runtimes/80dfc8d7-6687-41b4-982c-2292afce5ac9.yaml", - "comparisonResultDirPath": "/tmp/migration-2024-10-28T13:38:49+01:00/comparison-results/80dfc8d7-6687-41b4-982c-2292afce5ac9" - } + { + "runtimeId": "1df09b5b-0347-459d-aa0a-715db8fcaad7", + "shootName": "c-1228ddd", + "status": "Success", + "runtimeCRFilePath": "/tmp/migration-2024-11-21T14:53:24+01:00/runtimes/1df09b5b-0347-459d-aa0a-715db8fcaad7.yaml" + }, + { + "runtimeId": "ea439a5e-aa59-4e3e-8bfb-9bab1b31371e", + "shootName": "c3a59d5", + "status": "Success", + "runtimeCRFilePath": "/tmp/migration-2024-11-21T14:53:24+01:00/runtimes/ea439a5e-aa59-4e3e-8bfb-9bab1b31371e.yaml" + }, + { + "runtimeId": "d6eeafee-ffd5-4f23-97dc-a1df197b3b30", + "shootName": "c141da7", + "status": "Success", + "runtimeCRFilePath": "/tmp/migration-2024-11-21T14:53:24+01:00/runtimes/d6eeafee-ffd5-4f23-97dc-a1df197b3b30.yaml" + }, + { + "runtimeId": "99a38a99-e8d7-4b98-a6f2-5a54ed389c4d", + "shootName": "c-71da0f2", + "status": "ValidationDetectedUnwantedUpdate", + "errorMessage": "Runtime may cause unwanted update in Gardener", + "runtimeCRFilePath": "/tmp/migration-2024-11-21T14:53:24+01:00/runtimes/99a38a99-e8d7-4b98-a6f2-5a54ed389c4d.yaml", + "comparisonResultDirPath": "/tmp/migration-2024-11-21T14:53:24+01:00/comparison-results/99a38a99-e8d7-4b98-a6f2-5a54ed389c4d" + }, + { + "runtimeId": "0a61a3c4-0ea8-4e39-860a-7853f0b6d180", + "shootName": "", + "status": "Error", + "errorMessage": "Failed to find shoot: no shoot with given runtimeID found" + }, + { + "runtimeId": "6daf5f59-b0ab-44af-bb8e-7735fd609449", + "shootName": "c-1f810d0", + "status": "ValidationError", + "errorMessage": "Failed to verify runtime: audit logs configuration not found: missing region: 'australiaeast' for providerType: 'azure'", + "runtimeCRFilePath": "/tmp/migration-2024-11-21T14:53:24+01:00/runtimes/6daf5f59-b0ab-44af-bb8e-7735fd609449.yaml" + } ] -``` -The runtime custom resource is saved in the `/tmp/migration-2024-10-28T13:38:49+01:00/runtimes/80dfc8d7-6687-41b4-982c-2292afce5ac9.yaml` file. -The `comparison-results` directory contains the following content: -``` -drwxr-xr-x@ 5 i326211 wheel 160 28 paź 13:39 . -drwxr-xr-x@ 3 i326211 wheel 96 28 paź 13:39 .. --rw-r--r--@ 1 i326211 wheel 1189 28 paź 13:39 c6069ce.diff --rw-r--r--@ 1 i326211 wheel 3492 28 paź 13:39 converted-shoot.yaml --rw-r--r--@ 1 i326211 wheel 24190 28 paź 13:39 original-shoot.yaml ``` +The following problems were detected in the above example: +- The runtime with the `0a61a3c4-0ea8-4e39-860a-7853f0b6d180` identifier was not found ; the identifier may be incorrect, or the corresponding shoot was deleted for some reason. +- The validation process for the runtime with the `6daf5f59-b0ab-44af-bb8e-7735fd609449` identifier failed. +- The runtime with the `99a38a99-e8d7-4b98-a6f2-5a54ed389c4d` identifier may cause an unwanted update in the Gardener. The comparison results are saved in the `/tmp/migration-2024-11-21T14:53:24+01:00/comparison-results/99a38a99-e8d7-4b98-a6f2-5a54ed389c4d` directory. + + +The `/tmp/migration-2024-11-21T14:53:24+01:00/comparison-results/99a38a99-e8d7-4b98-a6f2-5a54ed389c4d"` directory contains the following files: +- `c-71da0f2.diff` +- `converted-shoot.yaml` +- `original-shoot.yaml` -The `c6069ce.diff` file contains the differences between the original shoot and the shoot that will be created based on the new Runtime CR. The `converted-shoot.yaml` file contains the shoot that will be created based on the new Runtime CR. The `original-shoot.yaml` file contains the shoot fetched from the Gardener. +The `c-71da0f2.diff` file contains the differences between the original shoot and the shoot that will be created based on the new Runtime CR. The `converted-shoot.yaml` file contains the shoot that will be created based on the new Runtime CR. The `original-shoot.yaml` file contains the shoot fetched from the Gardener. ## Configurable Parameters This table lists the configurable parameters, their descriptions, and default values: -| Parameter | Description | Default value | -|-----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------| -| **kcp-kubeconfig-path** | Path to the Kubeconfig file of KCP cluster. | `/path/to/kcp/kubeconfig` | -| **gardener-kubeconfig-path** | Path to the Kubeconfig file of Gardener cluster. | `/path/to/gardener/kubeconfig` | -| **gardener-project-name** | Name of the Gardener project. | `gardener-project-name` | -| **output-path** | Path where generated yamls will be saved. Directory has to exist. | `/tmp/` | -| **dry-run** | Dry-run flag. Has to be set to **false**, otherwise migrator will not apply the CRs on the KCP cluster. | `true` | -| **input-type** | Type of input to be used. Possible values: **all** (will migrate all Gardener shoots), and **json** (will migrate only clusters whose runtimeIds were passed as an input, [see the example](input/runtimeids_sample.json)). | `json` | +| Parameter | Description | Default value | +|-----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------| +| **kcp-kubeconfig-path** | Path to the Kubeconfig file of KCP cluster. | `/path/to/kcp/kubeconfig` | +| **gardener-kubeconfig-path** | Path to the Kubeconfig file of Gardener cluster. | `/path/to/gardener/kubeconfig` | +| **gardener-project-name** | Name of the Gardener project. | `gardener-project-name` | +| **output-path** | Path where generated report, and yamls will be saved. Directory has to exist. | `/tmp/` | +| **dry-run** | Dry-run flag. Has to be set to **false**, otherwise migrator will not apply the CRs on the KCP cluster. | `true` | +| **input-type** | Type of input to be used. Possible values: **txt** (will expect text file with one runtime identifier per line, [see the example](input/runtimeids_sample.txt)), and **json** (will expect `json` array with runtime identifiers, [see the example](input/runtimeids_sample.json)). | `json` | +| **input-file-path** | Path to the file containing Runtimes to be migrated. | `/path/to/input/file` | diff --git a/hack/runtime-migrator/cmd/main.go b/hack/runtime-migrator/cmd/main.go index 34e15cd8..eb00d060 100644 --- a/hack/runtime-migrator/cmd/main.go +++ b/hack/runtime-migrator/cmd/main.go @@ -29,7 +29,7 @@ import ( ) const ( - timeoutK8sOperation = 5 * time.Second + timeoutK8sOperation = 10 * time.Second expirationTime = 60 * time.Minute runtimeIDAnnotation = "kcp.provisioner.kyma-project.io/runtime-id" ) diff --git a/hack/runtime-migrator/cmd/migration.go b/hack/runtime-migrator/cmd/migration.go index 2c5b4ef2..263d38ef 100644 --- a/hack/runtime-migrator/cmd/migration.go +++ b/hack/runtime-migrator/cmd/migration.go @@ -70,12 +70,12 @@ func (m Migration) Do(ctx context.Context, runtimeIDs []string) error { reportValidationError := func(runtimeID, shootName string, msg string, err error) { errorMsg := fmt.Sprintf("%s: %v", msg, err) results.ValidationErrorOccurred(runtimeID, shootName, errorMsg) - slog.Warn(msg, "runtimeID", runtimeID) + slog.Error(msg, "runtimeID", runtimeID) } reportUnwantedUpdateDetected := func(runtimeID, shootName string, msg string) { results.ValidationDetectedUnwantedUpdate(runtimeID, shootName) - slog.Info(msg, "runtimeID", runtimeID) + slog.Warn(msg, "runtimeID", runtimeID) } reportSuccess := func(runtimeID, shootName string, msg string) { @@ -119,7 +119,7 @@ func (m Migration) Do(ctx context.Context, runtimeIDs []string) error { return } - reportUnwantedUpdateDetected(runtimeID, shoot.Name, "Runtime CR can cause unwanted update in Gardener. Please verify the runtime CR.") + reportUnwantedUpdateDetected(runtimeID, shoot.Name, "Runtime CR can cause unwanted update in Gardener") return } diff --git a/hack/runtime-migrator/go.mod b/hack/runtime-migrator/go.mod index e2c22f10..6a695807 100644 --- a/hack/runtime-migrator/go.mod +++ b/hack/runtime-migrator/go.mod @@ -3,15 +3,15 @@ module github.com/kyma-project/infrastructure-manager/hack/runtime-migrator-app go 1.23.1 require ( - github.com/gardener/gardener v1.106.1 - github.com/go-playground/validator/v10 v10.22.1 + github.com/gardener/gardener v1.108.0 + github.com/go-playground/validator/v10 v10.23.0 github.com/kyma-project/infrastructure-manager v0.0.0-20241023155010-55a6abeb1690 github.com/kyma-project/infrastructure-manager/hack/shoot-comparator v0.0.0-20241023155010-55a6abeb1690 github.com/pkg/errors v0.9.1 k8s.io/api v0.31.3 k8s.io/apimachinery v0.31.3 - k8s.io/client-go v0.31.2 - k8s.io/utils v0.0.0-20240921022957-49e7df575cb6 + k8s.io/client-go v0.31.3 + k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 sigs.k8s.io/controller-runtime v0.19.1 sigs.k8s.io/yaml v1.4.0 ) @@ -23,9 +23,9 @@ require ( github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect - github.com/gardener/gardener-extension-provider-aws v1.57.1 // indirect - github.com/gardener/gardener-extension-provider-gcp v1.39.0 // indirect - github.com/gardener/gardener-extension-provider-openstack v1.42.1 // indirect + github.com/gardener/gardener-extension-provider-aws v1.58.3 // indirect + github.com/gardener/gardener-extension-provider-gcp v1.40.1 // indirect + github.com/gardener/gardener-extension-provider-openstack v1.43.0 // indirect github.com/gardener/gardener-extension-shoot-dns-service v1.53.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/zapr v1.3.0 // indirect @@ -50,25 +50,25 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/onsi/gomega v1.34.2 // indirect + github.com/onsi/gomega v1.35.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/x448/float16 v0.8.4 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/crypto v0.28.0 // indirect - golang.org/x/net v0.30.0 // indirect + golang.org/x/crypto v0.29.0 // indirect + golang.org/x/net v0.31.0 // indirect golang.org/x/oauth2 v0.23.0 // indirect - golang.org/x/sys v0.26.0 // indirect - golang.org/x/term v0.25.0 // indirect - golang.org/x/text v0.19.0 // indirect - golang.org/x/time v0.7.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/term v0.26.0 // indirect + golang.org/x/text v0.20.0 // indirect + golang.org/x/time v0.8.0 // indirect google.golang.org/protobuf v1.35.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.31.1 // indirect + k8s.io/apiextensions-apiserver v0.31.2 // indirect k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20240521193020-835d969ad83a // indirect + k8s.io/kube-openapi v0.0.0-20240808142205-8e686545bdb8 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect ) diff --git a/hack/runtime-migrator/go.sum b/hack/runtime-migrator/go.sum index 55a2e686..0e42ced1 100644 --- a/hack/runtime-migrator/go.sum +++ b/hack/runtime-migrator/go.sum @@ -1,7 +1,22 @@ +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= +github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= +github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cyphar/filepath-securejoin v0.3.1 h1:1V7cHiaW+C+39wEfpH6XlLBQo3j/PciWFrgfCLS8XrE= +github.com/cyphar/filepath-securejoin v0.3.1/go.mod h1:F7i41x/9cBF7lzCrVsYs9fuzwRZm4NQsGTBdpp6mETc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -10,24 +25,36 @@ github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtz github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +github.com/fluent/fluent-operator/v2 v2.9.0 h1:VFGgRPOI+yxnOrTIAL6sgFCtc+quDda12iyVL1lRQag= +github.com/fluent/fluent-operator/v2 v2.9.0/go.mod h1:Hthhi/3oO26udvro6t5foUx20PZAMn7WGUhSnEWUV9U= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= -github.com/gardener/gardener v1.106.1 h1:nbWHqV/rV5Q/7nfuMD5mudWmRnBYZfaJC3O0QaVqwYI= -github.com/gardener/gardener v1.106.1/go.mod h1:l5TUgzs/Gv8SbuUFW/hCnfID6oo1/DRrGXx/IbjwQi8= -github.com/gardener/gardener-extension-provider-aws v1.57.1 h1:9CLTxWw1q1TGTlW+8fJEj/ilxkZurcv2KmebLrgH5lU= -github.com/gardener/gardener-extension-provider-aws v1.57.1/go.mod h1:7eonlUnJVODAER50EvdTrvZUVBL+peNOxfYNjyOzOks= -github.com/gardener/gardener-extension-provider-gcp v1.39.0 h1:fLx5tiu6EUa1VJzkqLltnlkDm+l5xLCJuQ13h8o3Uhg= -github.com/gardener/gardener-extension-provider-gcp v1.39.0/go.mod h1:0+YVRmwO0Scvm7M3AZoxq2k30tHxRUgAbQZbmhUs920= -github.com/gardener/gardener-extension-provider-openstack v1.42.1 h1:Umj1dOFn0bLsNQR3dZup3+20j5UtSSAOm3ms5LkaZt0= -github.com/gardener/gardener-extension-provider-openstack v1.42.1/go.mod h1:77m0Wte0mF1HiQxi3ixLqCyHoJKRs9INCAI/9CKF7Xc= +github.com/gardener/cert-management v0.16.0 h1:OlE8nnPgqUii5jBknwASy5EtQlJ3Udy2f7VKIk35A4Q= +github.com/gardener/cert-management v0.16.0/go.mod h1:09sH/cxbK3o4xdwCjM7HE9gGX2wq2lLhhVIqiMpmZy4= +github.com/gardener/etcd-druid v0.24.1 h1:BfFQXOevuJ5oOvM3rkQSJ5XITMJzY/a2j54e7XcBIos= +github.com/gardener/etcd-druid v0.24.1/go.mod h1:6C0eyfdlw6CowLm/l4ZiKwrvkc+5NHrnc/rY2wCUwys= +github.com/gardener/gardener v1.108.0 h1:XJNLWRucboac4LYGqLpzIt8XaLxymFBsz7nHxfVF1gw= +github.com/gardener/gardener v1.108.0/go.mod h1:dmgxecs+i3vWlitYftNuCGVRu0ZWYTlKLBFE6iV+dBk= +github.com/gardener/gardener-extension-provider-aws v1.58.3 h1:YDv5s5BEVpPQ+x70tHOcwf762/vo/I6OvwjeT3FD3AU= +github.com/gardener/gardener-extension-provider-aws v1.58.3/go.mod h1:EFrr2XNSCCEzC6U8Y/wUxCri3Y8zwgaRvFxEPkMOJww= +github.com/gardener/gardener-extension-provider-gcp v1.40.1 h1:ErTgztMj/6zLSN8sFJXQ2D3ZNyGD1t+GZjAcCBIP+mU= +github.com/gardener/gardener-extension-provider-gcp v1.40.1/go.mod h1:7Ra8FdadX+y2xcSwJ1Y4gLOYoS5dcY28lIbNamafVqA= +github.com/gardener/gardener-extension-provider-openstack v1.43.0 h1:7/kLqL/Gkg3lavr9bgTbeJGeLz+aXuQwnZIcFZzR7ps= +github.com/gardener/gardener-extension-provider-openstack v1.43.0/go.mod h1:RjJEGmZhFv9Ps4d7BuDhl63SwPCDX4cFKfs/qAF1daA= github.com/gardener/gardener-extension-shoot-dns-service v1.53.0 h1:WXSjw6y2bLCxScwu0LnH4+1Zf2VKNCwlbPKAjECCeBg= github.com/gardener/gardener-extension-shoot-dns-service v1.53.0/go.mod h1:HG9iWR/XszjmH0mmTHIKmX2Egwo8+giSCF8pjqlIPfM= +github.com/gardener/hvpa-controller/api v0.17.0 h1:1mNeP+xsnjPH6GhewugU5srslXiTCJgYIFCMuRXwI7w= +github.com/gardener/hvpa-controller/api v0.17.0/go.mod h1:eKrL7j6/YX8PaoP80xxi3+UFmQgHVf/QCPsGwNnmDeE= +github.com/gardener/machine-controller-manager v0.54.0 h1:V7EOODiaBO9VesskdCgxMvo5vgMAmtmUTdb9Y9Nwp50= +github.com/gardener/machine-controller-manager v0.54.0/go.mod h1:RPpnU8gmTrhDAd79+iKqKlbANiXCRkXoJW+z+5zSTME= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= +github.com/go-openapi/errors v0.20.4 h1:unTcVm6PispJsMECE3zWgvG4xTiKda1LIR5rCRWLG6M= +github.com/go-openapi/errors v0.20.4/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= @@ -40,10 +67,12 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA= -github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-playground/validator/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL8sThn8IHr/sO+o= +github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= @@ -56,15 +85,19 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= -github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo= +github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= +github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -73,14 +106,24 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0 h1:nHHjmvjitIiyPlUHk/ofpgvBcNcawJLtf4PYHORLjAA= +github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0/go.mod h1:YBCo4DoEeDndqvAn6eeu0vWM7QdXmHEeI9cFWplmBys= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8= +github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -88,17 +131,33 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4= -github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag= -github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= -github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM= +github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= +github.com/onsi/gomega v1.35.0 h1:xuM1M/UvMp9BCdS4hojhS9/4jEuVqS9Er3bqupeaoPM= +github.com/onsi/gomega v1.35.0/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.78.1 h1:Fm9Z+FabnB+6EoGq15j+pyLmaK6hYrYOpBlTzOLTQ+E= +github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.78.1/go.mod h1:SvsRXw4m1F2vk7HquU5h475bFpke27mIUswfyw9u3ug= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc= +github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= +github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= +github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= +github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -107,12 +166,18 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= -go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= +go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= +go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= @@ -120,18 +185,18 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= -golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= +golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= +golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= +golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= +golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= -golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -140,26 +205,31 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= -golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= +golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= -golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= -golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= +golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= -golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= +golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= +golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= +gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= +google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 h1:BulPr26Jqjnd4eYDVe+YvyR7Yc2vJGkO5/0UxD0/jZU= +google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1:hjSy6tcFQZ171igDaN5QHOw2n6vx40juYbC/x67CEhc= +google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I= google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -174,20 +244,36 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +helm.sh/helm/v3 v3.16.2 h1:Y9v7ry+ubQmi+cb5zw1Llx8OKHU9Hk9NQ/+P+LGBe2o= +helm.sh/helm/v3 v3.16.2/go.mod h1:SyTXgKBjNqi2NPsHCW5dDAsHqvGIu0kdNYNH9gQaw70= +istio.io/api v1.23.3 h1:+CP0AHz8/+WJ7ZKJLbilHEiqBCi5KLe1Yil9bJI39ow= +istio.io/api v1.23.3/go.mod h1:QPSTGXuIQdnZFEm3myf9NZ5uBMwCdJWUvfj9ZZ+2oBM= +istio.io/client-go v1.23.2 h1:BIt6A+KaUOFin3SzXiDq2Fr/TMBev1+c836R0BfUfhU= +istio.io/client-go v1.23.2/go.mod h1:E08wpMtUulJk2tlWOCUVakjy1bKFxUNm22tM1R1QY0Y= k8s.io/api v0.31.3 h1:umzm5o8lFbdN/hIXbrK9oRpOproJO62CV1zqxXrLgk8= k8s.io/api v0.31.3/go.mod h1:UJrkIp9pnMOI9K2nlL6vwpxRzzEX5sWgn8kGQe92kCE= -k8s.io/apiextensions-apiserver v0.31.1 h1:L+hwULvXx+nvTYX/MKM3kKMZyei+UiSXQWciX/N6E40= -k8s.io/apiextensions-apiserver v0.31.1/go.mod h1:tWMPR3sgW+jsl2xm9v7lAyRF1rYEK71i9G5dRtkknoQ= +k8s.io/apiextensions-apiserver v0.31.2 h1:W8EwUb8+WXBLu56ser5IudT2cOho0gAKeTOnywBLxd0= +k8s.io/apiextensions-apiserver v0.31.2/go.mod h1:i+Geh+nGCJEGiCGR3MlBDkS7koHIIKWVfWeRFiOsUcM= k8s.io/apimachinery v0.31.3 h1:6l0WhcYgasZ/wk9ktLq5vLaoXJJr5ts6lkaQzgeYPq4= k8s.io/apimachinery v0.31.3/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/client-go v0.31.2 h1:Y2F4dxU5d3AQj+ybwSMqQnpZH9F30//1ObxOKlTI9yc= -k8s.io/client-go v0.31.2/go.mod h1:NPa74jSVR/+eez2dFsEIHNa+3o09vtNaWwWwb1qSxSs= +k8s.io/autoscaler/vertical-pod-autoscaler v1.2.1 h1:t5t0Rsn4b7iQfiVlGdWSEnEx8pjrSM96Sn4Dvo1QH/Q= +k8s.io/autoscaler/vertical-pod-autoscaler v1.2.1/go.mod h1:9ywHbt0kTrLyeNGgTNm7WEns34PmBMEr+9bDKTxW6wQ= +k8s.io/client-go v0.31.3 h1:CAlZuM+PH2cm+86LOBemaJI/lQ5linJ6UFxKX/SoG+4= +k8s.io/client-go v0.31.3/go.mod h1:2CgjPUTpv3fE5dNygAr2NcM8nhHzXvxB8KL5gYc3kJs= +k8s.io/component-base v0.31.2 h1:Z1J1LIaC0AV+nzcPRFqfK09af6bZ4D1nAOpWsy9owlA= +k8s.io/component-base v0.31.2/go.mod h1:9PeyyFN/drHjtJZMCTkSpQJS3U9OXORnHQqMLDz0sUQ= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20240521193020-835d969ad83a h1:zD1uj3Jf+mD4zmA7W+goE5TxDkI7OGJjBNBzq5fJtLA= -k8s.io/kube-openapi v0.0.0-20240521193020-835d969ad83a/go.mod h1:UxDHUPsUwTOOxSU+oXURfFBcAS6JwiRXTYqYwfuGowc= -k8s.io/utils v0.0.0-20240921022957-49e7df575cb6 h1:MDF6h2H/h4tbzmtIKTuctcwZmY0tY9mD9fNT47QO6HI= -k8s.io/utils v0.0.0-20240921022957-49e7df575cb6/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/kube-aggregator v0.31.2 h1:Uw1zUP2D/4wiSjKWVVzSOcCGLuW/+IdRwjjC0FJooYU= +k8s.io/kube-aggregator v0.31.2/go.mod h1:41/VIXH+/Qcg9ERNAY6bRF/WQR6xL1wFgYagdHac1X4= +k8s.io/kube-openapi v0.0.0-20240808142205-8e686545bdb8 h1:1Wof1cGQgA5pqgo8MxKPtf+qN6Sh/0JzznmeGPm1HnE= +k8s.io/kube-openapi v0.0.0-20240808142205-8e686545bdb8/go.mod h1:Os6V6dZwLNii3vxFpxcNaTmH8LJJBkOTg1N0tOA0fvA= +k8s.io/kubelet v0.31.2 h1:6Hytyw4LqWqhgzoi7sPfpDGClu2UfxmPmaiXPC4FRgI= +k8s.io/kubelet v0.31.2/go.mod h1:0E4++3cMWi2cJxOwuaQP3eMBa7PSOvAFgkTPlVc/2FA= +k8s.io/metrics v0.31.2 h1:sQhujR9m3HN/Nu/0fTfTscjnswQl0qkQAodEdGBS0N4= +k8s.io/metrics v0.31.2/go.mod h1:QqqyReApEWO1UEgXOSXiHCQod6yTxYctbAAQBWZkboU= +k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 h1:jGnCPejIetjiy2gqaJ5V0NLwTpF4wbQ6cZIItJCSHno= +k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/controller-runtime v0.19.1 h1:Son+Q40+Be3QWb+niBXAg2vFiYWolDjjRfO8hn/cxOk= sigs.k8s.io/controller-runtime v0.19.1/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= diff --git a/hack/runtime-migrator/input/runtimeids_sample.txt b/hack/runtime-migrator/input/runtimeids_sample.txt new file mode 100644 index 00000000..fa80cc87 --- /dev/null +++ b/hack/runtime-migrator/input/runtimeids_sample.txt @@ -0,0 +1,2 @@ +7c6b4bd3-09d3-462f-b27c-992727b62eec +another-id" \ No newline at end of file diff --git a/hack/runtime-migrator/internal/config/config.go b/hack/runtime-migrator/internal/config/config.go index e2a8da06..451968a9 100644 --- a/hack/runtime-migrator/internal/config/config.go +++ b/hack/runtime-migrator/internal/config/config.go @@ -33,6 +33,7 @@ func printConfig(cfg Config) { log.Println("output-path:", cfg.OutputPath) log.Println("dry-run:", cfg.IsDryRun) log.Println("input-type:", cfg.InputType) + log.Println("input-file-path:", cfg.InputFilePath) log.Println("") } @@ -44,7 +45,7 @@ func NewConfig() Config { flag.StringVar(&result.GardenerProjectName, "gardener-project-name", "gardener-project-name", "Name of the Gardener project.") flag.StringVar(&result.OutputPath, "output-path", "/tmp/", "Path where generated yamls will be saved. Directory has to exist.") flag.BoolVar(&result.IsDryRun, "dry-run", true, "Dry-run flag. Has to be set to 'false' otherwise it will not apply the Custom Resources on the KCP cluster.") - flag.StringVar(&result.InputType, "input-type", InputTypeJSON, "Type of input to be used. Possible values: **all** (will migrate all gardener shoots), and **json** (will migrate only cluster whose runtimeIds were passed as an input, see the example hack/runtime-migrator/input/runtimeids_sample.json).") + flag.StringVar(&result.InputType, "input-type", InputTypeJSON, "Type of input to be used. Possible values: **txt** (see the example hack/runtime-migrator/input/runtimeids_sample.txt), and **json** (see the example hack/runtime-migrator/input/runtimeids_sample.json).") flag.StringVar(&result.InputFilePath, "input-file-path", "/path/to/input/file", "Path to the input file containing RuntimeCRs to be migrated.") flag.Parse() diff --git a/internal/controller/kubeconfig/gardener_cluster_controller.go b/internal/controller/kubeconfig/gardener_cluster_controller.go index 75554b43..c3bf14d8 100644 --- a/internal/controller/kubeconfig/gardener_cluster_controller.go +++ b/internal/controller/kubeconfig/gardener_cluster_controller.go @@ -34,6 +34,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" + pkgctrl "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/predicate" ) @@ -43,6 +44,7 @@ const ( clusterCRNameLabel = "operator.kyma-project.io/cluster-name" rotationPeriodRatio = 0.95 + numberOfWorkers = 25 ) // GardenerClusterController reconciles a GardenerCluster object @@ -436,5 +438,6 @@ func (controller *GardenerClusterController) SetupWithManager(mgr ctrl.Manager) predicate.AnnotationChangedPredicate{}, predicate.GenerationChangedPredicate{}), )). + WithOptions(pkgctrl.Options{MaxConcurrentReconciles: numberOfWorkers}). Complete(controller) } diff --git a/internal/controller/runtime/fsm/runtime_fsm.go b/internal/controller/runtime/fsm/runtime_fsm.go index 0a5391d1..5d79d549 100644 --- a/internal/controller/runtime/fsm/runtime_fsm.go +++ b/internal/controller/runtime/fsm/runtime_fsm.go @@ -26,14 +26,17 @@ type writerGetter = func(filePath string) (io.Writer, error) // runtime reconciler specific configuration type RCCfg struct { - GardenerRequeueDuration time.Duration - ControlPlaneRequeueDuration time.Duration - Finalizer string - PVCPath string - ShootNamesapace string - AuditLogMandatory bool - Metrics metrics.Metrics - AuditLogging auditlogs.Configuration + GardenerRequeueDuration time.Duration + RequeueDurationShootCreate time.Duration + RequeueDurationShootDelete time.Duration + RequeueDurationShootReconcile time.Duration + ControlPlaneRequeueDuration time.Duration + Finalizer string + PVCPath string + ShootNamesapace string + AuditLogMandatory bool + Metrics metrics.Metrics + AuditLogging auditlogs.Configuration config.Config } diff --git a/internal/controller/runtime/fsm/runtime_fsm_apply_clusterrolebindings.go b/internal/controller/runtime/fsm/runtime_fsm_apply_clusterrolebindings.go index 2b63b63f..87613dba 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_apply_clusterrolebindings.go +++ b/internal/controller/runtime/fsm/runtime_fsm_apply_clusterrolebindings.go @@ -2,14 +2,15 @@ package fsm import ( "context" + "fmt" "slices" - authenticationv1alpha1 "github.com/gardener/gardener/pkg/apis/authentication/v1alpha1" - gardener_api "github.com/gardener/gardener/pkg/apis/core/v1beta1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" + corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/clientcmd" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -17,16 +18,17 @@ import ( var ( //nolint:gochecknoglobals - labelsClusterRoleBindings = map[string]string{ - "app": "kyma", + labelsManagedByKIM = map[string]string{ "reconciler.kyma-project.io/managed-by": "infrastructure-manager", } + //nolint:gochecknoglobals + labelsManagedByReconciler = map[string]string{ + "reconciler.kyma-project.io/managed-by": "reconciler", + } ) func sFnApplyClusterRoleBindings(ctx context.Context, m *fsm, s *systemState) (stateFn, *ctrl.Result, error) { - // prepare subresource client to request admin kubeconfig - srscClient := m.ShootClient.SubResource("adminkubeconfig") - shootAdminClient, err := GetShootClient(ctx, srscClient, s.shoot) + shootAdminClient, err := GetShootClient(ctx, m.Client, s.instance) if err != nil { updateCRBApplyFailed(&s.instance) return updateStatusAndStopWithError(err) @@ -63,15 +65,15 @@ func sFnApplyClusterRoleBindings(ctx context.Context, m *fsm, s *systemState) (s } //nolint:gochecknoglobals -var GetShootClient = func(ctx context.Context, - adminKubeconfigClient client.SubResourceClient, shoot *gardener_api.Shoot) (client.Client, error) { - // request for admin kubeconfig with low expiration timeout - var req authenticationv1alpha1.AdminKubeconfigRequest - if err := adminKubeconfigClient.Create(ctx, shoot, &req); err != nil { +var GetShootClient = func(ctx context.Context, cnt client.Client, runtime imv1.Runtime) (client.Client, error) { + runtimeID := runtime.Labels[imv1.LabelKymaRuntimeID] + + secret, err := getKubeconfigSecret(ctx, cnt, runtimeID, runtime.Namespace) + if err != nil { return nil, err } - restConfig, err := clientcmd.RESTConfigFromKubeConfig(req.Status.Kubeconfig) + restConfig, err := clientcmd.RESTConfigFromKubeConfig(secret.Data[kubeconfigSecretKey]) if err != nil { return nil, err } @@ -84,6 +86,24 @@ var GetShootClient = func(ctx context.Context, return shootClientWithAdmin, nil } +func getKubeconfigSecret(ctx context.Context, cnt client.Client, runtimeID, namespace string) (corev1.Secret, error) { + secretName := fmt.Sprintf("kubeconfig-%s", runtimeID) + + var kubeconfigSecret corev1.Secret + secretKey := types.NamespacedName{Name: secretName, Namespace: namespace} + + err := cnt.Get(ctx, secretKey, &kubeconfigSecret) + + if err != nil { + return corev1.Secret{}, err + } + + if kubeconfigSecret.Data == nil { + return corev1.Secret{}, fmt.Errorf("kubeconfig secret `%s` does not contain kubeconfig data", kubeconfigSecret.Name) + } + return kubeconfigSecret, nil +} + func isRBACUserKindOneOf(names []string) func(rbacv1.Subject) bool { return func(s rbacv1.Subject) bool { return s.Kind == rbacv1.UserKind && @@ -94,7 +114,7 @@ func isRBACUserKindOneOf(names []string) func(rbacv1.Subject) bool { func getRemoved(crbs []rbacv1.ClusterRoleBinding, admins []string) (removed []rbacv1.ClusterRoleBinding) { // iterate over cluster role bindings to find out removed administrators for _, crb := range crbs { - if !labels.Set(crb.Labels).AsSelector().Matches(labels.Set(labelsClusterRoleBindings)) { + if !managedByKIM(crb) { // cluster role binding is not controlled by KIM continue } @@ -116,10 +136,18 @@ func getRemoved(crbs []rbacv1.ClusterRoleBinding, admins []string) (removed []rb return removed } +func managedByKIM(crb rbacv1.ClusterRoleBinding) bool { + selector := labels.Set(crb.Labels).AsSelector() + isManagedByKIM := selector.Matches(labels.Set(labelsManagedByKIM)) + isManagedByReconciler := selector.Matches(labels.Set(labelsManagedByReconciler)) + // Provisioner managed CRBs with label managed-by=reconciler, we have to manage them as well + return isManagedByKIM || isManagedByReconciler +} + //nolint:gochecknoglobals var newContainsAdmin = func(admin string) func(rbacv1.ClusterRoleBinding) bool { return func(crb rbacv1.ClusterRoleBinding) bool { - if !labels.Set(crb.Labels).AsSelector().Matches(labels.Set(labelsClusterRoleBindings)) { + if !managedByKIM(crb) { return false } isAdmin := isRBACUserKindOneOf([]string{admin}) @@ -144,7 +172,7 @@ func toAdminClusterRoleBinding(name string) rbacv1.ClusterRoleBinding { return rbacv1.ClusterRoleBinding{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "admin-", - Labels: labelsClusterRoleBindings, + Labels: labelsManagedByKIM, }, Subjects: []rbacv1.Subject{{ Kind: rbacv1.UserKind, diff --git a/internal/controller/runtime/fsm/runtime_fsm_apply_crb_test.go b/internal/controller/runtime/fsm/runtime_fsm_apply_crb_test.go index c8b7eb38..62c78823 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_apply_crb_test.go +++ b/internal/controller/runtime/fsm/runtime_fsm_apply_crb_test.go @@ -5,7 +5,6 @@ import ( "fmt" "time" - gardener_api "github.com/gardener/gardener/pkg/apis/core/v1beta1" imv1 "github.com/kyma-project/infrastructure-manager/api/v1" "github.com/kyma-project/infrastructure-manager/internal/controller/metrics/mocks" . "github.com/onsi/ginkgo/v2" @@ -31,11 +30,11 @@ var _ = Describe(`runtime_fsm_apply_crb`, Label("applyCRB"), func() { } DescribeTable("getMissing", - func(tc tcGetCRB) { + func(tc tcCRBData) { actual := getMissing(tc.crbs, tc.admins) Expect(actual).To(BeComparableTo(tc.expected)) }, - Entry("should return a list with CRBs to be created", tcGetCRB{ + Entry("should return a list with CRBs to be created", tcCRBData{ admins: []string{"test1", "test2"}, crbs: nil, expected: []rbacv1.ClusterRoleBinding{ @@ -43,7 +42,16 @@ var _ = Describe(`runtime_fsm_apply_crb`, Label("applyCRB"), func() { toAdminClusterRoleBinding("test2"), }, }), - Entry("should return nil list if no admins missing", tcGetCRB{ + Entry("should return nil list if no admins missing", tcCRBData{ + admins: []string{"test1", "test2", "test3"}, + crbs: []rbacv1.ClusterRoleBinding{ + toAdminClusterRoleBinding("test1"), + toManagedClusterRoleBinding("test2", "reconciler"), + toManagedClusterRoleBinding("test3", "infrastructure-manager"), + }, + expected: nil, + }), + Entry("should return nil list if no admins missing", tcCRBData{ admins: []string{"test1"}, crbs: []rbacv1.ClusterRoleBinding{ toAdminClusterRoleBinding("test1"), @@ -53,26 +61,26 @@ var _ = Describe(`runtime_fsm_apply_crb`, Label("applyCRB"), func() { ) DescribeTable("getRemoved", - func(tc tcGetCRB) { + func(tc tcCRBData) { actual := getRemoved(tc.crbs, tc.admins) Expect(actual).To(BeComparableTo(tc.expected)) }, - Entry("should return nil list if CRB list is nil", tcGetCRB{ + Entry("should return nil list if CRB list is nil", tcCRBData{ admins: []string{"test1"}, crbs: nil, expected: nil, }), - Entry("should return nil list if CRB list is empty", tcGetCRB{ + Entry("should return nil list if CRB list is empty", tcCRBData{ admins: []string{"test1"}, crbs: []rbacv1.ClusterRoleBinding{}, expected: nil, }), - Entry("should return nil list if no admins to remove", tcGetCRB{ + Entry("should return nil list if no admins to remove", tcCRBData{ admins: []string{"test1"}, crbs: []rbacv1.ClusterRoleBinding{toAdminClusterRoleBinding("test1")}, expected: nil, }), - Entry("should return list if with CRBs to remove", tcGetCRB{ + Entry("should return list if with CRBs to remove", tcCRBData{ admins: []string{"test2"}, crbs: []rbacv1.ClusterRoleBinding{ toAdminClusterRoleBinding("test1"), @@ -84,6 +92,38 @@ var _ = Describe(`runtime_fsm_apply_crb`, Label("applyCRB"), func() { toAdminClusterRoleBinding("test3"), }, }), + Entry("should not remove CRB managed by reconciler", tcCRBData{ + admins: []string{"test1", "test2"}, + crbs: []rbacv1.ClusterRoleBinding{ + toManagedClusterRoleBinding("test1", "reconciler"), + toAdminClusterRoleBinding("test3"), + }, + expected: []rbacv1.ClusterRoleBinding{ + toAdminClusterRoleBinding("test3"), + }, + }), + Entry("should not remove CRB not managed by reconciler or KIM", tcCRBData{ + admins: []string{"test1", "test2"}, + crbs: []rbacv1.ClusterRoleBinding{ + toManagedClusterRoleBinding("test3", "should-stay"), + toManagedClusterRoleBinding("test4", ""), + }, + expected: nil, + }), + Entry("should remove CRB managed by reconciler or KIM, that are not in the admin list", tcCRBData{ + admins: []string{"test4", "test5"}, + crbs: []rbacv1.ClusterRoleBinding{ + toManagedClusterRoleBinding("test1", "infrastructure-manager"), + toManagedClusterRoleBinding("test2", "reconciler"), + toManagedClusterRoleBinding("test3", "should-stay"), + toManagedClusterRoleBinding("test4", "infrastructure-manager"), + toManagedClusterRoleBinding("test5", "reconciler"), + }, + expected: []rbacv1.ClusterRoleBinding{ + toManagedClusterRoleBinding("test1", "infrastructure-manager"), + toManagedClusterRoleBinding("test2", "reconciler"), + }, + }), ) testRuntime := imv1.Runtime{ @@ -113,8 +153,8 @@ var _ = Describe(`runtime_fsm_apply_crb`, Label("applyCRB"), func() { defaultSetup := func(f *fsm) error { GetShootClient = func( _ context.Context, - _ client.SubResourceClient, - _ *gardener_api.Shoot) (client.Client, error) { + _ client.Client, + _ imv1.Runtime) (client.Client, error) { return f.Client, nil } return nil @@ -188,8 +228,8 @@ var _ = Describe(`runtime_fsm_apply_crb`, Label("applyCRB"), func() { setup: func(f *fsm) error { GetShootClient = func( _ context.Context, - _ client.SubResourceClient, - _ *gardener_api.Shoot) (client.Client, error) { + _ client.Client, + _ imv1.Runtime) (client.Client, error) { return nil, testErr } return nil @@ -199,7 +239,7 @@ var _ = Describe(`runtime_fsm_apply_crb`, Label("applyCRB"), func() { ) }) -type tcGetCRB struct { +type tcCRBData struct { crbs []rbacv1.ClusterRoleBinding admins []string expected []rbacv1.ClusterRoleBinding @@ -237,3 +277,11 @@ func newTestScheme() (*runtime.Scheme, error) { } return schema, nil } + +func toManagedClusterRoleBinding(name, managedBy string) rbacv1.ClusterRoleBinding { + clusterRoleBinding := toAdminClusterRoleBinding(name) + clusterRoleBinding.Labels = map[string]string{ + "reconciler.kyma-project.io/managed-by": managedBy, + } + return clusterRoleBinding +} diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go index 58c8ce0d..fa7b140a 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc.go @@ -72,8 +72,7 @@ func createDefaultOIDCConfig(defaultSharedIASTenant config.OidcProvider) gardene } func recreateOpenIDConnectResources(ctx context.Context, m *fsm, s *systemState) error { - srscClient := m.ShootClient.SubResource("adminkubeconfig") - shootAdminClient, shootClientError := GetShootClient(ctx, srscClient, s.shoot) + shootAdminClient, shootClientError := GetShootClient(ctx, m.Client, s.instance) if shootClientError != nil { return shootClientError } diff --git a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go index c3a6beb7..e74ba1ab 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go +++ b/internal/controller/runtime/fsm/runtime_fsm_configure_oidc_test.go @@ -63,7 +63,7 @@ func TestOidcState(t *testing.T) { var fakeClient = fake.NewClientBuilder(). WithScheme(scheme). Build() - fsm := &fsm{K8s: K8s{ + testFsm := &fsm{K8s: K8s{ ShootClient: fakeClient, Client: fakeClient, }, @@ -77,8 +77,8 @@ func TestOidcState(t *testing.T) { } GetShootClient = func( _ context.Context, - _ client.SubResourceClient, - _ *gardener.Shoot) (client.Client, error) { + _ client.Client, + _ imv1.Runtime) (client.Client, error) { return fakeClient, nil } // end of fake client setup @@ -106,7 +106,7 @@ func TestOidcState(t *testing.T) { } // when - stateFn, _, _ := sFnConfigureOidc(ctx, fsm, systemState) + stateFn, _, _ := sFnConfigureOidc(ctx, testFsm, systemState) // then require.Contains(t, stateFn.name(), "sFnApplyClusterRoleBindings") @@ -131,14 +131,14 @@ func TestOidcState(t *testing.T) { var fakeClient = fake.NewClientBuilder(). WithScheme(scheme). Build() - fsm := &fsm{K8s: K8s{ + testFsm := &fsm{K8s: K8s{ ShootClient: fakeClient, Client: fakeClient, }} GetShootClient = func( _ context.Context, - _ client.SubResourceClient, - _ *gardener.Shoot) (client.Client, error) { + _ client.Client, + _ imv1.Runtime) (client.Client, error) { return fakeClient, nil } // end of fake client setup @@ -171,7 +171,7 @@ func TestOidcState(t *testing.T) { } // when - stateFn, _, _ := sFnConfigureOidc(ctx, fsm, systemState) + stateFn, _, _ := sFnConfigureOidc(ctx, testFsm, systemState) // then require.Contains(t, stateFn.name(), "sFnApplyClusterRoleBindings") @@ -198,14 +198,14 @@ func TestOidcState(t *testing.T) { var fakeClient = fake.NewClientBuilder(). WithScheme(scheme). Build() - fsm := &fsm{K8s: K8s{ + testFSM := &fsm{K8s: K8s{ ShootClient: fakeClient, Client: fakeClient, }} GetShootClient = func( _ context.Context, - _ client.SubResourceClient, - _ *gardener.Shoot) (client.Client, error) { + _ client.Client, + _ imv1.Runtime) (client.Client, error) { return fakeClient, nil } // end of fake client setup @@ -241,7 +241,7 @@ func TestOidcState(t *testing.T) { } // when - stateFn, _, _ := sFnConfigureOidc(ctx, fsm, systemState) + stateFn, _, _ := sFnConfigureOidc(ctx, testFSM, systemState) // then require.Contains(t, stateFn.name(), "sFnApplyClusterRoleBindings") diff --git a/internal/controller/runtime/fsm/runtime_fsm_create_kubeconfig.go b/internal/controller/runtime/fsm/runtime_fsm_create_kubeconfig.go index 72155b6d..a52c79e5 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_create_kubeconfig.go +++ b/internal/controller/runtime/fsm/runtime_fsm_create_kubeconfig.go @@ -12,6 +12,10 @@ import ( ctrl "sigs.k8s.io/controller-runtime" ) +const ( + kubeconfigSecretKey = "config" +) + func sFnCreateKubeconfig(ctx context.Context, m *fsm, s *systemState) (stateFn, *ctrl.Result, error) { m.log.Info("Create Gardener Cluster CR state") @@ -110,7 +114,7 @@ func makeGardenerClusterForRuntime(runtime imv1.Runtime, shoot *gardener.Shoot) Secret: imv1.Secret{ Name: fmt.Sprintf("kubeconfig-%s", runtime.Labels[imv1.LabelKymaRuntimeID]), Namespace: runtime.Namespace, - Key: "config", + Key: kubeconfigSecretKey, }, }, }, diff --git a/internal/controller/runtime/fsm/runtime_fsm_delete_shoot.go b/internal/controller/runtime/fsm/runtime_fsm_delete_shoot.go index 37f4a33d..0875cbb9 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_delete_shoot.go +++ b/internal/controller/runtime/fsm/runtime_fsm_delete_shoot.go @@ -16,7 +16,7 @@ func sFnDeleteShoot(ctx context.Context, m *fsm, s *systemState) (stateFn, *ctrl // wait section if !s.shoot.GetDeletionTimestamp().IsZero() { m.log.Info("Waiting for shoot to be deleted", "Name", s.shoot.Name, "Namespace", s.shoot.Namespace) - return requeueAfter(m.RCCfg.GardenerRequeueDuration) + return requeueAfter(m.RCCfg.RequeueDurationShootDelete) } // action section @@ -58,7 +58,7 @@ func sFnDeleteShoot(ctx context.Context, m *fsm, s *systemState) (stateFn, *ctrl } // out section - return updateStatusAndRequeueAfter(m.RCCfg.GardenerRequeueDuration) + return updateStatusAndRequeueAfter(m.RCCfg.RequeueDurationShootDelete) } // workaround diff --git a/internal/controller/runtime/fsm/runtime_fsm_waiting_for_shoot_reconcile.go b/internal/controller/runtime/fsm/runtime_fsm_waiting_for_shoot_reconcile.go index 788e60d1..1b6f2855 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_waiting_for_shoot_reconcile.go +++ b/internal/controller/runtime/fsm/runtime_fsm_waiting_for_shoot_reconcile.go @@ -23,7 +23,7 @@ func sFnWaitForShootReconcile(_ context.Context, m *fsm, s *systemState) (stateF "Unknown", "Shoot update is in progress") - return updateStatusAndRequeueAfter(m.RCCfg.GardenerRequeueDuration) + return updateStatusAndRequeueAfter(m.RCCfg.RequeueDurationShootReconcile) case gardener.LastOperationStateFailed: lastErrors := s.shoot.Status.LastErrors @@ -36,7 +36,7 @@ func sFnWaitForShootReconcile(_ context.Context, m *fsm, s *systemState) (stateF imv1.ConditionReasonShootCreationPending, "Unknown", "Retryable gardener errors during cluster reconcile") - return updateStatusAndRequeueAfter(m.RCCfg.GardenerRequeueDuration) + return updateStatusAndRequeueAfter(m.RCCfg.RequeueDurationShootReconcile) } msg := fmt.Sprintf("error during cluster processing: reconcilation failed for shoot %s, reason: %s, exiting with no retry", s.shoot.Name, reason) diff --git a/internal/controller/runtime/fsm/runtime_fsm_waiting_shoot_creation.go b/internal/controller/runtime/fsm/runtime_fsm_waiting_shoot_creation.go index 2c0036fc..d0322379 100644 --- a/internal/controller/runtime/fsm/runtime_fsm_waiting_shoot_creation.go +++ b/internal/controller/runtime/fsm/runtime_fsm_waiting_shoot_creation.go @@ -39,7 +39,7 @@ func sFnWaitForShootCreation(_ context.Context, m *fsm, s *systemState) (stateFn "Unknown", "Shoot creation in progress") - return updateStatusAndRequeueAfter(m.RCCfg.GardenerRequeueDuration) + return updateStatusAndRequeueAfter(m.RCCfg.RequeueDurationShootCreate) case gardener.LastOperationStateFailed: lastErrors := s.shoot.Status.LastErrors @@ -52,7 +52,7 @@ func sFnWaitForShootCreation(_ context.Context, m *fsm, s *systemState) (stateFn imv1.ConditionReasonShootCreationPending, "Unknown", "Retryable gardener errors during cluster provisioning") - return updateStatusAndRequeueAfter(m.RCCfg.GardenerRequeueDuration) + return updateStatusAndRequeueAfter(m.RCCfg.RequeueDurationShootCreate) } msg := fmt.Sprintf("Provisioning failed for shoot: %s ! Last state: %s, Description: %s", s.shoot.Name, s.shoot.Status.LastOperation.State, s.shoot.Status.LastOperation.Description) diff --git a/internal/controller/runtime/fsm/utilz_for_test.go b/internal/controller/runtime/fsm/utilz_for_test.go index f5134dd7..d0c8801c 100644 --- a/internal/controller/runtime/fsm/utilz_for_test.go +++ b/internal/controller/runtime/fsm/utilz_for_test.go @@ -24,6 +24,8 @@ type fakeFSMOpt func(*fsm) error const defaultControlPlaneRequeueDuration = 10 * time.Second const defaultGardenerRequeueDuration = 15 * time.Second +const defaultRequeueDurationShootCreate = 15 * time.Second +const defaultRequeueDurationShootDelete = 15 * time.Second var ( errFailedToCreateFakeFSM = fmt.Errorf("failed to create fake FSM") diff --git a/internal/controller/runtime/runtime_controller.go b/internal/controller/runtime/runtime_controller.go index d87f09a7..a92d1ed7 100644 --- a/internal/controller/runtime/runtime_controller.go +++ b/internal/controller/runtime/runtime_controller.go @@ -27,9 +27,12 @@ import ( "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/predicate" ) +const numberOfWorkers = 25 + // RuntimeReconciler reconciles a Runtime object // nolint:revive type RuntimeReconciler struct { @@ -86,6 +89,7 @@ func NewRuntimeReconciler(mgr ctrl.Manager, shootClient client.Client, logger lo func (r *RuntimeReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&imv1.Runtime{}). + WithOptions(controller.Options{MaxConcurrentReconciles: numberOfWorkers}). WithEventFilter(predicate.Or( predicate.GenerationChangedPredicate{}, predicate.LabelChangedPredicate{}, diff --git a/internal/controller/runtime/suite_test.go b/internal/controller/runtime/suite_test.go index cf1e044d..8eb94681 100644 --- a/internal/controller/runtime/suite_test.go +++ b/internal/controller/runtime/suite_test.go @@ -25,7 +25,7 @@ import ( gardener_api "github.com/gardener/gardener/pkg/apis/core/v1beta1" gardener_oidc "github.com/gardener/oidc-webhook-authenticator/apis/authentication/v1alpha1" - infrastructuremanagerv1 "github.com/kyma-project/infrastructure-manager/api/v1" + imv1 "github.com/kyma-project/infrastructure-manager/api/v1" "github.com/kyma-project/infrastructure-manager/internal/controller/metrics/mocks" "github.com/kyma-project/infrastructure-manager/internal/controller/runtime/fsm" "github.com/kyma-project/infrastructure-manager/pkg/config" @@ -94,7 +94,7 @@ var _ = BeforeSuite(func() { Expect(err).NotTo(HaveOccurred()) Expect(cfg).NotTo(BeNil()) - err = infrastructuremanagerv1.AddToScheme(scheme.Scheme) + err = imv1.AddToScheme(scheme.Scheme) Expect(err).NotTo(HaveOccurred()) mgr, err := ctrl.NewManager(cfg, ctrl.Options{ @@ -106,7 +106,7 @@ var _ = BeforeSuite(func() { clientScheme := runtime.NewScheme() _ = gardener_api.AddToScheme(clientScheme) - _ = infrastructuremanagerv1.AddToScheme(clientScheme) + _ = imv1.AddToScheme(clientScheme) // tracker will be updated with different shoot sequence for each test case tracker := clienttesting.NewObjectTracker(clientScheme, serializer.NewCodecFactory(clientScheme).UniversalDecoder()) @@ -121,12 +121,15 @@ var _ = BeforeSuite(func() { mm.On("CleanUpRuntimeGauge", mock.Anything, mock.Anything).Return() fsmCfg := fsm.RCCfg{ - Finalizer: infrastructuremanagerv1.Finalizer, - Config: convConfig, - Metrics: mm, - AuditLogging: map[string]map[string]auditlogs.AuditLogData{}, - GardenerRequeueDuration: 3 * time.Second, - ControlPlaneRequeueDuration: 3 * time.Second, + Finalizer: imv1.Finalizer, + Config: convConfig, + Metrics: mm, + AuditLogging: map[string]map[string]auditlogs.AuditLogData{}, + GardenerRequeueDuration: 3 * time.Second, + ControlPlaneRequeueDuration: 3 * time.Second, + RequeueDurationShootReconcile: 3 * time.Second, + RequeueDurationShootCreate: 3 * time.Second, + RequeueDurationShootDelete: 3 * time.Second, } runtimeReconciler = NewRuntimeReconciler(mgr, gardenerTestClient, logger, fsmCfg) @@ -144,7 +147,7 @@ var _ = BeforeSuite(func() { err = gardener_oidc.AddToScheme(shootClientScheme) k8sFakeClientRoleBindings = fake.NewClientBuilder().WithScheme(shootClientScheme).Build() - fsm.GetShootClient = func(_ context.Context, _ client.SubResourceClient, _ *gardener_api.Shoot) (client.Client, error) { + fsm.GetShootClient = func(_ context.Context, _ client.Client, _ imv1.Runtime) (client.Client, error) { return k8sFakeClientRoleBindings, nil }