diff --git a/charts/gardener-extension-admission-metal/charts/application/templates/mutatingwebhook-mutator.yaml b/charts/gardener-extension-admission-metal/charts/application/templates/mutatingwebhook-mutator.yaml deleted file mode 100644 index c5c1bbf94..000000000 --- a/charts/gardener-extension-admission-metal/charts/application/templates/mutatingwebhook-mutator.yaml +++ /dev/null @@ -1,37 +0,0 @@ -apiVersion: admissionregistration.k8s.io/v1 -kind: MutatingWebhookConfiguration -metadata: - name: {{ include "name" . }} -webhooks: -- name: mutation.metal.provider.extensions.gardener.cloud - rules: - - apiGroups: - - "core.gardener.cloud" - apiVersions: - - v1alpha1 - - v1beta1 - operations: - - CREATE - resources: - - shoots - failurePolicy: Fail - objectSelector: - {{- if .Values.global.webhookConfig.useObjectSelector }} - matchLabels: - provider.extensions.gardener.cloud/metal: "true" - {{- end }} - namespaceSelector: {} - sideEffects: None - admissionReviewVersions: - - v1 - - v1beta1 - clientConfig: - {{- if .Values.global.virtualGarden.enabled }} - url: {{ printf "https://%s.%s/webhooks/mutate" (include "name" .) (.Release.Namespace) }} - {{- else }} - service: - namespace: {{ .Release.Namespace }} - name: {{ include "name" . }} - path: /webhooks/mutate - {{- end }} - caBundle: {{ required ".Values.global.webhookConfig.caBundle is required" .Values.global.webhookConfig.caBundle | b64enc }} \ No newline at end of file diff --git a/charts/gardener-extension-admission-metal/charts/application/templates/validatingwebhook-validator.yaml b/charts/gardener-extension-admission-metal/charts/application/templates/validatingwebhook-validator.yaml deleted file mode 100644 index 9b5728f78..000000000 --- a/charts/gardener-extension-admission-metal/charts/application/templates/validatingwebhook-validator.yaml +++ /dev/null @@ -1,35 +0,0 @@ -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: {{ include "name" . }} -webhooks: -- name: validation.metal.provider.extensions.gardener.cloud - rules: - - apiGroups: - - "core.gardener.cloud" - apiVersions: - - v1alpha1 - - v1beta1 - operations: - - CREATE - - UPDATE - resources: - - cloudprofiles - - shoots - failurePolicy: Fail - objectSelector: {} - namespaceSelector: {} - sideEffects: None - admissionReviewVersions: - - v1 - - v1beta1 - clientConfig: - {{- if .Values.global.virtualGarden.enabled }} - url: {{ printf "https://%s.%s/webhooks/validate" (include "name" .) (.Release.Namespace) }} - {{- else }} - service: - namespace: {{ .Release.Namespace }} - name: {{ include "name" . }} - path: /webhooks/validate - {{- end }} - caBundle: {{ required ".Values.webhookConfig.caBundle is required" (b64enc .Values.global.webhookConfig.caBundle) }} diff --git a/charts/gardener-extension-admission-metal/charts/runtime/templates/_helpers.tpl b/charts/gardener-extension-admission-metal/charts/runtime/templates/_helpers.tpl index 98a57c4eb..67fec204d 100644 --- a/charts/gardener-extension-admission-metal/charts/runtime/templates/_helpers.tpl +++ b/charts/gardener-extension-admission-metal/charts/runtime/templates/_helpers.tpl @@ -21,3 +21,7 @@ app.kubernetes.io/instance: {{ .Release.Name }} {{- printf "%s:%s" .repository .tag }} {{- end }} {{- end }} + +{{- define "leaderelectionid" -}} +gardener-extension-admission-metal +{{- end -}} diff --git a/charts/gardener-extension-admission-metal/charts/runtime/templates/deployment.yaml b/charts/gardener-extension-admission-metal/charts/runtime/templates/deployment.yaml index 21ec5b4a8..6d968504b 100644 --- a/charts/gardener-extension-admission-metal/charts/runtime/templates/deployment.yaml +++ b/charts/gardener-extension-admission-metal/charts/runtime/templates/deployment.yaml @@ -14,7 +14,6 @@ spec: template: metadata: annotations: - checksum/secret-gardener-extension-admission-metal-cert: {{ include (print $.Template.BasePath "/secret-cert.yaml") . | sha256sum }} {{- if .Values.global.kubeconfig }} checksum/gardener-extension-admission-metal-kubeconfig: {{ include (print $.Template.BasePath "/secret-kubeconfig.yaml") . | sha256sum }} {{- end }} @@ -37,11 +36,24 @@ spec: - /gardener-extension-metal-hyper - admission-metal - --webhook-config-server-port={{ .Values.global.webhookConfig.serverPort }} - - --webhook-config-cert-dir=/etc/gardener-extension-admission-metal/srv + {{- if .Values.global.virtualGarden.enabled }} + - --webhook-config-mode=url + - --webhook-config-url={{ printf "%s.%s" (include "name" .) (.Release.Namespace) }} + {{- else }} + - --webhook-config-mode=service + {{- end }} + - --webhook-config-namespace={{ .Release.Namespace }} {{- if .Values.global.kubeconfig }} - --kubeconfig=/etc/gardener-extension-admission-metal/kubeconfig/kubeconfig {{- end }} + {{- if .Values.global.projectedKubeconfig }} + - --kubeconfig={{ required ".Values.global.projectedKubeconfig.baseMountPath is required" .Values.global.projectedKubeconfig.baseMountPath }}/kubeconfig + {{- end }} + {{- if .Values.global.metricsPort }} + - --metrics-bind-address=:{{ .Values.global.metricsPort }} + {{- end }} - --health-bind-address=:{{ .Values.global.healthPort }} + - --leader-election-id={{ include "leaderelectionid" . }} livenessProbe: httpGet: path: /healthz @@ -54,41 +66,37 @@ spec: port: {{ .Values.global.healthPort }} scheme: HTTP initialDelaySeconds: 5 - ports: - - name: webhook-server - containerPort: {{ .Values.global.webhookConfig.serverPort }} - protocol: TCP - livenessProbe: - tcpSocket: - port: {{ .Values.global.webhookConfig.serverPort }} - initialDelaySeconds: 5 - periodSeconds: 10 env: + - name: LEADER_ELECTION_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace {{- range $key, $value := .Values.global.defaulter }} {{- if ne nil $value }} - - name: DEFAULTER_{{ upper $key }} - value: {{ $value | quote }} + - name: DEFAULTER_{{ upper $key }} + value: {{ $value | quote }} {{- end }} {{- end }} - + # TODO: This is not yet working, maybe with Gardener Operator? + # {{- if .Values.global.virtualGarden.enabled }} + # - name: SOURCE_CLUSTER + # value: enabled + # {{- end }} + ports: + - name: webhook-server + containerPort: {{ .Values.global.webhookConfig.serverPort }} + protocol: TCP {{- if .Values.global.resources }} resources: {{ toYaml .Values.global.resources | nindent 10 }} {{- end }} volumeMounts: - - name: gardener-extension-admission-metal-cert - mountPath: /etc/gardener-extension-admission-metal/srv - readOnly: true {{- if .Values.global.kubeconfig }} - name: gardener-extension-admission-metal-kubeconfig mountPath: /etc/gardener-extension-admission-metal/kubeconfig readOnly: true {{- end }} volumes: - - name: gardener-extension-admission-metal-cert - secret: - secretName: gardener-extension-admission-metal-cert - defaultMode: 420 {{- if .Values.global.kubeconfig }} - name: gardener-extension-admission-metal-kubeconfig secret: diff --git a/charts/gardener-extension-admission-metal/charts/runtime/templates/secret-cert.yaml b/charts/gardener-extension-admission-metal/charts/runtime/templates/secret-cert.yaml deleted file mode 100644 index 55be846d3..000000000 --- a/charts/gardener-extension-admission-metal/charts/runtime/templates/secret-cert.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: gardener-extension-admission-metal-cert - namespace: {{ .Release.Namespace }} - labels: - app: gardener - role: controller-manager - chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" - release: "{{ .Release.Name }}" - heritage: "{{ .Release.Service }}" -type: Opaque -data: - tls.crt: {{ required ".Values.global.webhookConfig.tls.crt is required" (b64enc .Values.global.webhookConfig.tls.crt) }} - tls.key: {{ required ".Values.global.webhookConfig.tls.key is required" (b64enc .Values.global.webhookConfig.tls.key) }} diff --git a/charts/gardener-extension-admission-metal/charts/runtime/templates/serviceaccount.yaml b/charts/gardener-extension-admission-metal/charts/runtime/templates/serviceaccount.yaml new file mode 100644 index 000000000..52458f74c --- /dev/null +++ b/charts/gardener-extension-admission-metal/charts/runtime/templates/serviceaccount.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "name" . }} + namespace: {{ .Release.Namespace }} + labels: +{{ include "labels" . | indent 4 }} diff --git a/charts/gardener-extension-admission-metal/values.yaml b/charts/gardener-extension-admission-metal/values.yaml index 74ff33e6b..d9c61c61f 100644 --- a/charts/gardener-extension-admission-metal/values.yaml +++ b/charts/gardener-extension-admission-metal/values.yaml @@ -7,6 +7,7 @@ global: pullPolicy: Always replicaCount: 1 resources: {} + metricsPort: 8080 healthPort: 8081 vpa: enabled: true @@ -17,21 +18,7 @@ global: updatePolicy: updateMode: "Auto" webhookConfig: - caBundle: | - -----BEGIN CERTIFICATE----- - ... - -----END CERTIFICATE----- serverPort: 443 - tls: - crt: | - -----BEGIN CERTIFICATE----- - ... - -----END CERTIFICATE----- - key: | - -----BEGIN RSA PRIVATE KEY----- - ... - -----END RSA PRIVATE KEY----- - useObjectSelector: false # Kubeconfig to the target cluster. In-cluster configuration will be used if not specified. kubeconfig: diff --git a/cmd/gardener-extension-admission-metal/app/app.go b/cmd/gardener-extension-admission-metal/app/app.go index 1dfaae340..3e1fc1aa2 100644 --- a/cmd/gardener-extension-admission-metal/app/app.go +++ b/cmd/gardener-extension-admission-metal/app/app.go @@ -3,6 +3,7 @@ package app import ( "context" "fmt" + "os" admissioncmd "github.com/metal-stack/gardener-extension-provider-metal/pkg/admission/cmd" metalinstall "github.com/metal-stack/gardener-extension-provider-metal/pkg/apis/metal/install" @@ -12,15 +13,25 @@ import ( "github.com/gardener/gardener/extensions/pkg/util" webhookcmd "github.com/gardener/gardener/extensions/pkg/webhook/cmd" "github.com/gardener/gardener/pkg/apis/core/install" + v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants" gardenerhealthz "github.com/gardener/gardener/pkg/healthz" "github.com/spf13/cobra" + corev1 "k8s.io/api/core/v1" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" componentbaseconfig "k8s.io/component-base/config" "k8s.io/component-base/version/verflag" + "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/cluster" "sigs.k8s.io/controller-runtime/pkg/healthz" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/manager" ) +// AdmissionName is the name of the admission component. +const AdmissionName = "admission-metal" + var log = logf.Log.WithName("gardener-extension-admission-metal") // NewAdmissionCommand creates a new command for running an metal admission webhook. @@ -28,11 +39,26 @@ func NewAdmissionCommand(ctx context.Context) *cobra.Command { var ( restOpts = &controllercmd.RESTOptions{} mgrOpts = &controllercmd.ManagerOptions{ - WebhookServerPort: 443, - HealthBindAddress: ":8081", + LeaderElection: true, + LeaderElectionID: controllercmd.LeaderElectionNameID(AdmissionName), + LeaderElectionNamespace: os.Getenv("LEADER_ELECTION_NAMESPACE"), + WebhookServerPort: 443, + MetricsBindAddress: ":8080", + HealthBindAddress: ":8081", + WebhookCertDir: "/tmp/admission-metal-cert", + } + // options for the webhook server + webhookServerOptions = &webhookcmd.ServerOptions{ + Namespace: os.Getenv("WEBHOOK_CONFIG_NAMESPACE"), } webhookSwitches = admissioncmd.GardenWebhookSwitchOptions() - webhookOptions = webhookcmd.NewAddToManagerSimpleOptions(webhookSwitches) + webhookOptions = webhookcmd.NewAddToManagerOptions( + AdmissionName, + "", + nil, + webhookServerOptions, + webhookSwitches, + ) aggOption = controllercmd.NewOptionAggregator( restOpts, @@ -56,7 +82,33 @@ func NewAdmissionCommand(ctx context.Context) *cobra.Command { Burst: 130, }, restOpts.Completed().Config) - mgr, err := manager.New(restOpts.Completed().Config, mgrOpts.Completed().Options()) + managerOptions := mgrOpts.Completed().Options() + + // Operators can enable the source cluster option via SOURCE_CLUSTER environment variable. + // In-cluster config will be used if no SOURCE_KUBECONFIG is specified. + // + // The source cluster is for instance used by Gardener's certificate controller, to maintain certificate + // secrets in a different cluster ('runtime-garden') than the cluster where the webhook configurations + // are maintained ('virtual-garden'). + var sourceClusterConfig *rest.Config + if sourceClusterEnabled := os.Getenv("SOURCE_CLUSTER"); sourceClusterEnabled != "" { + log.Info("Configuring source cluster option") + var err error + sourceClusterConfig, err = clientcmd.BuildConfigFromFlags("", os.Getenv("SOURCE_KUBECONFIG")) + if err != nil { + return err + } + managerOptions.LeaderElectionConfig = sourceClusterConfig + } else { + // Restrict the cache for secrets to the configured namespace to avoid the need for cluster-wide list/watch permissions. + managerOptions.Cache = cache.Options{ + ByObject: map[client.Object]cache.ByObject{ + &corev1.Secret{}: {Namespaces: map[string]cache.Config{webhookOptions.Server.Completed().Namespace: {}}}, + }, + } + } + + mgr, err := manager.New(restOpts.Completed().Config, managerOptions) if err != nil { return fmt.Errorf("could not instantiate manager: %w", err) } @@ -67,8 +119,27 @@ func NewAdmissionCommand(ctx context.Context) *cobra.Command { return fmt.Errorf("could not update manager scheme: %w", err) } + var sourceCluster cluster.Cluster + if sourceClusterConfig != nil { + sourceCluster, err = cluster.New(sourceClusterConfig, func(opts *cluster.Options) { + opts.Logger = log + opts.Cache.DefaultNamespaces = map[string]cache.Config{v1beta1constants.GardenNamespace: {}} + }) + if err != nil { + return err + } + + if err := mgr.AddReadyzCheck("source-informer-sync", gardenerhealthz.NewCacheSyncHealthz(sourceCluster.GetCache())); err != nil { + return err + } + + if err = mgr.Add(sourceCluster); err != nil { + return err + } + } + log.Info("Setting up webhook server") - if err := webhookOptions.Completed().AddToManager(mgr); err != nil { + if _, err := webhookOptions.Completed().AddToManager(ctx, mgr, sourceCluster); err != nil { return err } diff --git a/cmd/gardener-extension-provider-metal/app/app.go b/cmd/gardener-extension-provider-metal/app/app.go index 0ace37a92..a6245a2cb 100644 --- a/cmd/gardener-extension-provider-metal/app/app.go +++ b/cmd/gardener-extension-provider-metal/app/app.go @@ -213,7 +213,7 @@ func NewControllerManagerCommand(ctx context.Context) *cobra.Command { workerCtrlOpts.Completed().Apply(&metalworker.DefaultAddOptions.Controller) metalworker.DefaultAddOptions.GardenCluster = gardenCluster - atomicShootWebhookConfig, err := webhookOptions.Completed().AddToManager(ctx, mgr) + atomicShootWebhookConfig, err := webhookOptions.Completed().AddToManager(ctx, mgr, nil) if err != nil { return fmt.Errorf("could not add webhooks to manager: %w", err) } diff --git a/example/controller-registration.yaml b/example/controller-registration.yaml index 9dccca3c9..bf885b3bc 100644 --- a/example/controller-registration.yaml +++ b/example/controller-registration.yaml @@ -8,7 +8,7 @@ providerConfig: chart: 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 values: image: - tag: v0.23.1 + tag: v0.24.3 --- apiVersion: core.gardener.cloud/v1beta1 kind: ControllerRegistration diff --git a/go.mod b/go.mod index 745474c50..8b9654685 100644 --- a/go.mod +++ b/go.mod @@ -8,48 +8,46 @@ require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/ahmetb/gen-crd-api-reference-docs v0.3.0 github.com/coreos/go-systemd/v22 v22.5.0 - github.com/gardener/etcd-druid v0.20.1 - github.com/gardener/gardener v1.83.3 + github.com/gardener/etcd-druid v0.22.0 + github.com/gardener/gardener v1.87.4 github.com/gardener/gardener-extension-networking-calico v1.36.1 github.com/gardener/gardener-extension-networking-cilium v1.26.0 github.com/gardener/machine-controller-manager v0.50.1 - github.com/go-logr/logr v1.4.1 + github.com/go-logr/logr v1.4.2 github.com/go-openapi/strfmt v0.23.0 github.com/golang/mock v1.6.0 github.com/google/go-cmp v0.6.0 - github.com/metal-stack/duros-controller v0.9.1 - github.com/metal-stack/firewall-controller-manager v0.4.0 + github.com/metal-stack/duros-controller v0.9.3 + github.com/metal-stack/firewall-controller-manager v0.4.2 github.com/metal-stack/firewall-controller/v2 v2.3.3 - github.com/metal-stack/metal-go v0.31.1 - github.com/metal-stack/metal-lib v0.16.2 + github.com/metal-stack/metal-go v0.32.3 + github.com/metal-stack/metal-lib v0.18.0 github.com/onsi/ginkgo v1.16.5 - github.com/onsi/gomega v1.33.1 - github.com/spf13/cobra v1.8.0 + github.com/onsi/gomega v1.34.1 + github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.9.0 k8s.io/api v0.29.3 k8s.io/apiextensions-apiserver v0.29.3 k8s.io/apimachinery v0.29.3 - k8s.io/autoscaler/vertical-pod-autoscaler v0.14.0 + k8s.io/autoscaler/vertical-pod-autoscaler v1.0.0 k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible - k8s.io/code-generator v0.29.3 + k8s.io/code-generator v0.28.3 k8s.io/component-base v0.29.3 - k8s.io/kubelet v0.29.3 - sigs.k8s.io/controller-runtime v0.16.5 + k8s.io/kubelet v0.28.3 + sigs.k8s.io/controller-runtime v0.16.6 sigs.k8s.io/yaml v1.4.0 ) require ( github.com/BurntSushi/toml v1.3.2 // indirect github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver v1.5.0 // indirect - github.com/Masterminds/sprig v2.22.0+incompatible // indirect - github.com/Masterminds/sprig/v3 v3.2.2 // indirect + github.com/Masterminds/sprig/v3 v3.2.3 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/bronze1man/yaml2json v0.0.0-20211227013850-8972abeaea25 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/coreos/go-oidc/v3 v3.10.0 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect @@ -60,7 +58,6 @@ require ( github.com/fluent/fluent-operator/v2 v2.2.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gardener/hvpa-controller/api v0.5.0 // indirect - github.com/ghodss/yaml v1.0.0 // indirect github.com/go-jose/go-jose/v4 v4.0.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zapr v1.3.0 // indirect @@ -92,6 +89,7 @@ require ( github.com/huandu/xstrings v1.4.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/ironcore-dev/vgopath v0.1.3 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0 // indirect @@ -116,20 +114,23 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nxadm/tail v1.4.11 // indirect github.com/oklog/ulid v1.3.1 // indirect - github.com/onsi/ginkgo/v2 v2.17.2 // indirect + github.com/onsi/ginkgo/v2 v2.19.0 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.19.0 // indirect - github.com/prometheus/client_model v0.6.0 // indirect - github.com/prometheus/common v0.51.0 // indirect - github.com/prometheus/procfs v0.13.0 // indirect + github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.54.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/segmentio/asm v1.2.0 // indirect github.com/shopspring/decimal v1.2.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/stretchr/objx v0.5.2 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + github.com/xeipuuv/gojsonschema v1.2.0 // indirect go.mongodb.org/mongo-driver v1.14.0 // indirect go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect @@ -137,27 +138,28 @@ require ( go.uber.org/mock v0.4.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/crypto v0.23.0 // indirect - golang.org/x/exp v0.0.0-20240318143956-a85f2c67cd81 // indirect - golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.25.0 // indirect - golang.org/x/oauth2 v0.20.0 // indirect + golang.org/x/crypto v0.25.0 // indirect + golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect + golang.org/x/mod v0.19.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/oauth2 v0.21.0 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.20.0 // indirect - golang.org/x/term v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/term v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.20.0 // indirect + golang.org/x/tools v0.23.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8 // indirect - google.golang.org/protobuf v1.33.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240617180043-68d350f18fd4 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - istio.io/api v0.0.0-20230217221049-9d422bf48675 // indirect - istio.io/client-go v1.17.1 // indirect - k8s.io/apiserver v0.28.3 // indirect + helm.sh/helm/v3 v3.11.1 // indirect + istio.io/api v1.19.2-0.20231011000955-f3015ebb5bd4 // indirect + istio.io/client-go v1.19.3 // indirect + k8s.io/apiserver v0.28.9 // indirect k8s.io/cluster-bootstrap v0.28.3 // indirect k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 // indirect k8s.io/helm v2.17.0+incompatible // indirect diff --git a/go.sum b/go.sum index 600394cbd..7e58016be 100644 --- a/go.sum +++ b/go.sum @@ -602,15 +602,11 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= 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 v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= -github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= -github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= -github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= -github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8= -github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= +github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= +github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/ahmetb/gen-crd-api-reference-docs v0.3.0 h1:+XfOU14S4bGuwyvCijJwhhBIjYN+YXS18jrCY2EzJaY= @@ -656,8 +652,9 @@ github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +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/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -679,7 +676,7 @@ github.com/coreos/go-oidc/v3 v3.10.0/go.mod h1:5j11xcw0D3+SGxn6Z/WFADsgcWVMyNAlS github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= @@ -728,17 +725,16 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4 github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/gardener/etcd-druid v0.20.1 h1:o6F4higujfg7dvBXvk+yPb86+3t2+XLE0Hmw5W1kXtM= -github.com/gardener/etcd-druid v0.20.1/go.mod h1:1tAeHycB0Vb2GfCX6sUCc6V6frGrCQI//quVg4K3GNA= -github.com/gardener/gardener v1.83.3 h1:ZnN5W0JWeUrheHHVpLfZc2xnl/vxLTQNRKCEB2VqrEM= -github.com/gardener/gardener v1.83.3/go.mod h1:WbCEy0CuG3fk1QFDeQeagwvWRtA7FaiuP9ska9EA7Xc= +github.com/gardener/etcd-druid v0.22.0 h1:DVe+Zjrb93r9vI1uUiCTMHBffIUoMAKhNzFZNC6hsQ8= +github.com/gardener/etcd-druid v0.22.0/go.mod h1:FROhfVKyWBo4krlPe3R6FIhJRmOmijEWBdEeUP0CJjE= +github.com/gardener/gardener v1.87.4 h1:pOWHDirMd04dLGd7I8fcv8UAZwrW6uFV8fJJfiQN0E0= +github.com/gardener/gardener v1.87.4/go.mod h1:MNqPkSxLD2w+HeIP56JnZbZtaqPnDb4hSRl3JWEZTWU= github.com/gardener/gardener-extension-networking-calico v1.36.1 h1:WyAdADamhxQgcCBrQOZAeSM/wm/urmmwBaqd2YLc7MY= github.com/gardener/gardener-extension-networking-calico v1.36.1/go.mod h1:GFmktIEzLxrOV6uNrCREeKjIkwYK6TlVOEPP7dffjAM= github.com/gardener/hvpa-controller/api v0.5.0 h1:f4F3O7YUrenwh4S3TgPREPiB287JjjUiUL18OqPLyAA= github.com/gardener/hvpa-controller/api v0.5.0/go.mod h1:QQl3ELkCaki+8RhXl0FZMfvnm0WCGwGJlGmrxJj6lvM= github.com/gardener/machine-controller-manager v0.50.1 h1:lL2q0O+K6jkgYzHPz85wIc9MzASZaiDvLYnTxW7P5ws= github.com/gardener/machine-controller-manager v0.50.1/go.mod h1:RySZ40AgbNV/wMq60G/w49kb+okbj5Xs1A6usz5Pm/I= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= @@ -768,8 +764,8 @@ github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbV github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +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/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= @@ -951,7 +947,7 @@ github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9 github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= @@ -963,6 +959,8 @@ 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/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/ironcore-dev/vgopath v0.1.3 h1:/g3QJ29VrUkYEy52kcUhtvQ3mxfbMIlI1uvEbmt6S4E= +github.com/ironcore-dev/vgopath v0.1.3/go.mod h1:edfsCmU2M4r2N+t4RebSluq//tF3vzogyiDDhcf7MXs= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= @@ -1025,10 +1023,10 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/metal-stack/duros-controller v0.9.1 h1:1DEWqGo9asBKBCpimO2RB0ZSusjOVqIjx120vpWJ1Uw= -github.com/metal-stack/duros-controller v0.9.1/go.mod h1:m27bLB7Fpj8CLVs2oBKnUGNwLDf81HCmjZUGraoAHA0= -github.com/metal-stack/firewall-controller-manager v0.4.0 h1:a2vskWMCjaDw7PhwLpm71y3apGKDxo2GYdHz3cWkt44= -github.com/metal-stack/firewall-controller-manager v0.4.0/go.mod h1:tp/yt1nv3P1pmNnkW4r4LJqLTxjZhZ8IgANXQvx/HFg= +github.com/metal-stack/duros-controller v0.9.3 h1:zpaiYxZ6NUqIfg/AHV0DOx7heOfdLznQtd2OkkDYYeI= +github.com/metal-stack/duros-controller v0.9.3/go.mod h1:JbHNZ+4cDHqO5qVOsLmbxN7LrCq/VTBi4lvS1+zNlzA= +github.com/metal-stack/firewall-controller-manager v0.4.2 h1:Ye+m0TzMFhemiQFLp5wV7mUaBCVeOlc6pyMfV2afl8g= +github.com/metal-stack/firewall-controller-manager v0.4.2/go.mod h1:tp/yt1nv3P1pmNnkW4r4LJqLTxjZhZ8IgANXQvx/HFg= github.com/metal-stack/firewall-controller/v2 v2.3.3 h1:4NrSFGl9NdUHQpKZK867ti6z0bPvZNPuP3ec1a7vGT8= github.com/metal-stack/firewall-controller/v2 v2.3.3/go.mod h1:Zo3HIlqqzWyvPGIpfWzsxkQjrIkmZHYtKgld71q24FE= github.com/metal-stack/gardener-extension-networking-cilium v1.16.1-0.20240510132804-f1f2b0fdce23 h1:NIloWL0ES3VscClkU49BqeCzqBcsniQv6xFx+D7aRII= @@ -1092,8 +1090,8 @@ github.com/onsi/ginkgo/v2 v2.9.0/go.mod h1:4xkjoL/tZv4SMWeww56BU5kAt19mVB47gTWxm github.com/onsi/ginkgo/v2 v2.9.1/go.mod h1:FEcmzVcCHl+4o9bQZVab+4dC9+j+91t2FHSzmGAPfuo= github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts= github.com/onsi/ginkgo/v2 v2.9.4/go.mod h1:gCQYp2Q+kSoIj7ykSVb9nskRSsR6PUj4AiLywzIhbKM= -github.com/onsi/ginkgo/v2 v2.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g= -github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= +github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= +github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= @@ -1108,8 +1106,8 @@ github.com/onsi/gomega v1.27.1/go.mod h1:aHX5xOykVYzWOV4WqQy0sy8BQptgukenXpCXfad github.com/onsi/gomega v1.27.3/go.mod h1:5vG284IBtfDAmDyrK+eGyZmUgUlmi+Wngqo557cZ6Gw= github.com/onsi/gomega v1.27.4/go.mod h1:riYq/GJKh8hhoM01HN6Vmuy93AarCXCBGpvFDK3q3fQ= github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= -github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= -github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= +github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= +github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= @@ -1135,16 +1133,16 @@ github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrb github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= -github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= -github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= +github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= -github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +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.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= @@ -1152,8 +1150,8 @@ github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+ github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/common v0.51.0 h1:vT5R9NAlW4V6k8Wruk7ikrHaHRsrPbduM/cKTOdQM/k= -github.com/prometheus/common v0.51.0/go.mod h1:wHFBCEVWVmHMUpg7pYcOm2QUR/ocQdYSJVQJKnHc3xQ= +github.com/prometheus/common v0.54.0 h1:ZlZy0BgJhTwVZUn7dLOkwCZHUkrAqd3WYtcFCWnM1D8= +github.com/prometheus/common v0.54.0/go.mod h1:/TQgMJP5CuVYveyT7n/0Ix8yLNNXy9yRSkhnLTHPDIQ= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= @@ -1163,8 +1161,8 @@ github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= -github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o= -github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g= +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/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -1197,8 +1195,8 @@ github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= 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= @@ -1219,6 +1217,12 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/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/xhit/go-str2duration v1.2.0/go.mod h1:3cPSlfZlUHVlneIVfePFWcJZsuwf+P1v2SRTV4cUmp4= github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1283,15 +1287,15 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1307,8 +1311,8 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= -golang.org/x/exp v0.0.0-20240318143956-a85f2c67cd81 h1:6R2FC06FonbXQ8pK11/PDFY6N6LWlf9KlzibaCapmqc= -golang.org/x/exp v0.0.0-20240318143956-a85f2c67cd81/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -1354,8 +1358,8 @@ golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1422,8 +1426,8 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1453,8 +1457,8 @@ golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= -golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= -golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1571,8 +1575,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1584,8 +1588,8 @@ golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1603,8 +1607,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1685,8 +1689,8 @@ golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= -golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= -golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= +golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= 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= @@ -1904,8 +1908,8 @@ google.golang.org/genproto v0.0.0-20230525234025-438c736192d0/go.mod h1:9ExIQyXL google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= google.golang.org/genproto/googleapis/api v0.0.0-20230525234020-1aefcd67740a/go.mod h1:ts19tUU+Z0ZShN1y3aPyq2+O3d5FUNNgT6FtOzmrNn8= google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8 h1:8eadJkXbwDEMNwcB5O0s5Y5eCfyuCLdvaiOIaGTrWmQ= -google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= +google.golang.org/genproto/googleapis/api v0.0.0-20240617180043-68d350f18fd4 h1:MuYw1wJzT+ZkybKfaOXKp5hJiZDn2iHaXRw0mRYdHSc= +google.golang.org/genproto/googleapis/api v0.0.0-20240617180043-68d350f18fd4/go.mod h1:px9SlOOZBg1wM1zdnr8jEL4CNGUBZ+ZKYtNPApNQc4c= google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234015-3fc162c6f38a/go.mod h1:xURIpW9ES5+/GZhnV6beoEtxQrnkRGIfP5VQG2tCBLc= google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -1965,8 +1969,8 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1992,6 +1996,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 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.11.1 h1:cmL9fFohOoNQf+wnp2Wa0OhNFH0KFnSzEkVxi3fcc3I= +helm.sh/helm/v3 v3.11.1/go.mod h1:z/Bu/BylToGno/6dtNGuSmjRqxKq5gaH+FU0BPO+AQ8= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -2000,21 +2006,21 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -istio.io/api v0.0.0-20230217221049-9d422bf48675 h1:dxHqYbJwurfq+x2OOG4WP+NkbyjURgcP9PQTsxh7HXM= -istio.io/api v0.0.0-20230217221049-9d422bf48675/go.mod h1:owGDRg9uqMob8CN1gxaOzk6nJxnbT8wrP7PmggpJHHY= -istio.io/client-go v1.17.1 h1:W0kQXYCzIluA/20zLzxeNF7bNMJXXArmGYRt/MIg2io= -istio.io/client-go v1.17.1/go.mod h1:mLTRYYFxHctzUbt8Iclgj+Sueq34+qC2ZEJTn6BxRuE= +istio.io/api v1.19.2-0.20231011000955-f3015ebb5bd4 h1:NoiArVONh9DPs/DovhCCl771BUeEkKp+/GhsRB1YbOk= +istio.io/api v1.19.2-0.20231011000955-f3015ebb5bd4/go.mod h1:KstZe4bKbXouALUJ5PqpjNEhu5nj90HrDFitZfpNhlU= +istio.io/client-go v1.19.3 h1:nxNcBhtpJJmSoiTbCzO4Ay4Y1qve4Uct6oiqPSJVNMg= +istio.io/client-go v1.19.3/go.mod h1:ra3fVlXcquh7EuQnNssuLxfp6lFv/nx5314PvNEzOUs= k8s.io/api v0.28.3 h1:Gj1HtbSdB4P08C8rs9AR94MfSGpRhJgsS+GF9V26xMM= k8s.io/api v0.28.3/go.mod h1:MRCV/jr1dW87/qJnZ57U5Pak65LGmQVkKTzf3AtKFHc= k8s.io/apiextensions-apiserver v0.28.3 h1:Od7DEnhXHnHPZG+W9I97/fSQkVpVPQx2diy+2EtmY08= k8s.io/apiextensions-apiserver v0.28.3/go.mod h1:NE1XJZ4On0hS11aWWJUTNkmVB03j9LM7gJSisbRt8Lc= k8s.io/apimachinery v0.28.3 h1:B1wYx8txOaCQG0HmYF6nbpU8dg6HvA06x5tEffvOe7A= k8s.io/apimachinery v0.28.3/go.mod h1:uQTKmIqs+rAYaq+DFaoD2X7pcjLOqbQX2AOiO0nIpb8= -k8s.io/apiserver v0.28.3 h1:8Ov47O1cMyeDzTXz0rwcfIIGAP/dP7L8rWbEljRcg5w= -k8s.io/apiserver v0.28.3/go.mod h1:YIpM+9wngNAv8Ctt0rHG4vQuX/I5rvkEMtZtsxW2rNM= +k8s.io/apiserver v0.28.9 h1:koPXvgSXRBDxKJQjJGdZNgPsT9lQv6scJJFipd1m86E= +k8s.io/apiserver v0.28.9/go.mod h1:D51I37WBZojJhmLcjNVE4GSVrjiUHP+yq+N5KvKn2wY= k8s.io/autoscaler/vertical-pod-autoscaler v0.9.0/go.mod h1:PwWTGRRCxefhAezrDbG/tRYSAW7etHjjMPAr8fXKVAA= -k8s.io/autoscaler/vertical-pod-autoscaler v0.14.0 h1:HkQHkcuwVP3BgJpVqTGeYHro83qGBj8mWotygHZND1k= -k8s.io/autoscaler/vertical-pod-autoscaler v0.14.0/go.mod h1:w6/LjLR3DPQd57vlgvgbpzpuJKsCiily0+OzQI+nyfI= +k8s.io/autoscaler/vertical-pod-autoscaler v1.0.0 h1:y0TgWoHaeYEv3L1MfLC+D2WVxyN1fGr6axURHXq+wHE= +k8s.io/autoscaler/vertical-pod-autoscaler v1.0.0/go.mod h1:w6/LjLR3DPQd57vlgvgbpzpuJKsCiily0+OzQI+nyfI= k8s.io/client-go v0.28.3 h1:2OqNb72ZuTZPKCl+4gTKvqao0AMOl9f3o2ijbAj3LI4= k8s.io/client-go v0.28.3/go.mod h1:LTykbBp9gsA7SwqirlCXBWtK0guzfhpoW4qSm7i9dxo= k8s.io/cluster-bootstrap v0.28.3 h1:hGK3mJsmVGGvRJ61nyQcYNR9g/IYax75TbJcylTmZts= @@ -2089,8 +2095,8 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8 rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/controller-runtime v0.16.5 h1:yr1cEJbX08xsTW6XEIzT13KHHmIyX8Umvme2cULvFZw= -sigs.k8s.io/controller-runtime v0.16.5/go.mod h1:j7bialYoSn142nv9sCOJmQgDXQXxnroFU4VnX/brVJ0= +sigs.k8s.io/controller-runtime v0.16.6 h1:FiXwTuFF5ZJKmozfP2Z0j7dh6kmxP4Ou1KLfxgKKC3I= +sigs.k8s.io/controller-runtime v0.16.6/go.mod h1:+dQzkZxnylD0u49e0a+7AR+vlibEBaThmPca7lTyUsI= sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20231015215740-bf15e44028f9 h1:O27fSMHw4u0h+Rj8bNzcZk5jY0iZCO0J8/mCpigpnbw= sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20231015215740-bf15e44028f9/go.mod h1:TF/lVLWS+JNNaVqJuDDictY2hZSXSsIHCx4FClMvqFg= sigs.k8s.io/controller-tools v0.13.0 h1:NfrvuZ4bxyolhDBt/rCZhDnx3M2hzlhgo5n3Iv2RykI= diff --git a/pkg/admission/cmd/options.go b/pkg/admission/cmd/options.go index 35732939e..4acfd7e6b 100644 --- a/pkg/admission/cmd/options.go +++ b/pkg/admission/cmd/options.go @@ -11,6 +11,7 @@ import ( func GardenWebhookSwitchOptions() *webhookcmd.SwitchOptions { return webhookcmd.NewSwitchOptions( webhookcmd.Switch(validator.Name, validator.New), + webhookcmd.Switch(validator.SecretsValidatorName, validator.NewSecretsWebhook), webhookcmd.Switch(mutator.Name, mutator.New), ) } diff --git a/pkg/admission/mutator/webhook.go b/pkg/admission/mutator/webhook.go index cc09e5aae..cbb85eb7b 100644 --- a/pkg/admission/mutator/webhook.go +++ b/pkg/admission/mutator/webhook.go @@ -5,6 +5,7 @@ import ( extensionswebhook "github.com/gardener/gardener/extensions/pkg/webhook" gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1" "github.com/metal-stack/gardener-extension-provider-metal/pkg/metal" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/manager" @@ -29,5 +30,9 @@ func New(mgr manager.Manager) (*extensionswebhook.Webhook, error) { Mutators: map[extensionswebhook.Mutator][]extensionswebhook.Type{ NewShootMutator(mgr): {{Obj: &gardencorev1beta1.Shoot{}}}, }, + Target: extensionswebhook.TargetSeed, + ObjectSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"provider.extensions.gardener.cloud/metal": "true"}, + }, }) } diff --git a/pkg/admission/validator/secretbinding.go b/pkg/admission/validator/secretbinding.go new file mode 100644 index 000000000..0f78def43 --- /dev/null +++ b/pkg/admission/validator/secretbinding.go @@ -0,0 +1,58 @@ +package validator + +import ( + "context" + "fmt" + + extensionswebhook "github.com/gardener/gardener/extensions/pkg/webhook" + "github.com/gardener/gardener/pkg/apis/core" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/manager" + + metalvalidation "github.com/metal-stack/gardener-extension-provider-metal/pkg/apis/metal/validation" +) + +type secretBinding struct { + apiReader client.Reader +} + +// NewSecretBindingValidator returns a new instance of a secret binding validator. +func NewSecretBindingValidator(mgr manager.Manager) extensionswebhook.Validator { + return &secretBinding{ + apiReader: mgr.GetAPIReader(), + } +} + +// Validate checks whether the given SecretBinding refers to a Secret with valid metal-api credentials. +func (sb *secretBinding) Validate(ctx context.Context, newObj, oldObj client.Object) error { + secretBinding, ok := newObj.(*core.SecretBinding) + if !ok { + return fmt.Errorf("wrong object type %T", newObj) + } + + if oldObj != nil { + oldSecretBinding, ok := oldObj.(*core.SecretBinding) + if !ok { + return fmt.Errorf("wrong object type %T for old object", oldObj) + } + + // If the provider type did not change, we exit early. + if oldSecretBinding.Provider != nil && equality.Semantic.DeepEqual(secretBinding.Provider.Type, oldSecretBinding.Provider.Type) { + return nil + } + } + + var ( + secret = &corev1.Secret{} + secretKey = client.ObjectKey{Namespace: secretBinding.SecretRef.Namespace, Name: secretBinding.SecretRef.Name} + ) + // Explicitly use the client.Reader to prevent controller-runtime to start Informer for Secrets + // under the hood. The latter increases the memory usage of the component. + if err := sb.apiReader.Get(ctx, secretKey, secret); err != nil { + return err + } + + return metalvalidation.ValidateCloudProviderSecret(secret) +} diff --git a/pkg/admission/validator/secrets.go b/pkg/admission/validator/secrets.go new file mode 100644 index 000000000..9f613b6d7 --- /dev/null +++ b/pkg/admission/validator/secrets.go @@ -0,0 +1,41 @@ +package validator + +import ( + "context" + "fmt" + + extensionswebhook "github.com/gardener/gardener/extensions/pkg/webhook" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" + "sigs.k8s.io/controller-runtime/pkg/client" + + metalvalidation "github.com/metal-stack/gardener-extension-provider-metal/pkg/apis/metal/validation" +) + +type secret struct{} + +// NewSecretValidator returns a new instance of a secret validator. +func NewSecretValidator() extensionswebhook.Validator { + return &secret{} +} + +// Validate checks whether the given new secret contains valid metal-api credentials. +func (s *secret) Validate(_ context.Context, newObj, oldObj client.Object) error { + secret, ok := newObj.(*corev1.Secret) + if !ok { + return fmt.Errorf("wrong object type %T", newObj) + } + + if oldObj != nil { + oldSecret, ok := oldObj.(*corev1.Secret) + if !ok { + return fmt.Errorf("wrong object type %T for old object", oldObj) + } + + if equality.Semantic.DeepEqual(secret.Data, oldSecret.Data) { + return nil + } + } + + return metalvalidation.ValidateCloudProviderSecret(secret) +} diff --git a/pkg/admission/validator/webhook.go b/pkg/admission/validator/webhook.go index 49814e384..dee618636 100644 --- a/pkg/admission/validator/webhook.go +++ b/pkg/admission/validator/webhook.go @@ -9,11 +9,16 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/predicate" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) const ( // Name is a name for a validation webhook. Name = "validator" + // SecretsValidatorName is the name of the secrets validator. + SecretsValidatorName = "secrets." + Name ) var logger = log.Log.WithName("metal-validator-webhook") @@ -28,8 +33,31 @@ func New(mgr manager.Manager) (*extensionswebhook.Webhook, error) { Path: "/webhooks/validate", Predicates: []predicate.Predicate{extensionspredicate.GardenCoreProviderType(metal.Type)}, Validators: map[extensionswebhook.Validator][]extensionswebhook.Type{ - NewShootValidator(mgr): {{Obj: &core.Shoot{}}}, - NewCloudProfileValidator(mgr): {{Obj: &core.CloudProfile{}}}, + NewShootValidator(mgr): {{Obj: &core.Shoot{}}}, + NewCloudProfileValidator(mgr): {{Obj: &core.CloudProfile{}}}, + NewSecretBindingValidator(mgr): {{Obj: &core.SecretBinding{}}}, + }, + Target: extensionswebhook.TargetSeed, + ObjectSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"provider.extensions.gardener.cloud/metal": "true"}, + }, + }) +} + +// NewSecretsWebhook creates a new validation webhook for Secrets. +func NewSecretsWebhook(mgr manager.Manager) (*extensionswebhook.Webhook, error) { + logger.Info("Setting up webhook", "name", SecretsValidatorName) + + return extensionswebhook.New(mgr, extensionswebhook.Args{ + Provider: metal.Type, + Name: SecretsValidatorName, + Path: "/webhooks/validate/secrets", + Validators: map[extensionswebhook.Validator][]extensionswebhook.Type{ + NewSecretValidator(): {{Obj: &corev1.Secret{}}}, + }, + Target: extensionswebhook.TargetSeed, + ObjectSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"provider.shoot.gardener.cloud/metal": "true"}, }, }) } diff --git a/pkg/apis/metal/types_cloudprofile.go b/pkg/apis/metal/types_cloudprofile.go index 9c315f5e6..ed3cf5245 100644 --- a/pkg/apis/metal/types_cloudprofile.go +++ b/pkg/apis/metal/types_cloudprofile.go @@ -75,7 +75,6 @@ type Partition struct { // NetworkIsolation defines configuration for restricted or forbidden clusters. type NetworkIsolation struct { // AllowedNetworks is a list of networks which are allowed to connect in restricted or forbidden NetworkIsolated clusters. - // if empty all destinations are allowed. AllowedNetworks AllowedNetworks // DNSServers DNSServers []string diff --git a/pkg/apis/metal/validation/cloudprofile.go b/pkg/apis/metal/validation/cloudprofile.go index bd183079e..6acb1372d 100644 --- a/pkg/apis/metal/validation/cloudprofile.go +++ b/pkg/apis/metal/validation/cloudprofile.go @@ -52,76 +52,129 @@ func ValidateCloudProfileConfig(cloudProfileConfig *apismetal.CloudProfileConfig networkIsolationField := mcpField.Child(partitionName, "networkIsolation") - if len(partition.NetworkIsolation.DNSServers) > 3 { - dnsField := networkIsolationField.Child("dnsServers") - allErrs = append(allErrs, field.Invalid(dnsField, partition.NetworkIsolation.DNSServers, "only up to 3 dns servers are allowed")) - } - for index, ip := range partition.NetworkIsolation.DNSServers { - ipField := networkIsolationField.Child("dnsServers").Index(index) - if _, err := netip.ParseAddr(ip); err != nil { - allErrs = append(allErrs, field.Invalid(ipField, ip, "invalid ip address")) - } - } - for index, ip := range partition.NetworkIsolation.NTPServers { - ipField := networkIsolationField.Child("ntpServers").Index(index) - if _, err := netip.ParseAddr(ip); err != nil { - allErrs = append(allErrs, field.Invalid(ipField, ip, "invalid ip address")) - } - } - for index, cidr := range partition.NetworkIsolation.AllowedNetworks.Egress { - ipField := networkIsolationField.Child("allowedNetworks", "egress").Index(index) - if _, err := netip.ParsePrefix(cidr); err != nil { - allErrs = append(allErrs, field.Invalid(ipField, cidr, "invalid cidr")) - } - } - for index, cidr := range partition.NetworkIsolation.AllowedNetworks.Ingress { - ipField := networkIsolationField.Child("allowedNetworks", "ingress").Index(index) - if _, err := netip.ParsePrefix(cidr); err != nil { - allErrs = append(allErrs, field.Invalid(ipField, cidr, "invalid cidr")) - } - } + dnsServers := partition.NetworkIsolation.DNSServers + dnsServersField := networkIsolationField.Child("dnsServers") + allErrs = append(allErrs, validateDNSServers(dnsServers, dnsServersField)...) - for mirrIndex, mirr := range partition.NetworkIsolation.RegistryMirrors { - mirrorField := networkIsolationField.Child("registryMirrors").Index(mirrIndex) - if mirr.Name == "" { - allErrs = append(allErrs, field.Invalid(mirrorField.Child("name"), mirr.Name, "name of mirror may not be empty")) - } - endpointUrl, err := url.Parse(mirr.Endpoint) - if err != nil { - allErrs = append(allErrs, field.Invalid(mirrorField.Child("endpoint"), mirr.Endpoint, "not a valid url")) - } else if endpointUrl.Scheme != "http" && endpointUrl.Scheme != "https" { - allErrs = append(allErrs, field.Invalid(mirrorField.Child("endpoint"), mirr.Endpoint, "url must have the scheme http/s")) - } - if _, err := netip.ParseAddr(mirr.IP); err != nil { - allErrs = append(allErrs, field.Invalid(mirrorField.Child("ip"), mirr.IP, "invalid ip address")) - } - if mirr.Port == 0 { - allErrs = append(allErrs, field.Invalid(mirrorField.Child("port"), mirr.Port, "must be a valid port")) - } - if len(mirr.MirrorOf) == 0 { - allErrs = append(allErrs, field.Invalid(mirrorField.Child("mirrorOf"), mirr.MirrorOf, "registry mirror must replace existing registries")) - } + ntpServers := partition.NetworkIsolation.NTPServers + ntpServersField := networkIsolationField.Child("ntpServers") + allErrs = append(allErrs, validateNTPServers(ntpServers, ntpServersField)...) - for regIndex, reg := range mirr.MirrorOf { - regField := mirrorField.Child("mirrorOf").Index(regIndex) - if reg == "" { - allErrs = append(allErrs, field.Invalid(regField, reg, "cannot be empty")) - } - regUrl, err := url.Parse("https://" + reg + "/") - if err != nil { - allErrs = append(allErrs, field.Invalid(regField, reg, "invalid registry")) - } - if regUrl.Host != reg { - allErrs = append(allErrs, field.Invalid(regField, reg, "not a valid registry host")) - } - } - } + allowedNetworks := partition.NetworkIsolation.AllowedNetworks + allowedNetworksField := networkIsolationField.Child("allowedNetworks") + allErrs = append(allErrs, validateAllowedNetworks(allowedNetworksField, allowedNetworks)...) + + registryMirrors := partition.NetworkIsolation.RegistryMirrors + registryMirrorsField := networkIsolationField.Child("registryMirrors") + allErrs = append(allErrs, validateRegistryMirrors(registryMirrors, registryMirrorsField)...) } } return allErrs } +func validateDNSServers(dnsServers []string, dnsField *field.Path) field.ErrorList { + errs := field.ErrorList{} + if len(dnsServers) == 0 { + errs = append(errs, field.Invalid(dnsField, dnsServers, "may not be empty")) + } + if len(dnsServers) > 3 { + errs = append(errs, field.Invalid(dnsField, dnsServers, "only up to 3 dns servers are allowed")) + } + for index, ip := range dnsServers { + ipField := dnsField.Index(index) + if _, err := netip.ParseAddr(ip); err != nil { + errs = append(errs, field.Invalid(ipField, ip, "invalid ip address")) + } + } + return errs +} + +func validateNTPServers(ntpServers []string, ntpField *field.Path) field.ErrorList { + errs := field.ErrorList{} + if len(ntpServers) == 0 { + errs = append(errs, field.Invalid(ntpField, ntpServers, "may not be empty")) + } + for index, ip := range ntpServers { + ipField := ntpField.Index(index) + if _, err := netip.ParseAddr(ip); err != nil { + errs = append(errs, field.Invalid(ipField, ip, "invalid ip address")) + } + } + return errs +} + +func validateAllowedNetworks(allowedNetworksField *field.Path, allowedNetworks apismetal.AllowedNetworks) field.ErrorList { + errs := field.ErrorList{} + + egress := allowedNetworks.Egress + egressField := allowedNetworksField.Child("egress") + if len(egress) == 0 { + errs = append(errs, field.Invalid(egressField, egress, "may not be empty")) + } + for index, cidr := range egress { + ipField := egressField.Index(index) + if _, err := netip.ParsePrefix(cidr); err != nil { + errs = append(errs, field.Invalid(ipField, cidr, "invalid cidr")) + } + } + ingress := allowedNetworks.Ingress + ingressField := allowedNetworksField.Child("ingress") + if len(ingress) == 0 { + errs = append(errs, field.Invalid(ingressField, ingress, "may not be empty")) + } + for index, cidr := range ingress { + ipField := ingressField.Index(index) + if _, err := netip.ParsePrefix(cidr); err != nil { + errs = append(errs, field.Invalid(ipField, cidr, "invalid cidr")) + } + } + return errs +} + +func validateRegistryMirrors(registryMirrors []apismetal.RegistryMirror, registryMirrorsField *field.Path) field.ErrorList { + errs := field.ErrorList{} + if len(registryMirrors) == 0 { + errs = append(errs, field.Invalid(registryMirrorsField, registryMirrors, "may not be empty")) + } + for mirrIndex, mirr := range registryMirrors { + mirrorField := registryMirrorsField.Index(mirrIndex) + if mirr.Name == "" { + errs = append(errs, field.Invalid(mirrorField.Child("name"), mirr.Name, "name of mirror may not be empty")) + } + endpointUrl, err := url.Parse(mirr.Endpoint) + if err != nil { + errs = append(errs, field.Invalid(mirrorField.Child("endpoint"), mirr.Endpoint, "not a valid url")) + } else if endpointUrl.Scheme != "http" && endpointUrl.Scheme != "https" { + errs = append(errs, field.Invalid(mirrorField.Child("endpoint"), mirr.Endpoint, "url must have the scheme http/s")) + } + if _, err := netip.ParseAddr(mirr.IP); err != nil { + errs = append(errs, field.Invalid(mirrorField.Child("ip"), mirr.IP, "invalid ip address")) + } + if mirr.Port == 0 { + errs = append(errs, field.Invalid(mirrorField.Child("port"), mirr.Port, "must be a valid port")) + } + if len(mirr.MirrorOf) == 0 { + errs = append(errs, field.Invalid(mirrorField.Child("mirrorOf"), mirr.MirrorOf, "registry mirror must replace existing registries")) + } + + for regIndex, reg := range mirr.MirrorOf { + regField := mirrorField.Child("mirrorOf").Index(regIndex) + if reg == "" { + errs = append(errs, field.Invalid(regField, reg, "cannot be empty")) + } + regUrl, err := url.Parse("https://" + reg + "/") + if err != nil { + errs = append(errs, field.Invalid(regField, reg, "invalid registry")) + } + if regUrl.Host != reg { + errs = append(errs, field.Invalid(regField, reg, "not a valid registry host")) + } + } + } + return errs +} + func ValidateImmutableCloudProfileConfig( newCloudProfileConfig *apismetal.CloudProfileConfig, oldCloudProfileConfig *apismetal.CloudProfileConfig, diff --git a/pkg/apis/metal/validation/cloudprofile_test.go b/pkg/apis/metal/validation/cloudprofile_test.go index efb6ae7fb..0c1ea994c 100644 --- a/pkg/apis/metal/validation/cloudprofile_test.go +++ b/pkg/apis/metal/validation/cloudprofile_test.go @@ -125,6 +125,67 @@ var _ = Describe("CloudProfileConfig validation", func() { Expect(errorList).To(BeEmpty()) }) + It("should pass with missing network isolation", func() { + cloudProfileConfig.MetalControlPlanes = map[string]apismetal.MetalControlPlane{ + "prod": { + Partitions: map[string]apismetal.Partition{ + "partition-b": {}, + }, + }, + } + + errorList := ValidateCloudProfileConfig(cloudProfileConfig, cloudProfile, path) + + Expect(errorList).To(BeEmpty()) + }) + + It("should fail with network isolation with empty values", func() { + cloudProfileConfig.MetalControlPlanes = map[string]apismetal.MetalControlPlane{ + "prod": { + Partitions: map[string]apismetal.Partition{ + "partition-b": { + NetworkIsolation: &apismetal.NetworkIsolation{}, + }, + }, + }, + } + + errorList := ValidateCloudProfileConfig(cloudProfileConfig, cloudProfile, path) + + Expect(errorList).To(ConsistOf( + PointTo(MatchFields(IgnoreExtras, Fields{ + "Type": Equal(field.ErrorTypeInvalid), + "Field": Equal("test.metalControlPlanes.prod.partition-b.networkIsolation.dnsServers"), + "BadValue": HaveLen(0), + "Detail": Equal("may not be empty"), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "Type": Equal(field.ErrorTypeInvalid), + "Field": Equal("test.metalControlPlanes.prod.partition-b.networkIsolation.ntpServers"), + "BadValue": HaveLen(0), + "Detail": Equal("may not be empty"), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "Type": Equal(field.ErrorTypeInvalid), + "Field": Equal("test.metalControlPlanes.prod.partition-b.networkIsolation.registryMirrors"), + "BadValue": HaveLen(0), + "Detail": Equal("may not be empty"), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "Type": Equal(field.ErrorTypeInvalid), + "Field": Equal("test.metalControlPlanes.prod.partition-b.networkIsolation.allowedNetworks.egress"), + "BadValue": HaveLen(0), + "Detail": Equal("may not be empty"), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "Type": Equal(field.ErrorTypeInvalid), + "Field": Equal("test.metalControlPlanes.prod.partition-b.networkIsolation.allowedNetworks.ingress"), + "BadValue": HaveLen(0), + "Detail": Equal("may not be empty"), + })), + )) + }) + It("should allow up to 3 dns servers", func() { cloudProfileConfig.MetalControlPlanes = map[string]apismetal.MetalControlPlane{ "prod": { @@ -166,24 +227,7 @@ var _ = Describe("CloudProfileConfig validation", func() { Partitions: map[string]apismetal.Partition{ "partition-b": { NetworkIsolation: &apismetal.NetworkIsolation{ - AllowedNetworks: apismetal.AllowedNetworks{ - Ingress: []string{"10.0.0.1/24"}, - Egress: []string{"100.0.0.1/24"}, - }, DNSServers: []string{"1.1.1.1", "1.0.0.1", "8.8.8.8", "8.8.4.4"}, - NTPServers: []string{"134.60.1.27", "134.60.111.110"}, - RegistryMirrors: []apismetal.RegistryMirror{ - { - Name: "metal-stack registry", - Endpoint: "https://some.registry", - IP: "1.2.3.4", - Port: 443, - MirrorOf: []string{ - "ghcr.io", - "quay.io", - }, - }, - }, }, }, }, @@ -192,7 +236,7 @@ var _ = Describe("CloudProfileConfig validation", func() { errorList := ValidateCloudProfileConfig(cloudProfileConfig, cloudProfile, path) - Expect(errorList).To(ConsistOf( + Expect(errorList).To(ContainElement( PointTo(MatchFields(IgnoreExtras, Fields{ "Type": Equal(field.ErrorTypeInvalid), "Field": Equal("test.metalControlPlanes.prod.partition-b.networkIsolation.dnsServers"), @@ -202,18 +246,12 @@ var _ = Describe("CloudProfileConfig validation", func() { )) }) - It("should prevent partitions with empty network isolation registry mirror", func() { + It("should prevent registry mirrors with empty values", func() { cloudProfileConfig.MetalControlPlanes = map[string]apismetal.MetalControlPlane{ "prod": { Partitions: map[string]apismetal.Partition{ "partition-b": { NetworkIsolation: &apismetal.NetworkIsolation{ - AllowedNetworks: apismetal.AllowedNetworks{ - Ingress: []string{"10.0.0.1/24"}, - Egress: []string{"100.0.0.1/24"}, - }, - DNSServers: []string{"1.1.1.1", "1.0.0.1"}, - NTPServers: []string{"134.60.1.27", "134.60.111.110"}, RegistryMirrors: []apismetal.RegistryMirror{ { Name: "", @@ -231,7 +269,7 @@ var _ = Describe("CloudProfileConfig validation", func() { errorList := ValidateCloudProfileConfig(cloudProfileConfig, cloudProfile, path) - Expect(errorList).To(ConsistOf( + Expect(errorList).To(ContainElements( PointTo(MatchFields(IgnoreExtras, Fields{ "Type": Equal(field.ErrorTypeInvalid), "Field": Equal("test.metalControlPlanes.prod.partition-b.networkIsolation.registryMirrors[0].name"), @@ -265,7 +303,7 @@ var _ = Describe("CloudProfileConfig validation", func() { )) }) - It("should prevent partitions with invalid network isolation", func() { + It("should prevent partition with invalid network isolation", func() { cloudProfileConfig.MetalControlPlanes = map[string]apismetal.MetalControlPlane{ "prod": { Partitions: map[string]apismetal.Partition{ diff --git a/pkg/apis/metal/validation/network_access.go b/pkg/apis/metal/validation/network_access.go index 45fc65ace..fd1831c93 100644 --- a/pkg/apis/metal/validation/network_access.go +++ b/pkg/apis/metal/validation/network_access.go @@ -32,46 +32,9 @@ func validateNetworkAccessFields(controlPlaneConfig *apismetal.ControlPlaneConfi if partition.NetworkIsolation == nil { allErrs = append(allErrs, - field.Invalid(natPath, controlPlaneConfig.NetworkAccessType, "network access type requires partition's networkAccess to be set"), + field.Invalid(natPath, controlPlaneConfig.NetworkAccessType, "network access type requires partition's networkIsolation to be set"), field.Required(partNiPath, "network isolation required if control plane config networkAccess is not baseline"), ) - return allErrs - } - - if len(partition.NetworkIsolation.DNSServers) == 0 { - allErrs = append(allErrs, field.Invalid( - partNiPath.Child("dnsServers"), - partition.NetworkIsolation.DNSServers, - "may not be empty", - )) - } - if len(partition.NetworkIsolation.NTPServers) == 0 { - allErrs = append(allErrs, field.Invalid( - partNiPath.Child("ntpServers"), - partition.NetworkIsolation.NTPServers, - "may not be empty", - )) - } - if len(partition.NetworkIsolation.RegistryMirrors) == 0 { - allErrs = append(allErrs, field.Invalid( - partNiPath.Child("registryMirrors"), - partition.NetworkIsolation.RegistryMirrors, - "may not be empty", - )) - } - if len(partition.NetworkIsolation.AllowedNetworks.Egress) == 0 { - allErrs = append(allErrs, field.Invalid( - partNiPath.Child("allowedNetworks", "egress"), - partition.NetworkIsolation.AllowedNetworks.Egress, - "may not be empty", - )) - } - if len(partition.NetworkIsolation.AllowedNetworks.Ingress) == 0 { - allErrs = append(allErrs, field.Invalid( - partNiPath.Child("allowedNetworks", "ingress"), - partition.NetworkIsolation.AllowedNetworks.Ingress, - "may not be empty", - )) } return allErrs diff --git a/pkg/apis/metal/validation/network_access_test.go b/pkg/apis/metal/validation/network_access_test.go index 67b67cd85..2a830ed24 100644 --- a/pkg/apis/metal/validation/network_access_test.go +++ b/pkg/apis/metal/validation/network_access_test.go @@ -80,7 +80,7 @@ var _ = Describe("CloudProfileConfig validation", func() { "Type": Equal(field.ErrorTypeInvalid), "Field": Equal("test.networkAccessType"), "BadValue": PointTo(Equal(apismetal.NetworkAccessForbidden)), - "Detail": Equal("network access type requires partition's networkAccess to be set"), + "Detail": Equal("network access type requires partition's networkIsolation to be set"), })), PointTo(MatchFields(IgnoreExtras, Fields{ "Type": Equal(field.ErrorTypeRequired), @@ -125,53 +125,6 @@ var _ = Describe("CloudProfileConfig validation", func() { Expect(errorList).To(BeEmpty()) }) - - It("should fail with empty network isolation", func() { - cloudProfileConfig.MetalControlPlanes = map[string]apismetal.MetalControlPlane{ - "prod": { - Partitions: map[string]apismetal.Partition{ - "partition-b": { - NetworkIsolation: &apismetal.NetworkIsolation{}, - }, - }, - }, - } - - errorList := ValidateControlPlaneConfigNetworkAccess(controlPlaneConfig, cloudProfileConfig, partitionName, path) - - Expect(errorList).To(ConsistOf( - PointTo(MatchFields(IgnoreExtras, Fields{ - "Type": Equal(field.ErrorTypeInvalid), - "Field": Equal("test.metalControlPlanes[prod].partitions[partition-b].networkIsolation.dnsServers"), - "BadValue": HaveLen(0), - "Detail": Equal("may not be empty"), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "Type": Equal(field.ErrorTypeInvalid), - "Field": Equal("test.metalControlPlanes[prod].partitions[partition-b].networkIsolation.ntpServers"), - "BadValue": HaveLen(0), - "Detail": Equal("may not be empty"), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "Type": Equal(field.ErrorTypeInvalid), - "Field": Equal("test.metalControlPlanes[prod].partitions[partition-b].networkIsolation.registryMirrors"), - "BadValue": HaveLen(0), - "Detail": Equal("may not be empty"), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "Type": Equal(field.ErrorTypeInvalid), - "Field": Equal("test.metalControlPlanes[prod].partitions[partition-b].networkIsolation.allowedNetworks.egress"), - "BadValue": HaveLen(0), - "Detail": Equal("may not be empty"), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "Type": Equal(field.ErrorTypeInvalid), - "Field": Equal("test.metalControlPlanes[prod].partitions[partition-b].networkIsolation.allowedNetworks.ingress"), - "BadValue": HaveLen(0), - "Detail": Equal("may not be empty"), - })), - )) - }) }) Describe("with network access type restricted", func() { @@ -195,7 +148,7 @@ var _ = Describe("CloudProfileConfig validation", func() { "Type": Equal(field.ErrorTypeInvalid), "Field": Equal("test.networkAccessType"), "BadValue": PointTo(Equal(apismetal.NetworkAccessRestricted)), - "Detail": Equal("network access type requires partition's networkAccess to be set"), + "Detail": Equal("network access type requires partition's networkIsolation to be set"), })), PointTo(MatchFields(IgnoreExtras, Fields{ "Type": Equal(field.ErrorTypeRequired), @@ -240,53 +193,6 @@ var _ = Describe("CloudProfileConfig validation", func() { Expect(errorList).To(BeEmpty()) }) - - It("should fail with empty network isolation", func() { - cloudProfileConfig.MetalControlPlanes = map[string]apismetal.MetalControlPlane{ - "prod": { - Partitions: map[string]apismetal.Partition{ - "partition-b": { - NetworkIsolation: &apismetal.NetworkIsolation{}, - }, - }, - }, - } - - errorList := ValidateControlPlaneConfigNetworkAccess(controlPlaneConfig, cloudProfileConfig, partitionName, path) - - Expect(errorList).To(ConsistOf( - PointTo(MatchFields(IgnoreExtras, Fields{ - "Type": Equal(field.ErrorTypeInvalid), - "Field": Equal("test.metalControlPlanes[prod].partitions[partition-b].networkIsolation.dnsServers"), - "BadValue": HaveLen(0), - "Detail": Equal("may not be empty"), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "Type": Equal(field.ErrorTypeInvalid), - "Field": Equal("test.metalControlPlanes[prod].partitions[partition-b].networkIsolation.ntpServers"), - "BadValue": HaveLen(0), - "Detail": Equal("may not be empty"), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "Type": Equal(field.ErrorTypeInvalid), - "Field": Equal("test.metalControlPlanes[prod].partitions[partition-b].networkIsolation.registryMirrors"), - "BadValue": HaveLen(0), - "Detail": Equal("may not be empty"), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "Type": Equal(field.ErrorTypeInvalid), - "Field": Equal("test.metalControlPlanes[prod].partitions[partition-b].networkIsolation.allowedNetworks.egress"), - "BadValue": HaveLen(0), - "Detail": Equal("may not be empty"), - })), - PointTo(MatchFields(IgnoreExtras, Fields{ - "Type": Equal(field.ErrorTypeInvalid), - "Field": Equal("test.metalControlPlanes[prod].partitions[partition-b].networkIsolation.allowedNetworks.ingress"), - "BadValue": HaveLen(0), - "Detail": Equal("may not be empty"), - })), - )) - }) }) }) }) diff --git a/pkg/apis/metal/validation/secrets.go b/pkg/apis/metal/validation/secrets.go new file mode 100644 index 000000000..5d69af76f --- /dev/null +++ b/pkg/apis/metal/validation/secrets.go @@ -0,0 +1,26 @@ +package validation + +import ( + "fmt" + + corev1 "k8s.io/api/core/v1" + + "github.com/metal-stack/gardener-extension-provider-metal/pkg/metal" +) + +// ValidateCloudProviderSecret checks whether the given secret contains a valid metal-api credentials. +func ValidateCloudProviderSecret(secret *corev1.Secret) error { + creds, err := metal.ReadCredentialsSecret(secret) + if err != nil { + return fmt.Errorf("unable to read credentials secret: %w", err) + } + + if creds.MetalAPIHMac != "" && creds.MetalAPIKey != "" { + return fmt.Errorf("either hmac or api key must be set, not both") + } + if creds.MetalAPIHMac == "" && creds.MetalAPIKey == "" { + return fmt.Errorf("either hmac or api key must be set") + } + + return nil +} diff --git a/pkg/controller/infrastructure/actuator_reconcile.go b/pkg/controller/infrastructure/actuator_reconcile.go index a10d67027..2d01e4af9 100644 --- a/pkg/controller/infrastructure/actuator_reconcile.go +++ b/pkg/controller/infrastructure/actuator_reconcile.go @@ -121,7 +121,7 @@ func (a *actuator) maintainFirewallDeployment(ctx context.Context, logger logr.L // so it cannot be put to the worker controller. if !gardener.EffectiveShootMaintenanceTimeWindow(cluster.Shoot).Contains(time.Now()) { - // note that this prevents updating the firewall image even when annotating the shoot explicitly with the maintainenance annotation + // note that this prevents updating the firewall image even when annotating the shoot explicitly with the maintenance annotation // if a user wants to update the firewall immediately he needs to specify the new firewall image in the spec logger.Info("not maintaining firewall deployment as shoot not in effective maintenance time window") return nil diff --git a/pkg/controller/worker/firewall_reconcile.go b/pkg/controller/worker/firewall_reconcile.go index 4d05412a6..ed6eaebad 100644 --- a/pkg/controller/worker/firewall_reconcile.go +++ b/pkg/controller/worker/firewall_reconcile.go @@ -14,6 +14,7 @@ import ( "github.com/metal-stack/gardener-extension-provider-metal/pkg/apis/metal/helper" "github.com/metal-stack/gardener-extension-provider-metal/pkg/apis/metal/validation" "github.com/metal-stack/gardener-extension-provider-metal/pkg/metal" + metalcommon "github.com/metal-stack/metal-lib/pkg/metal" "github.com/metal-stack/metal-lib/pkg/tag" admissionregistrationv1 "k8s.io/api/admissionregistration/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -132,7 +133,17 @@ func (a *actuator) ensureFirewallDeployment(ctx context.Context, log logr.Logger deploy.Spec.Template.Labels[tag.ClusterID] = clusterID deploy.Spec.Template.Spec.Size = d.infrastructureConfig.Firewall.Size - deploy.Spec.Template.Spec.Image = d.infrastructureConfig.Firewall.Image + if deploy.Spec.AutoUpdate.MachineImage && d.infrastructureConfig.Firewall.Image != "" { + isPatch, err := patchUpdate(deploy.Spec.Template.Spec.Image, d.infrastructureConfig.Firewall.Image) + if err != nil { + return err + } + if !isPatch { + deploy.Spec.Template.Spec.Image = d.infrastructureConfig.Firewall.Image + } + } else { + deploy.Spec.Template.Spec.Image = d.infrastructureConfig.Firewall.Image + } deploy.Spec.Template.Spec.Networks = append(d.infrastructureConfig.Firewall.Networks, d.privateNetworkID) deploy.Spec.Template.Spec.RateLimits = mapRateLimits(d.infrastructureConfig.Firewall.RateLimits) deploy.Spec.Template.Spec.InternalPrefixes = a.controllerConfig.FirewallInternalPrefixes @@ -206,3 +217,21 @@ func mapEgressRules(egress []apismetal.EgressRule) []fcmv2.EgressRuleSNAT { } return result } + +func patchUpdate(old, new string) (bool, error) { + oldKind, o, err := metalcommon.GetOsAndSemverFromImage(old) + if err != nil { + return false, fmt.Errorf("unable to parse firewall image: %w", err) + } + + newKind, n, err := metalcommon.GetOsAndSemverFromImage(new) + if err != nil { + return false, fmt.Errorf("unable to parse firewall image: %w", err) + } + + if oldKind == newKind && o.Major() == n.Major() && o.Minor() == n.Minor() && o.Patch() != n.Patch() { + return true, nil + } + + return false, nil +} diff --git a/pkg/controller/worker/firewall_reconcile_test.go b/pkg/controller/worker/firewall_reconcile_test.go new file mode 100644 index 000000000..ec66dc2ac --- /dev/null +++ b/pkg/controller/worker/firewall_reconcile_test.go @@ -0,0 +1,80 @@ +package worker + +import ( + "github.com/google/go-cmp/cmp" + "github.com/metal-stack/metal-lib/pkg/testcommon" + + "testing" +) + +func Test_patchUpdate(t *testing.T) { + tests := []struct { + name string + old string + new string + want bool + wantErr error + }{ + { + name: "no update", + old: "firewall-ubuntu-3.0", + new: "firewall-ubuntu-3.0", + want: false, + wantErr: nil, + }, + { + name: "no update fully qualified", + old: "firewall-ubuntu-3.0.20240101", + new: "firewall-ubuntu-3.0.20240101", + want: false, + wantErr: nil, + }, + { + name: "patch update", + old: "firewall-ubuntu-3.0.20240101", + new: "firewall-ubuntu-3.0.20240201", + want: true, + wantErr: nil, + }, + { + name: "minor update", + old: "firewall-ubuntu-3.0.20240101", + new: "firewall-ubuntu-3.1.20240101", + want: false, + wantErr: nil, + }, + { + name: "major update", + old: "firewall-ubuntu-3.0.20240101", + new: "firewall-ubuntu-4.0.20240101", + want: false, + wantErr: nil, + }, + { + name: "os update", + old: "firewall-ubuntu-3.0.20240101", + new: "firewall-debian-3.0.20240101", + want: false, + wantErr: nil, + }, + { + name: "update to fully qualified", + old: "firewall-ubuntu-3.0", + new: "firewall-ubuntu-3.0.20240101", + want: true, + wantErr: nil, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := patchUpdate(tt.old, tt.new) + if diff := cmp.Diff(tt.wantErr, err, testcommon.ErrorStringComparer()); diff != "" { + t.Errorf("error diff (+got -want):\n %s", diff) + } + + if diff := cmp.Diff(got, tt.want, testcommon.StrFmtDateComparer()); diff != "" { + t.Errorf("diff (+got -want):\n %s", diff) + } + }) + } +}