From 8c432597d2ebecc9e592d861e3e6693401576fa7 Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Mon, 4 May 2026 23:07:30 +0200 Subject: [PATCH 01/25] controller Signed-off-by: Lukas Hoehl --- .../templates/deployment.yaml | 35 ++- .../templates/rbac.yaml | 11 + .../templates/secret.yaml | 30 ++ charts/gardener-extension-acl/values.yaml | 3 + .../envoyfilter/envoyfilter-api.yaml | 2 +- .../envoyfilter/envoyfilter-http-proxy.yaml | 4 +- .../envoyfilter/envoyfilter-ingress.yaml | 2 +- .../envoyfilter/envoyfilter-vpn.yaml | 4 +- charts/seed/values.yaml | 4 +- cmd/gardener-extension-acl/app/app.go | 9 + deploy/garden/rbac.yaml | 25 ++ pkg/controller/actuator.go | 291 +++++++++--------- pkg/controller/add.go | 60 +++- pkg/controller/allowedcidrs/allowedcidrs.go | 13 + pkg/controller/allowedcidrs/errors.go | 6 + pkg/controller/allowedcidrs/garden.go | 71 +++++ pkg/controller/allowedcidrs/shoot.go | 148 +++++++++ pkg/controller/healthcheck/add.go | 10 +- pkg/helper/seed.go | 9 + 19 files changed, 559 insertions(+), 178 deletions(-) create mode 100644 charts/gardener-extension-acl/templates/secret.yaml create mode 100644 deploy/garden/rbac.yaml create mode 100644 pkg/controller/allowedcidrs/allowedcidrs.go create mode 100644 pkg/controller/allowedcidrs/errors.go create mode 100644 pkg/controller/allowedcidrs/garden.go create mode 100644 pkg/controller/allowedcidrs/shoot.go diff --git a/charts/gardener-extension-acl/templates/deployment.yaml b/charts/gardener-extension-acl/templates/deployment.yaml index bee3e6aa..322e542d 100644 --- a/charts/gardener-extension-acl/templates/deployment.yaml +++ b/charts/gardener-extension-acl/templates/deployment.yaml @@ -22,9 +22,12 @@ spec: labels: networking.gardener.cloud/to-dns: allowed networking.gardener.cloud/to-runtime-apiserver: allowed + networking.resources.gardener.cloud/to-garden-virtual-garden-kube-apiserver-tcp-443: allowed {{ include "labels" . | indent 8 }} spec: - priorityClassName: gardener-system-900 + {{- if .Values.gardener.runtimeCluster.priorityClassName }} + priorityClassName: {{ .Values.gardener.runtimeCluster.priorityClassName }} + {{- end }} serviceAccountName: {{ include "name" . }} containers: - name: {{ include "name" . }} @@ -43,7 +46,16 @@ spec: {{- if .Values.gardener.version }} - --gardener-version={{ .Values.gardener.version }} {{- end }} + {{- if .Values.gardener.runtimeCluster.enabled }} + - --extension-classes=garden + {{- else }} + - --extension-classes=shoot + {{- end }} env: + {{- if .Values.gardener.runtimeCluster.enabled }} + - name: GARDEN_KUBECONFIG + value: /var/run/secrets/gardener.cloud/shoot/generic-kubeconfig/kubeconfig + {{- end }} - name: LEADER_ELECTION_NAMESPACE valueFrom: fieldRef: @@ -65,16 +77,33 @@ spec: runAsGroup: 65532 seccompProfile: type: RuntimeDefault - {{- if .Values.imageVectorOverwrite }} volumeMounts: + {{- if .Values.gardener.runtimeCluster.enabled }} + - name: kubeconfig + mountPath: /var/run/secrets/gardener.cloud/shoot/generic-kubeconfig + readOnly: true + {{- end }} + {{- if .Values.imageVectorOverwrite }} - name: extension-imagevector-overwrite mountPath: /charts_overwrite/ readOnly: true {{- end }} - {{- if .Values.imageVectorOverwrite }} volumes: + {{- if .Values.imageVectorOverwrite }} - name: extension-imagevector-overwrite configMap: name: {{ include "name" . }}-imagevector-overwrite defaultMode: 420 {{- end }} + {{- if .Values.gardener.runtimeCluster.enabled }} + - name: kubeconfig + projected: + defaultMode: 420 + sources: + - secret: + items: + - key: kubeconfig + path: kubeconfig + name: garden-kubeconfig + optional: false + {{- end }} diff --git a/charts/gardener-extension-acl/templates/rbac.yaml b/charts/gardener-extension-acl/templates/rbac.yaml index 6c855f21..eefe4223 100644 --- a/charts/gardener-extension-acl/templates/rbac.yaml +++ b/charts/gardener-extension-acl/templates/rbac.yaml @@ -18,6 +18,16 @@ rules: - delete resources: - envoyfilters +{{- if .Values.gardener.runtimeCluster.enabled }} +- apiGroups: + - operator.gardener.cloud + resources: + - gardens + verbs: + - get + - list + - watch +{{- else }} - apiGroups: - "" resources: @@ -36,6 +46,7 @@ rules: - get - list - watch +{{- end }} - apiGroups: - extensions.gardener.cloud resources: diff --git a/charts/gardener-extension-acl/templates/secret.yaml b/charts/gardener-extension-acl/templates/secret.yaml new file mode 100644 index 00000000..d912fd9f --- /dev/null +++ b/charts/gardener-extension-acl/templates/secret.yaml @@ -0,0 +1,30 @@ +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + annotations: + serviceaccount.resources.gardener.cloud/name: extension-acl + serviceaccount.resources.gardener.cloud/inject-ca-bundle: "true" + serviceaccount.resources.gardener.cloud/labels: '{"extension": "acl"}' + labels: + resources.gardener.cloud/class: garden + resources.gardener.cloud/purpose: token-requestor + name: garden-kubeconfig + namespace: {{ .Release.Namespace }} +stringData: + kubeconfig: | + apiVersion: v1 + clusters: + - cluster: + server: https://virtual-garden-kube-apiserver.garden.svc.cluster.local + name: default + contexts: + - context: + cluster: default + user: token + name: default + current-context: default + kind: Config + users: + - name: token + user: {} diff --git a/charts/gardener-extension-acl/values.yaml b/charts/gardener-extension-acl/values.yaml index b2aac4df..d06b944e 100644 --- a/charts/gardener-extension-acl/values.yaml +++ b/charts/gardener-extension-acl/values.yaml @@ -38,3 +38,6 @@ additionalAllowedCidrs: [] gardener: version: "" + runtimeCluster: + enabled: false + priorityClassName: "" diff --git a/charts/seed/templates/envoyfilter/envoyfilter-api.yaml b/charts/seed/templates/envoyfilter/envoyfilter-api.yaml index 532ce365..4e9972bb 100644 --- a/charts/seed/templates/envoyfilter/envoyfilter-api.yaml +++ b/charts/seed/templates/envoyfilter/envoyfilter-api.yaml @@ -1,7 +1,7 @@ apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: - name: acl-api-{{ .Values.shootName }} + name: acl-api-{{ .Values.suffix }} namespace: {{ .Values.targetNamespace }} labels: {{- include "gardener-extension.labels" . | nindent 4 }} diff --git a/charts/seed/templates/envoyfilter/envoyfilter-http-proxy.yaml b/charts/seed/templates/envoyfilter/envoyfilter-http-proxy.yaml index b0d469ff..76296239 100644 --- a/charts/seed/templates/envoyfilter/envoyfilter-http-proxy.yaml +++ b/charts/seed/templates/envoyfilter/envoyfilter-http-proxy.yaml @@ -1,8 +1,10 @@ +{{- if .Values.httpProxyEnvoyFilterSpec }} apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: - name: acl-http-proxy-{{ .Values.shootName }} + name: acl-http-proxy-{{ .Values.suffix }} namespace: {{ .Values.targetNamespace }} labels: {{- include "gardener-extension.labels" . | nindent 4 }} spec: {{- .Values.httpProxyEnvoyFilterSpec | toYaml | nindent 2 }} +{{- end }} diff --git a/charts/seed/templates/envoyfilter/envoyfilter-ingress.yaml b/charts/seed/templates/envoyfilter/envoyfilter-ingress.yaml index 819f9384..8b30e6c5 100644 --- a/charts/seed/templates/envoyfilter/envoyfilter-ingress.yaml +++ b/charts/seed/templates/envoyfilter/envoyfilter-ingress.yaml @@ -2,7 +2,7 @@ apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: - name: acl-ingress-{{ .Values.shootName }} + name: acl-ingress-{{ .Values.suffix }} namespace: istio-ingress labels: {{- include "gardener-extension.labels" . | nindent 4 }} diff --git a/charts/seed/templates/envoyfilter/envoyfilter-vpn.yaml b/charts/seed/templates/envoyfilter/envoyfilter-vpn.yaml index 2f75a4cd..84a7ead4 100644 --- a/charts/seed/templates/envoyfilter/envoyfilter-vpn.yaml +++ b/charts/seed/templates/envoyfilter/envoyfilter-vpn.yaml @@ -1,8 +1,10 @@ +{{- if .Values.vpnEnvoyFilterSpec }} apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: - name: acl-vpn-{{ .Values.shootName }} + name: acl-vpn-{{ .Values.suffix }} namespace: {{ .Values.targetNamespace }} labels: {{- include "gardener-extension.labels" . | nindent 4 }} spec: {{- .Values.vpnEnvoyFilterSpec | toYaml | nindent 2 }} +{{- end }} diff --git a/charts/seed/values.yaml b/charts/seed/values.yaml index f87f5c14..34b64dbf 100644 --- a/charts/seed/values.yaml +++ b/charts/seed/values.yaml @@ -1 +1,3 @@ -# TODO \ No newline at end of file +suffix: "" +targetNamespace: "" + diff --git a/cmd/gardener-extension-acl/app/app.go b/cmd/gardener-extension-acl/app/app.go index 725b3908..f9891459 100644 --- a/cmd/gardener-extension-acl/app/app.go +++ b/cmd/gardener-extension-acl/app/app.go @@ -22,6 +22,7 @@ import ( extensionscontroller "github.com/gardener/gardener/extensions/pkg/controller" "github.com/gardener/gardener/extensions/pkg/util" v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants" + operatorv1alpha1 "github.com/gardener/gardener/pkg/apis/operator/v1alpha1" "github.com/spf13/cobra" istionetworkv1alpha3 "istio.io/client-go/pkg/apis/networking/v1alpha3" istionetworkv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1" @@ -98,6 +99,10 @@ func (o *Options) run(ctx context.Context) error { return fmt.Errorf("could not update manager scheme: %s", err) } + if err := operatorv1alpha1.AddToScheme(mgr.GetScheme()); err != nil { + return fmt.Errorf("could not update manager scheme: %s", err) + } + if err := istionetworkv1alpha3.AddToScheme(mgr.GetScheme()); err != nil { return fmt.Errorf("could not update manager scheme: %s", err) } @@ -112,6 +117,10 @@ func (o *Options) run(ctx context.Context) error { o.controllerOptions.Completed().Apply(&controller.DefaultAddOptions.ControllerOptions) o.healthOptions.Completed().Apply(&healthcheck.DefaultAddOptions.Controller) o.reconcileOptions.Completed().Apply(&controller.DefaultAddOptions.IgnoreOperationAnnotation) + healthcheck.DefaultAddOptions.ExtensionClasses = o.generalOptions.Completed().ExtensionClasses + + o.reconcileOptions.Completed().Apply(&controller.DefaultAddOptions.IgnoreOperationAnnotation) + controller.DefaultAddOptions.ExtensionClasses = o.generalOptions.Completed().ExtensionClasses if err := o.controllerSwitches.Completed().AddToManager(ctx, mgr); err != nil { return fmt.Errorf("could not add controllers to manager: %s", err) diff --git a/deploy/garden/rbac.yaml b/deploy/garden/rbac.yaml new file mode 100644 index 00000000..a0a125e7 --- /dev/null +++ b/deploy/garden/rbac.yaml @@ -0,0 +1,25 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: extension-acl-managedseeds + annotations: + authorization.gardener.cloud/extensions-serviceaccount-selector: '{"matchLabels":{"extension":"acl"}}' + labels: + authorization.gardener.cloud/custom-extensions-permissions: "true" +rules: +- apiGroups: + - seedmanagement.gardener.cloud + resources: + - managedseeds + verbs: + - get + - list + - watch +- apiGroups: + - core.gardener.cloud + resources: + - shoots + verbs: + - get + - list + - watch diff --git a/pkg/controller/actuator.go b/pkg/controller/actuator.go index b7fe3177..9a203806 100644 --- a/pkg/controller/actuator.go +++ b/pkg/controller/actuator.go @@ -26,32 +26,29 @@ import ( "github.com/gardener/gardener/extensions/pkg/controller" "github.com/gardener/gardener/extensions/pkg/controller/extension" - v1beta1helper "github.com/gardener/gardener/pkg/api/core/v1beta1/helper" v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants" extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" + operatorv1alpha1 "github.com/gardener/gardener/pkg/apis/operator/v1alpha1" "github.com/gardener/gardener/pkg/chartrenderer" - "github.com/gardener/gardener/pkg/utils/chart" "github.com/gardener/gardener/pkg/utils/managedresources" "github.com/go-logr/logr" "github.com/pkg/errors" istionetworkv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1" appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/client-go/rest" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/cluster" "sigs.k8s.io/controller-runtime/pkg/manager" "github.com/stackitcloud/gardener-extension-acl/charts" + "github.com/stackitcloud/gardener-extension-acl/pkg/controller/allowedcidrs" "github.com/stackitcloud/gardener-extension-acl/pkg/controller/config" "github.com/stackitcloud/gardener-extension-acl/pkg/envoyfilters" "github.com/stackitcloud/gardener-extension-acl/pkg/extensionspec" "github.com/stackitcloud/gardener-extension-acl/pkg/helper" - "github.com/stackitcloud/gardener-extension-acl/pkg/imagevector" - - apierrors "k8s.io/apimachinery/pkg/api/errors" ) const ( @@ -62,10 +59,6 @@ const ( // HashAnnotationName name of annotation for triggering the envoyfilter webhook // DEPRECATED: Remove after annotation has been removed from all EnvoyFilters HashAnnotationName = "acl-ext-rule-hash" - // ImageName is used for the image vector override. - // This is currently not implemented correctly. - // TODO implement - ImageName = "image-name" deletionTimeout = 2 * time.Minute istioGatewayName = "kube-apiserver" ingressGatewayName = "nginx-ingress-controller" @@ -87,10 +80,16 @@ type ExtensionState struct { } // NewActuator returns an actuator responsible for Extension resources. -func NewActuator(mgr manager.Manager, cfg config.Config) extension.Actuator { +func NewActuator(mgr manager.Manager, gardenCluster cluster.Cluster, cfg config.Config) extension.Actuator { + var gardenClient client.Client + if gardenCluster != nil { + gardenClient = gardenCluster.GetClient() + } + return &actuator{ extensionConfig: cfg, client: mgr.GetClient(), + gardenClient: gardenClient, config: mgr.GetConfig(), decoder: serializer.NewCodecFactory(mgr.GetScheme(), serializer.EnableStrict).UniversalDecoder(), } @@ -98,6 +97,7 @@ func NewActuator(mgr manager.Manager, cfg config.Config) extension.Actuator { type actuator struct { client client.Client + gardenClient client.Client config *rest.Config decoder runtime.Decoder extensionConfig config.Config @@ -107,11 +107,6 @@ type actuator struct { // //nolint:gocyclo // this is the main reconcile loop func (a *actuator) Reconcile(ctx context.Context, log logr.Logger, ex *extensionsv1alpha1.Extension) error { - cluster, err := helper.GetClusterForExtension(ctx, a.client, ex) - if err != nil { - return err - } - extSpec := &extensionspec.ExtensionSpec{} if ex.Spec.ProviderConfig != nil && ex.Spec.ProviderConfig.Raw != nil { if err := json.Unmarshal(ex.Spec.ProviderConfig.Raw, &extSpec); err != nil { @@ -123,75 +118,69 @@ func (a *actuator) Reconcile(ctx context.Context, log logr.Logger, ex *extension return err } - istioNamespace, istioLabels, err := a.findIstioNamespaceForExtension(ctx, ex) - if err != nil { - // we ignore errors for hibernated clusters if they don't have a Gateway - // resource for the extension to get the istio namespace from - if controller.IsHibernated(cluster) { - return client.IgnoreNotFound(err) - } - return err - } - extState, err := getExtensionState(ex) if err != nil { return err } - hosts := make([]string, 0) - if len(cluster.Shoot.Status.AdvertisedAddresses) < 1 { - return ErrNoAdvertisedAddresses + var cluster *controller.Cluster + if !hasClassGarden(ex) { + var err error + cluster, err = helper.GetClusterForExtension(ctx, a.client, ex) + if err != nil { + return err + } } - for _, address := range cluster.Shoot.Status.AdvertisedAddresses { - hosts = append(hosts, strings.Split(address.URL, "//")[1]) + istioNamespace, istioLabels, err := a.findIstioNamespaceForExtension(ctx, ex) + if err != nil { + // we ignore errors for hibernated clusters if they don't have a Gateway + // resource for the extension to get the istio namespace from + if cluster != nil && controller.IsHibernated(cluster) { + return client.IgnoreNotFound(err) + } + return err } - var shootSpecificCIDRs []string - var alwaysAllowedCIDRs []string - alwaysAllowedCIDRs = append(alwaysAllowedCIDRs, helper.GetSeedSpecificAllowedCIDRs(cluster.Seed)...) + var allowedCIDRer allowedcidrs.AllowedCIDRer - // This relies on the LB hairpinning in-cluster traffic out and back in - // through the Seed's egress IP, which is the common case when the LB - // exposes ipMode: Proxy and the CNI does not short-circuit clusterIP - // traffic (e.g., Cilium with bpfSocketLBHostnsOnly: true). - if ok, err := a.usesProxyTypeLBService(ctx, istioNamespace); err != nil { - log.Error(err, "unable to get Istio Ingressgateway service", "namespace", istioNamespace) - return fmt.Errorf("unable to get istio service: %w", err) - } else if ok { - egressCIDRs, err := a.getSeedEgressIPOnManagedSeeds(ctx) + if hasClassGarden(ex) { + garden, err := a.getGarden(ctx) if err != nil { return err } - alwaysAllowedCIDRs = append(alwaysAllowedCIDRs, egressCIDRs...) + allowedCIDRer = &allowedcidrs.Garden{ + Garden: garden, + Client: a.gardenClient, + } + } else { + allowedCIDRer = &allowedcidrs.Shoot{ + Cluster: cluster, + Client: a.client, + IstioNamespace: istioNamespace, + } } - if len(a.extensionConfig.AdditionalAllowedCIDRs) >= 1 { + alwaysAllowedCIDRs, err := allowedCIDRer.AllowedCIDRs(ctx, ex) + if err != nil { + return err + } + if len(a.extensionConfig.AdditionalAllowedCIDRs) > 0 { alwaysAllowedCIDRs = append(alwaysAllowedCIDRs, a.extensionConfig.AdditionalAllowedCIDRs...) } - // Gardener supports workerless Shoots. These don't have an associated - // Infrastructure object and don't need Node- or Pod-specific CIDRs to be - // allowed. Therefore, skip these steps for workerless Shoots. - if !v1beta1helper.IsWorkerless(cluster.Shoot) { - shootSpecificCIDRs = append(shootSpecificCIDRs, helper.GetShootNodeSpecificAllowedCIDRs(cluster.Shoot)...) - - infra, err := helper.GetInfrastructureForExtension(ctx, a.client, ex, cluster.Shoot.Name) - if err != nil { - return err - } - - shootSpecificCIDRs = append(shootSpecificCIDRs, infra.Status.EgressCIDRs...) + hosts, err := allowedCIDRer.Hosts() + if err != nil { + return err } - if err := a.createSeedResources( + if err := a.createFilters( ctx, log, ex.GetNamespace(), extSpec, cluster, hosts, - shootSpecificCIDRs, alwaysAllowedCIDRs, istioNamespace, istioLabels, @@ -279,15 +268,12 @@ func (a *actuator) createSeedResources( spec *extensionspec.ExtensionSpec, cluster *controller.Cluster, hosts []string, - shootSpecificCIDRs []string, alwaysAllowedCIDRs []string, istioNamespace string, istioLabels map[string]string, ) error { var err error - alwaysAllowedCIDRs = append(alwaysAllowedCIDRs, shootSpecificCIDRs...) - apiEnvoyFilterSpec, err := envoyfilters.BuildAPIEnvoyFilterSpecForHelmChart( spec.Rule, hosts, alwaysAllowedCIDRs, istioLabels, ) @@ -295,37 +281,38 @@ func (a *actuator) createSeedResources( return err } - vpnEnvoyFilterSpec := envoyfilters.BuildVPNEnvoyFilterSpecForHelmChart( - cluster, spec.Rule, alwaysAllowedCIDRs, istioLabels, - ) - httpProxyEnvoyFilterSpec := envoyfilters.BuildHTTPProxyEnvoyFilterSpecForHelmChart( - cluster, spec.Rule, alwaysAllowedCIDRs, istioLabels, - ) - - cfg := map[string]interface{}{ - "shootName": cluster.Shoot.Status.TechnicalID, - "targetNamespace": istioNamespace, - "apiEnvoyFilterSpec": apiEnvoyFilterSpec, - "vpnEnvoyFilterSpec": vpnEnvoyFilterSpec, - "httpProxyEnvoyFilterSpec": httpProxyEnvoyFilterSpec, + values := values{ + TargetNamespace: istioNamespace, + APIEnvoyFilterSpec: apiEnvoyFilterSpec, } - defaultLabels, err := a.findDefaultIstioLabels(ctx) - if client.IgnoreNotFound(err) != nil { - return err - } else if err == nil { - // The `nginx-ingress-controller` Gateway object only exists in g/g@v1.89, (introduced with - // https://github.com/gardener/gardener/pull/9038). - // If it doesn't exist yet, we can't apply ACLs to shoot ingresses. - ingressEnvoyFilterSpec := envoyfilters.BuildIngressEnvoyFilterSpecForHelmChart( - cluster, spec.Rule, alwaysAllowedCIDRs, defaultLabels) + if cluster != nil { + values.Suffix = cluster.Shoot.Status.TechnicalID - cfg["ingressEnvoyFilterSpec"] = ingressEnvoyFilterSpec - } + vpnEnvoyFilterSpec := envoyfilters.BuildVPNEnvoyFilterSpecForHelmChart( + cluster, spec.Rule, alwaysAllowedCIDRs, istioLabels, + ) + httpProxyEnvoyFilterSpec := envoyfilters.BuildHTTPProxyEnvoyFilterSpecForHelmChart( + cluster, spec.Rule, alwaysAllowedCIDRs, istioLabels, + ) - cfg, err = chart.InjectImages(cfg, imagevector.ImageVector(), []string{ImageName}) - if err != nil { - return fmt.Errorf("failed to find image version for %s: %v", ImageName, err) + values.VPNEnvoyFilterSpec = vpnEnvoyFilterSpec + values.HTTPProxyEnvoyFilterSpec = httpProxyEnvoyFilterSpec + + defaultLabels, err := a.findDefaultIstioLabels(ctx) + if client.IgnoreNotFound(err) != nil { + return err + } else if err == nil { + // The `nginx-ingress-controller` Gateway object only exists in g/g@v1.89, (introduced with + // https://github.com/gardener/gardener/pull/9038). + // If it doesn't exist yet, we can't apply ACLs to shoot ingresses. + ingressEnvoyFilterSpec := envoyfilters.BuildIngressEnvoyFilterSpecForHelmChart( + cluster, spec.Rule, alwaysAllowedCIDRs, defaultLabels) + + values.IngressEnvoyFilterSpec = ingressEnvoyFilterSpec + } + } else { + values.Suffix = "garden" } renderer, err := chartrenderer.NewForConfig(a.config) @@ -335,7 +322,35 @@ func (a *actuator) createSeedResources( log.Info("Component is being applied", "component", "component-name", "namespace", namespace) - return a.createManagedResource(ctx, namespace, ResourceNameSeed, "seed", renderer, ChartNameSeed, namespace, cfg, nil, charts.Seed) + return a.createManagedResource(ctx, namespace, ResourceNameSeed, "seed", renderer, ChartNameSeed, namespace, values.AsMap(), nil, charts.Seed) +} + +type values struct { + // Suffix is the suffix that gets added to every envoy filter. + // For shoot extensions, this is the shoot name. + // For garden extension, this is "garden" + Suffix string `json:"suffix"` + + // TargetNamespace is the namespace where the envoy filters get created in + // This is the namespace where the istio gateway is running in + TargetNamespace string `json:"targetNamespace"` + + VPNEnvoyFilterSpec map[string]any `json:"vpnEnvoyFilterSpec"` + IngressEnvoyFilterSpec map[string]any `json:"ingressEnvoyFilterSpec"` + HTTPProxyEnvoyFilterSpec map[string]any `json:"httpProxyEnvoyFilterSpec"` + APIEnvoyFilterSpec map[string]any `json:"apiEnvoyFilterSpec"` +} + +func (v values) AsMap() map[string]any { + m := map[string]any{} + raw, err := json.Marshal(v) + if err != nil { + return m + } + if err := json.Unmarshal(raw, &m); err != nil { + return m + } + return m } func (a *actuator) deleteSeedResources(ctx context.Context, log logr.Logger, namespace string) error { @@ -382,6 +397,17 @@ func (a *actuator) createManagedResource( ) } +func (a *actuator) getGarden(ctx context.Context) (*operatorv1alpha1.Garden, error) { + gardens := &operatorv1alpha1.GardenList{} + if err := a.client.List(ctx, gardens); err != nil { + return nil, err + } + if len(gardens.Items) == 0 { + return nil, errors.New("no garden found") + } + return &gardens.Items[0], nil +} + func (a *actuator) updateStatus( ctx context.Context, ex *extensionsv1alpha1.Extension, @@ -409,6 +435,10 @@ func getExtensionState(ex *extensionsv1alpha1.Extension) (*ExtensionState, error return extState, nil } +func (a *actuator) InjectSourceClient(client client.Client) { + a.gardenClient = client +} + // findIstioNamespaceForExtension finds the Istio namespace by the Istio Gateway // object named "kube-apiserver", which is expected to be present in every // Shoot namespace (except when the Shoot is hibernated - in this case, the @@ -426,9 +456,15 @@ func (a *actuator) findIstioNamespaceForExtension( ) { gw := istionetworkv1beta1.Gateway{} + gatewayName := istioGatewayName + + if ex.Spec.Class != nil && *ex.Spec.Class == extensionsv1alpha1.ExtensionClassGarden { + gatewayName = operatorv1alpha1.VirtualGardenNamePrefix + gatewayName + } + err = a.client.Get(ctx, client.ObjectKey{ Namespace: ex.Namespace, - Name: istioGatewayName, + Name: gatewayName, }, &gw) if err != nil { return "", nil, err @@ -441,6 +477,14 @@ func (a *actuator) findIstioNamespaceForExtension( if err != nil { return "", nil, err } + if ex.Spec.Class != nil && *ex.Spec.Class == extensionsv1alpha1.ExtensionClassGarden { + for _, dep := range deployments.Items { + if dep.Namespace == operatorv1alpha1.VirtualGardenDefaultSNIIngressNamespace { + return dep.Namespace, gw.Spec.Selector, nil + } + } + } + if len(deployments.Items) != 1 { return "", nil, fmt.Errorf("no istio namespace could be selected, because the number of deployments found is %d", len(deployments.Items)) } @@ -467,65 +511,6 @@ func (a *actuator) findDefaultIstioLabels( return gw.Spec.Selector, nil } -// usesProxyTypeLBService checks the `istio-ingressgateway` LoadBalancer Service -// selected by its labels whether it is exposing the service with the Proxy IPMode -func (a *actuator) usesProxyTypeLBService( - ctx context.Context, - namespace string, -) (bool, error) { - svc := corev1.Service{} - err := a.client.Get( - ctx, - client.ObjectKey{ - Name: v1beta1constants.DefaultSNIIngressServiceName, - Namespace: namespace, - }, - &svc) - if err != nil { - if apierrors.IsNotFound(err) { - return false, nil - } - return false, err - } - - for _, ing := range svc.Status.LoadBalancer.Ingress { - if m := ing.IPMode; m != nil && *m == corev1.LoadBalancerIPModeProxy { - return true, nil - } - } - - return false, nil -} - -// getSeedEgressIPOnManagedSeeds returns the egressIP CIDRs of the ManagedSeed, if the -// Seed is not a shoot, it will return an empty list -func (a *actuator) getSeedEgressIPOnManagedSeeds(ctx context.Context) ([]string, error) { - cm := corev1.ConfigMap{} - if err := a.client.Get(ctx, - client.ObjectKey{ - Name: v1beta1constants.ConfigMapNameShootInfo, - Namespace: metav1.NamespaceSystem, - }, - &cm); err != nil { - if apierrors.IsNotFound(err) { - return []string{}, nil - } - return nil, err - } - - cidrsStr, ok := cm.Data["egressCIDRs"] - if !ok { - return nil, errors.New("unable to get egress CIDRs from shoot-info ConfigMap") - } - - var cidrs []string - for i := range strings.SplitSeq(cidrsStr, ",") { - _, _, err := net.ParseCIDR(i) - if err != nil { - return nil, err - } - cidrs = append(cidrs, i) - } - - return cidrs, nil +func hasClassGarden(ex *extensionsv1alpha1.Extension) bool { + return ptr.Deref(ex.GetExtensionSpec().GetExtensionClass(), extensionsv1alpha1.ExtensionClassShoot) == extensionsv1alpha1.ExtensionClassGarden } diff --git a/pkg/controller/add.go b/pkg/controller/add.go index cf44ad83..063cc345 100644 --- a/pkg/controller/add.go +++ b/pkg/controller/add.go @@ -17,12 +17,17 @@ package controller import ( "context" + "fmt" + "os" "slices" extensionscontroller "github.com/gardener/gardener/extensions/pkg/controller" "github.com/gardener/gardener/extensions/pkg/controller/extension" extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" + "github.com/gardener/gardener/pkg/client/kubernetes" "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/cluster" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/handler" @@ -40,10 +45,8 @@ const ( suffix = "-extension-service" ) -var ( - // DefaultAddOptions are the default AddOptions for AddToManager. - DefaultAddOptions = AddOptions{} -) +// DefaultAddOptions are the default AddOptions for AddToManager. +var DefaultAddOptions = AddOptions{} // AddOptions are options to apply when adding the shoot service controller to the manager. type AddOptions struct { @@ -53,8 +56,8 @@ type AddOptions struct { ExtensionConfig controllerconfig.Config // IgnoreOperationAnnotation specifies whether to ignore the operation annotation or not. IgnoreOperationAnnotation bool - // ExtensionClass defines the extension class this extension is responsible for. - ExtensionClass extensionsv1alpha1.ExtensionClass + // ExtensionClasses defines the extension classes this extension is responsible for. + ExtensionClasses []extensionsv1alpha1.ExtensionClass } // AddToManager adds a controller with the default Options to the given Controller Manager. @@ -65,17 +68,29 @@ func AddToManager(ctx context.Context, mgr manager.Manager) error { // AddToManagerWithOptions adds a controller with the given Options to the given manager. // The opts.Reconciler is being set with a newly instantiated actuator. func AddToManagerWithOptions(ctx context.Context, mgr manager.Manager, opts *AddOptions) error { - return extension.Add(mgr, extension.AddArgs{ - Actuator: NewActuator(mgr, opts.ExtensionConfig), + // configure garden + var gardenCluster cluster.Cluster + if kFile := os.Getenv("GARDEN_KUBECONFIG"); kFile != "" { + var err error + gardenCluster, err = setupGardenCluster(mgr, kFile) + if err != nil { + return fmt.Errorf("unable to set up garden cluster: %w", err) + } + } + args := extension.AddArgs{ + Actuator: NewActuator(mgr, gardenCluster, opts.ExtensionConfig), ControllerOptions: opts.ControllerOptions, Name: Type + suffix, FinalizerSuffix: Type + suffix, Resync: 0, Predicates: extension.DefaultPredicates(ctx, mgr, DefaultAddOptions.IgnoreOperationAnnotation), Type: Type, - ExtensionClasses: []extensionsv1alpha1.ExtensionClass{opts.ExtensionClass}, - WatchBuilder: watchInfrastructure(mgr), - }) + ExtensionClasses: opts.ExtensionClasses, + } + if !slices.Contains(opts.ExtensionClasses, extensionsv1alpha1.ExtensionClassGarden) { + args.WatchBuilder = watchInfrastructure(mgr) + } + return extension.Add(mgr, args) } func infrastructurePredicate() predicate.TypedFuncs[*extensionsv1alpha1.Infrastructure] { @@ -119,3 +134,26 @@ func watchInfrastructure(mgr manager.Manager) extensionscontroller.WatchBuilder )) }) } + +func setupGardenCluster(mgr manager.Manager, kubeconfigFile string) (cluster.Cluster, error) { + gardenRESTConfig, err := kubernetes.RESTConfigFromKubeconfigFile(kubeconfigFile, kubernetes.AuthTokenFile, kubernetes.AuthExec) + if err != nil { + return nil, err + } + + gardenCluster, err := cluster.New(gardenRESTConfig, func(opts *cluster.Options) { + opts.Scheme = kubernetes.GardenScheme + opts.Cache = cache.Options{ + DefaultNamespaces: map[string]cache.Config{ + // ManagedSeeds (and their underlying Shoots) must always be in the "garden" namespace, so that is the + // only one we need to watch. + "garden": {}, + }, + } + }) + if err != nil { + return nil, err + } + + return gardenCluster, mgr.Add(gardenCluster) +} diff --git a/pkg/controller/allowedcidrs/allowedcidrs.go b/pkg/controller/allowedcidrs/allowedcidrs.go new file mode 100644 index 00000000..fe02130a --- /dev/null +++ b/pkg/controller/allowedcidrs/allowedcidrs.go @@ -0,0 +1,13 @@ +package allowedcidrs + +import ( + "context" + + extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" +) + +// AllowedCIDRer defines an interface on how to get AllowedCIDRs and SNI Hosts +type AllowedCIDRer interface { + Hosts() ([]string, error) + AllowedCIDRs(context.Context, *extensionsv1alpha1.Extension) ([]string, error) +} diff --git a/pkg/controller/allowedcidrs/errors.go b/pkg/controller/allowedcidrs/errors.go new file mode 100644 index 00000000..ba2946bb --- /dev/null +++ b/pkg/controller/allowedcidrs/errors.go @@ -0,0 +1,6 @@ +package allowedcidrs + +import "errors" + +// ErrNoAdvertisedAddresses is returned if a cluster or garden does not contain advertised addresses +var ErrNoAdvertisedAddresses = errors.New("advertised addresses are not available, likely because cluster creation has not yet completed") diff --git a/pkg/controller/allowedcidrs/garden.go b/pkg/controller/allowedcidrs/garden.go new file mode 100644 index 00000000..b344d6f5 --- /dev/null +++ b/pkg/controller/allowedcidrs/garden.go @@ -0,0 +1,71 @@ +package allowedcidrs + +import ( + "context" + "strings" + + gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1" + v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants" + extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" + operatorv1alpha1 "github.com/gardener/gardener/pkg/apis/operator/v1alpha1" + seedmanagementv1alpha1 "github.com/gardener/gardener/pkg/apis/seedmanagement/v1alpha1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/stackitcloud/gardener-extension-acl/pkg/helper" +) + +// Garden implements [AllowedCIDRer] and retrieves CIDRs and Hosts relevant for Garden extension +type Garden struct { + Garden *operatorv1alpha1.Garden + Client client.Client +} + +// AllowedCIDRs returns always allowed cidrs for garden ACL +func (g *Garden) AllowedCIDRs(ctx context.Context, _ *extensionsv1alpha1.Extension) ([]string, error) { + var cidrs []string + cidrs = append(cidrs, helper.GetGardenSpecificAllowedCIDRs(g.Garden)...) + + seedCidrs, err := g.managedSeedsEgressCIDRs(ctx) + if err != nil { + return nil, err + } + cidrs = append(cidrs, seedCidrs...) + return cidrs, nil +} + +// Hosts returns SNI names of virtual garden kube-apiserver +func (g *Garden) Hosts() ([]string, error) { + hosts := make([]string, 0) + for _, address := range g.Garden.Status.AdvertisedAddresses { + if address.Name != operatorv1alpha1.AdvertisedAddressVirtualGarden { + continue + } + hosts = append(hosts, strings.Split(address.URL, "//")[1]) + } + if len(hosts) == 0 { + return nil, ErrNoAdvertisedAddresses + } + return hosts, nil +} + +func (g *Garden) managedSeedsEgressCIDRs(ctx context.Context) ([]string, error) { + managedSeeds := &seedmanagementv1alpha1.ManagedSeedList{} + if err := g.Client.List(ctx, managedSeeds, client.InNamespace(v1beta1constants.GardenNamespace)); err != nil { + return nil, err + } + + seedCIDRs := make([]string, 0, len(managedSeeds.Items)) + for _, managedSeed := range managedSeeds.Items { + shoot := &gardencorev1beta1.Shoot{} + if err := g.Client.Get(ctx, types.NamespacedName{Namespace: managedSeed.Namespace, Name: managedSeed.Spec.Shoot.Name}, shoot); err != nil { + return nil, err + } + if shoot.Status.Networking == nil { + continue + } + seedCIDRs = append(seedCIDRs, shoot.Status.Networking.EgressCIDRs...) + } + + return seedCIDRs, nil +} diff --git a/pkg/controller/allowedcidrs/shoot.go b/pkg/controller/allowedcidrs/shoot.go new file mode 100644 index 00000000..70edd831 --- /dev/null +++ b/pkg/controller/allowedcidrs/shoot.go @@ -0,0 +1,148 @@ +package allowedcidrs + +import ( + "context" + "errors" + "fmt" + "net" + "strings" + + "github.com/gardener/gardener/extensions/pkg/controller" + v1beta1helper "github.com/gardener/gardener/pkg/api/core/v1beta1/helper" + extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" + "sigs.k8s.io/controller-runtime/pkg/client" + logf "sigs.k8s.io/controller-runtime/pkg/log" + + v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/stackitcloud/gardener-extension-acl/pkg/helper" +) + +// Shoot implements [AllowedCIDRer] and retrieves CIDRs and Hosts relevant for Shoot extension +type Shoot struct { + Cluster *controller.Cluster + Client client.Client + IstioNamespace string +} + +// AllowedCIDRs returns always allowed cidrs for shoot ACL. +// It contains: +// - SeedSpecific CIDRs +// - Pod and Node CIDR if shoot is not workerless +func (s *Shoot) AllowedCIDRs(ctx context.Context, ex *extensionsv1alpha1.Extension) ([]string, error) { + log := logf.FromContext(ctx) + var shootSpecificCIDRs []string + var alwaysAllowedCIDRs []string + + alwaysAllowedCIDRs = append(alwaysAllowedCIDRs, helper.GetSeedSpecificAllowedCIDRs(s.Cluster.Seed)...) + + // Gardener supports workerless Shoots. These don't have an associated + // Infrastructure object and don't need Node- or Pod-specific CIDRs to be + // allowed. Therefore, skip these steps for workerless Shoots. + if !v1beta1helper.IsWorkerless(s.Cluster.Shoot) { + shootSpecificCIDRs = append(shootSpecificCIDRs, helper.GetShootNodeSpecificAllowedCIDRs(s.Cluster.Shoot)...) + + infra, err := helper.GetInfrastructureForExtension(ctx, s.Client, ex, s.Cluster.Shoot.Name) + if err != nil { + return nil, err + } + + shootSpecificCIDRs = append(shootSpecificCIDRs, infra.Status.EgressCIDRs...) + } + + // This relies on the LB hairpinning in-cluster traffic out and back in + // through the Seed's egress IP, which is the common case when the LB + // exposes ipMode: Proxy and the CNI does not short-circuit clusterIP + // traffic (e.g., Cilium with bpfSocketLBHostnsOnly: true). + if ok, err := s.usesProxyTypeLBService(ctx); err != nil { + log.Error(err, "unable to get Istio Ingressgateway service", "namespace", s.IstioNamespace) + return nil, fmt.Errorf("unable to get istio service: %w", err) + } else if ok { + egressCIDRs, err := s.getSeedEgressIPOnManagedSeeds(ctx) + if err != nil { + return nil, err + } + alwaysAllowedCIDRs = append(alwaysAllowedCIDRs, egressCIDRs...) + } + + alwaysAllowedCIDRs = append(alwaysAllowedCIDRs, shootSpecificCIDRs...) + return alwaysAllowedCIDRs, nil +} + +// Hosts returns SNI names of shoot's kube-apiserver +func (s *Shoot) Hosts() ([]string, error) { + hosts := make([]string, 0) + if len(s.Cluster.Shoot.Status.AdvertisedAddresses) < 1 { + return nil, ErrNoAdvertisedAddresses + } + + for _, address := range s.Cluster.Shoot.Status.AdvertisedAddresses { + hosts = append(hosts, strings.Split(address.URL, "//")[1]) + } + return hosts, nil +} + +// getSeedEgressIPOnManagedSeeds returns the egressIP CIDRs of the ManagedSeed, if the +// Seed is not a shoot, it will return an empty list +func (s *Shoot) getSeedEgressIPOnManagedSeeds(ctx context.Context) ([]string, error) { + cm := corev1.ConfigMap{} + if err := s.Client.Get(ctx, + client.ObjectKey{ + Name: v1beta1constants.ConfigMapNameShootInfo, + Namespace: metav1.NamespaceSystem, + }, + &cm); err != nil { + if apierrors.IsNotFound(err) { + return []string{}, nil + } + return nil, err + } + + cidrsStr, ok := cm.Data["egressCIDRs"] + if !ok { + return nil, errors.New("unable to get egress CIDRs from shoot-info ConfigMap") + } + + var cidrs []string + for i := range strings.SplitSeq(cidrsStr, ",") { + _, _, err := net.ParseCIDR(i) + if err != nil { + return nil, err + } + cidrs = append(cidrs, i) + } + + return cidrs, nil +} + +// usesProxyTypeLBService checks the `istio-ingressgateway` LoadBalancer Service +// selected by its labels whether it is exposing the service with the Proxy IPMode +func (s *Shoot) usesProxyTypeLBService( + ctx context.Context, +) (bool, error) { + svc := corev1.Service{} + err := s.Client.Get( + ctx, + client.ObjectKey{ + Name: v1beta1constants.DefaultSNIIngressServiceName, + Namespace: s.IstioNamespace, + }, + &svc) + if err != nil { + if apierrors.IsNotFound(err) { + return false, nil + } + return false, err + } + + for _, ing := range svc.Status.LoadBalancer.Ingress { + if m := ing.IPMode; m != nil && *m == corev1.LoadBalancerIPModeProxy { + return true, nil + } + } + + return false, nil +} diff --git a/pkg/controller/healthcheck/add.go b/pkg/controller/healthcheck/add.go index 4667c096..924142f3 100644 --- a/pkg/controller/healthcheck/add.go +++ b/pkg/controller/healthcheck/add.go @@ -31,12 +31,10 @@ import ( "github.com/stackitcloud/gardener-extension-acl/pkg/controller" ) -var ( - // DefaultAddOptions contains the default options for the healthchecks. - DefaultAddOptions = healthcheck.DefaultAddArgs{ - HealthCheckConfig: extensionsconfigv1alpha1.HealthCheckConfig{SyncPeriod: metav1.Duration{}}, - } -) +// DefaultAddOptions contains the default options for the healthchecks. +var DefaultAddOptions = healthcheck.DefaultAddArgs{ + HealthCheckConfig: extensionsconfigv1alpha1.HealthCheckConfig{SyncPeriod: metav1.Duration{}}, +} // RegisterHealthChecks registers health checks for each extension resource // HealthChecks are grouped by extension (e.g worker), extension.type (e.g aws) and Health Check Type (e.g SystemComponentsHealthy) diff --git a/pkg/helper/seed.go b/pkg/helper/seed.go index da7b041f..8ec3534d 100644 --- a/pkg/helper/seed.go +++ b/pkg/helper/seed.go @@ -2,6 +2,7 @@ package helper import ( "github.com/gardener/gardener/pkg/apis/core/v1beta1" + operatorv1alpha1 "github.com/gardener/gardener/pkg/apis/operator/v1alpha1" ) // GetSeedSpecificAllowedCIDRs returns the node and pod CIDRs from the seed @@ -24,3 +25,11 @@ func GetSeedIngressDomain(seed *v1beta1.Seed) string { } return domain } + +// GetGardenSpecificAllowedCIDRs returns the node and pod CIDRs from the garden runtime cluster +func GetGardenSpecificAllowedCIDRs(garden *operatorv1alpha1.Garden) []string { + cidrs := make([]string, 0) + cidrs = append(cidrs, garden.Spec.RuntimeCluster.Networking.Nodes...) + cidrs = append(cidrs, garden.Spec.RuntimeCluster.Networking.Pods...) + return cidrs +} From ddad90c06f89b4627b259a898b95d5f95923dfaa Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Mon, 11 May 2026 17:10:09 +0200 Subject: [PATCH 02/25] watch managedseed shoots Signed-off-by: Lukas Hoehl --- pkg/controller/add.go | 90 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/pkg/controller/add.go b/pkg/controller/add.go index 063cc345..4b237430 100644 --- a/pkg/controller/add.go +++ b/pkg/controller/add.go @@ -20,17 +20,25 @@ import ( "fmt" "os" "slices" + "time" extensionscontroller "github.com/gardener/gardener/extensions/pkg/controller" "github.com/gardener/gardener/extensions/pkg/controller/extension" + "github.com/gardener/gardener/pkg/api/indexer" + gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1" + v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants" extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" "github.com/gardener/gardener/pkg/client/kubernetes" + kubernetesutil "github.com/gardener/gardener/pkg/utils/kubernetes" "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" "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/controller" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/handler" + logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" @@ -76,6 +84,10 @@ func AddToManagerWithOptions(ctx context.Context, mgr manager.Manager, opts *Add if err != nil { return fmt.Errorf("unable to set up garden cluster: %w", err) } + + if err := indexer.AddManagedSeedShootName(ctx, gardenCluster.GetFieldIndexer()); err != nil { + return fmt.Errorf("adding index for managedSeed to garden cluster: %w", err) + } } args := extension.AddArgs{ Actuator: NewActuator(mgr, gardenCluster, opts.ExtensionConfig), @@ -89,6 +101,8 @@ func AddToManagerWithOptions(ctx context.Context, mgr manager.Manager, opts *Add } if !slices.Contains(opts.ExtensionClasses, extensionsv1alpha1.ExtensionClassGarden) { args.WatchBuilder = watchInfrastructure(mgr) + } else { + args.WatchBuilder = watchShootsOfManagedSeeds(mgr, gardenCluster) } return extension.Add(mgr, args) } @@ -135,6 +149,80 @@ func watchInfrastructure(mgr manager.Manager) extensionscontroller.WatchBuilder }) } +// watchShootsOfManagedSeeds watches for Shoot changes that are a managed seed and triggers the Extension reconciliation. +func watchShootsOfManagedSeeds(mgr manager.Manager, gardenCluster cluster.Cluster) extensionscontroller.WatchBuilder { + // Map Infrastructure changes to the Extension + mapFunc := func(ctx context.Context, shoot *gardencorev1beta1.Shoot) []reconcile.Request { + log := logf.FromContext(ctx).WithValues("shoot", shoot) + + exts := &extensionsv1alpha1.ExtensionList{} + if err := mgr.GetCache().List(ctx, exts, client.InNamespace(v1beta1constants.GardenNamespace)); err != nil { + log.Error(err, "listing extensions for managedseed enqueue requests") + return nil + } + gardenExtensions := slices.DeleteFunc(exts.Items, func(ext extensionsv1alpha1.Extension) bool { + if ext.Spec.Type != "acl" { + return true + } + if ext.Spec.Class == nil { + return true + } + return *ext.Spec.Class != extensionsv1alpha1.ExtensionClassGarden + }) + + reqs := make([]reconcile.Request, 0, len(gardenExtensions)) + for _, ext := range gardenExtensions { + reqs = append(reqs, reconcile.Request{NamespacedName: client.ObjectKeyFromObject(&ext)}) + } + return reqs + } + + // Watch for Infrastructure changes outside shoot reconciliation + return extensionscontroller.NewWatchBuilder(func(ctrl controller.Controller) error { + return ctrl.Watch(source.Kind(gardenCluster.GetCache(), &gardencorev1beta1.Shoot{}, + handler.TypedEnqueueRequestsFromMapFunc(mapFunc), + shootsOfManagedSeedsPredicate(gardenCluster.GetClient()), + )) + }) +} + +// shootsOfManagedSeedsPredicate filters change events to only enqueue if the shoot has a managed seed associated with it and the EgressCIDRs changes +func shootsOfManagedSeedsPredicate(c client.Reader) predicate.TypedFuncs[*gardencorev1beta1.Shoot] { + log := logf.Log.WithName("shootsOfManagedSeedsPredicate") + return predicate.TypedFuncs[*gardencorev1beta1.Shoot]{ + UpdateFunc: func(e event.TypedUpdateEvent[*gardencorev1beta1.Shoot]) bool { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + log.WithValues("shoot", e.ObjectNew) + ms, err := kubernetesutil.GetManagedSeedWithReader(ctx, c, e.ObjectNew.Namespace, e.ObjectNew.Name) + if err != nil { + log.Error(err, "getting managedseed from shoot") + return false + } + if ms == nil { + log.V(1).Info("no ManagedSeed available for shoot") + return false + } + if e.ObjectNew.Status.Networking == nil || e.ObjectOld.Status.Networking == nil { + return false + } + newEgress := ptr.Deref(e.ObjectNew.Status.Networking, gardencorev1beta1.NetworkingStatus{}).EgressCIDRs + oldEgress := ptr.Deref(e.ObjectOld.Status.Networking, gardencorev1beta1.NetworkingStatus{}).EgressCIDRs + return !slices.Equal(slices.Sorted(slices.Values(newEgress)), slices.Sorted(slices.Values(oldEgress))) + }, + DeleteFunc: func(event.TypedDeleteEvent[*gardencorev1beta1.Shoot]) bool { + // in case of shoot deletion we need to remove the CIDR of the seed + return true + }, + GenericFunc: func(event.TypedGenericEvent[*gardencorev1beta1.Shoot]) bool { + return false + }, + CreateFunc: func(event.TypedCreateEvent[*gardencorev1beta1.Shoot]) bool { + return false + }, + } +} + func setupGardenCluster(mgr manager.Manager, kubeconfigFile string) (cluster.Cluster, error) { gardenRESTConfig, err := kubernetes.RESTConfigFromKubeconfigFile(kubeconfigFile, kubernetes.AuthTokenFile, kubernetes.AuthExec) if err != nil { @@ -147,7 +235,7 @@ func setupGardenCluster(mgr manager.Manager, kubeconfigFile string) (cluster.Clu DefaultNamespaces: map[string]cache.Config{ // ManagedSeeds (and their underlying Shoots) must always be in the "garden" namespace, so that is the // only one we need to watch. - "garden": {}, + v1beta1constants.GardenNamespace: {}, }, } }) From 9818012e339c6af0d6338cb61c8bda619c2dd2de Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Tue, 12 May 2026 17:20:51 +0200 Subject: [PATCH 03/25] different managed resource name for garden extension Signed-off-by: Lukas Hoehl --- pkg/controller/actuator.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pkg/controller/actuator.go b/pkg/controller/actuator.go index 9a203806..07492846 100644 --- a/pkg/controller/actuator.go +++ b/pkg/controller/actuator.go @@ -52,8 +52,10 @@ import ( ) const ( - // ResourceNameSeed is name of the managedResource object + // ResourceNameSeed is name of the managedResource object for shoot extension ResourceNameSeed = "acl-seed" + // ResourceNameGarden is name of the managedResource object for garden extension + ResourceNameGarden = "acl-garden" // ChartNameSeed name of the helm chart ChartNameSeed = "seed" // HashAnnotationName name of annotation for triggering the envoyfilter webhook @@ -286,6 +288,8 @@ func (a *actuator) createSeedResources( APIEnvoyFilterSpec: apiEnvoyFilterSpec, } + mrName := ResourceNameSeed + if cluster != nil { values.Suffix = cluster.Shoot.Status.TechnicalID @@ -313,6 +317,7 @@ func (a *actuator) createSeedResources( } } else { values.Suffix = "garden" + mrName = ResourceNameGarden } renderer, err := chartrenderer.NewForConfig(a.config) @@ -322,7 +327,7 @@ func (a *actuator) createSeedResources( log.Info("Component is being applied", "component", "component-name", "namespace", namespace) - return a.createManagedResource(ctx, namespace, ResourceNameSeed, "seed", renderer, ChartNameSeed, namespace, values.AsMap(), nil, charts.Seed) + return a.createManagedResource(ctx, namespace, mrName, "seed", renderer, ChartNameSeed, namespace, values.AsMap(), nil, charts.Seed) } type values struct { From 7f2533915c3324aeaaf277788abf142c1d380bf0 Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Tue, 12 May 2026 17:20:57 +0200 Subject: [PATCH 04/25] healthcheck garden managed resource Signed-off-by: Lukas Hoehl --- pkg/controller/healthcheck/add.go | 40 ++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/pkg/controller/healthcheck/add.go b/pkg/controller/healthcheck/add.go index 924142f3..7c9ec70c 100644 --- a/pkg/controller/healthcheck/add.go +++ b/pkg/controller/healthcheck/add.go @@ -23,8 +23,11 @@ import ( "github.com/gardener/gardener/extensions/pkg/controller/healthcheck/general" gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1" extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" + operatorv1alpha1 "github.com/gardener/gardener/pkg/apis/operator/v1alpha1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/utils/ptr" + "k8s.io/utils/set" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/manager" @@ -39,6 +42,23 @@ var DefaultAddOptions = healthcheck.DefaultAddArgs{ // RegisterHealthChecks registers health checks for each extension resource // HealthChecks are grouped by extension (e.g worker), extension.type (e.g aws) and Health Check Type (e.g SystemComponentsHealthy) func RegisterHealthChecks(mgr manager.Manager, opts *healthcheck.DefaultAddArgs) error { + checks := []healthcheck.ConditionTypeToHealthCheck{} + classes := set.New(opts.ExtensionClasses...) + if classes.Has(extensionsv1alpha1.ExtensionClassShoot) { + checks = append(checks, healthcheck.ConditionTypeToHealthCheck{ + ConditionType: string(gardencorev1beta1.SeedExtensionsReady), + HealthCheck: general.CheckManagedResource(controller.ResourceNameSeed), + PreCheckFunc: isExtensionClass(extensionsv1alpha1.ExtensionClassShoot), + }) + } + if classes.Has(extensionsv1alpha1.ExtensionClassGarden) { + checks = append(checks, healthcheck.ConditionTypeToHealthCheck{ + ConditionType: string(operatorv1alpha1.VirtualComponentsHealthy), + HealthCheck: general.CheckManagedResource(controller.ResourceNameGarden), + PreCheckFunc: isExtensionClass(extensionsv1alpha1.ExtensionClassGarden), + }) + } + return healthcheck.DefaultRegistration( controller.Type, extensionsv1alpha1.SchemeGroupVersion.WithKind(extensionsv1alpha1.ExtensionResource), @@ -47,12 +67,7 @@ func RegisterHealthChecks(mgr manager.Manager, opts *healthcheck.DefaultAddArgs) mgr, *opts, nil, - []healthcheck.ConditionTypeToHealthCheck{ - { - ConditionType: string(gardencorev1beta1.SeedExtensionsReady), - HealthCheck: general.CheckManagedResource(controller.ResourceNameSeed), - }, - }, + checks, sets.New[gardencorev1beta1.ConditionType](), ) } @@ -61,3 +76,16 @@ func RegisterHealthChecks(mgr manager.Manager, opts *healthcheck.DefaultAddArgs) func AddToManager(_ context.Context, mgr manager.Manager) error { return RegisterHealthChecks(mgr, &DefaultAddOptions) } + +func isExtensionClass(class extensionsv1alpha1.ExtensionClass) healthcheck.PreCheckFunc { + return func(_ context.Context, _ client.Client, req client.Object, _ any) bool { + ext, ok := req.(*extensionsv1alpha1.Extension) + if !ok { + return false + } + if ptr.Deref(ext.Spec.Class, extensionsv1alpha1.ExtensionClassShoot) != class { + return false + } + return true + } +} From 2ed982153049437e96482b227bdedd3c9b4a205f Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Mon, 18 May 2026 17:18:57 +0200 Subject: [PATCH 05/25] tests Signed-off-by: Lukas Hoehl --- Makefile | 5 +- pkg/controller/actuator_garden_test.go | 82 + ...ctuator_test.go => actuator_shoot_test.go} | 18 +- pkg/controller/add.go | 26 +- pkg/controller/add_test.go | 151 ++ pkg/controller/allowedcidrs/garden_test.go | 108 + pkg/controller/allowedcidrs/suite_test.go | 14 + pkg/controller/suite_test.go | 115 +- ...-extensions.gardener.cloud_extensions.yaml | 49 +- ...0-crd-operator.gardener.cloud_gardens.yaml | 2409 +++++++++++++++++ 10 files changed, 2914 insertions(+), 63 deletions(-) create mode 100644 pkg/controller/actuator_garden_test.go rename pkg/controller/{actuator_test.go => actuator_shoot_test.go} (95%) create mode 100644 pkg/controller/allowedcidrs/garden_test.go create mode 100644 pkg/controller/allowedcidrs/suite_test.go create mode 100644 upstream-crds/10-crd-operator.gardener.cloud_gardens.yaml diff --git a/Makefile b/Makefile index a46b997f..c88ec1df 100644 --- a/Makefile +++ b/Makefile @@ -109,9 +109,10 @@ generate: $(HELM) $(YQ) format: $(GOIMPORTS) $(GOIMPORTSREVISER) @bash $(GARDENER_HACK_DIR)/format.sh ./cmd ./pkg -.PHONY: test +.PHONY: test +test: DIRS ?= "./cmd/... ./pkg/..." test: $(REPORT_COLLECTOR) $(SETUP_ENVTEST) - @./hack/test.sh ./cmd/... ./pkg/... + @./hack/test.sh $(DIRS) .PHONY: test-cov test-cov: diff --git a/pkg/controller/actuator_garden_test.go b/pkg/controller/actuator_garden_test.go new file mode 100644 index 00000000..93a402eb --- /dev/null +++ b/pkg/controller/actuator_garden_test.go @@ -0,0 +1,82 @@ +package controller + +import ( + "encoding/json" + "slices" + + "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants" + extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" + "github.com/gardener/gardener/pkg/utils/managedresources" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + istionetworkingv1alpha3 "istio.io/client-go/pkg/apis/networking/v1alpha3" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/stackitcloud/gardener-extension-acl/pkg/envoyfilters" + "github.com/stackitcloud/gardener-extension-acl/pkg/extensionspec" +) + +var _ = Describe("actuator garden test", func() { + var ( + a *actuator + istioNamespace string + istioNamespaceSelector map[string]string + ) + + BeforeEach(func() { + istioNamespace = createNewIstioNamespace() + istioNamespaceSelector = map[string]string{ + "app": "istio-ingressgateway", + "istio": istioNamespace, + } + + createNewGateway("virtual-garden-kube-apiserver", constants.GardenNamespace, istioNamespaceSelector) + createNewIstioDeployment(istioNamespace, istioNamespaceSelector) + createNewGarden() + + a = getNewActuator() + a.gardenClient = k8sClient + }) + + AfterEach(func() { + deleteNamespace(istioNamespace) + }) + + Describe("reconciliation of an ACL extension object", func() { + It("should create managed resource containing acl-api-garden EnvoyFilter object", func() { + extSpec := extensionspec.ExtensionSpec{ + Rule: &envoyfilters.ACLRule{ + Cidrs: []string{"1.2.3.4/24"}, + Action: "ALLOW", + Type: "remote_ip", + }, + } + extSpecJSON, err := json.Marshal(extSpec) + Expect(err).NotTo(HaveOccurred()) + ext := createNewExtension(constants.GardenNamespace, extSpecJSON, extensionsv1alpha1.ExtensionClassGarden) + Expect(ext).To(Not(BeNil())) + + Expect(a.Reconcile(ctx, logger, ext)).To(Succeed(), "actuator reconcile") + + objs, err := managedresources.GetObjects(ctx, a.client, constants.GardenNamespace, ResourceNameGarden) + Expect(err).NotTo(HaveOccurred()) + idx := slices.IndexFunc(objs, func(obj client.Object) bool { + filter, ok := obj.(*istionetworkingv1alpha3.EnvoyFilter) + if !ok { + return false + } + return filter.Name == "acl-api-garden" + }) + Expect(idx).NotTo(Equal(-1), "envoy filter acl-api-garden not found") + filter := objs[idx].(*istionetworkingv1alpha3.EnvoyFilter) + configPatch := filter.Spec.ConfigPatches[0] + patch, err := configPatch.Patch.Value.MarshalJSON() + Expect(err).NotTo(HaveOccurred()) + Expect(patch).To(ContainSubstring("1.2.3.4")) + Expect(patch).To(ContainSubstring(virtualGardenPodCIDR.Addr().String())) + Expect(patch).To(ContainSubstring(virtualGardenNodeCIDR.Addr().String())) + + Expect(configPatch.Match.GetListener().FilterChain.Sni).To(Equal(virtualGardenURL)) + }) + }) +}) diff --git a/pkg/controller/actuator_test.go b/pkg/controller/actuator_shoot_test.go similarity index 95% rename from pkg/controller/actuator_test.go rename to pkg/controller/actuator_shoot_test.go index 0f1acf2f..7e85d92b 100644 --- a/pkg/controller/actuator_test.go +++ b/pkg/controller/actuator_shoot_test.go @@ -21,7 +21,7 @@ import ( "github.com/stackitcloud/gardener-extension-acl/pkg/extensionspec" ) -var _ = Describe("actuator test", func() { +var _ = Describe("actuator shoot test", func() { var ( a *actuator shootNamespace1, shootNamespace2 string @@ -82,7 +82,7 @@ var _ = Describe("actuator test", func() { } extSpecJSON, err := json.Marshal(extSpec) Expect(err).NotTo(HaveOccurred()) - ext := createNewExtension(shootNamespace1, extSpecJSON) + ext := createNewExtension(shootNamespace1, extSpecJSON, extensionsv1alpha1.ExtensionClassShoot) Expect(ext).To(Not(BeNil())) Expect(a.Reconcile(ctx, logger, ext)).To(Succeed()) @@ -107,7 +107,7 @@ var _ = Describe("actuator test", func() { } extSpecJSON, err := json.Marshal(extSpec) Expect(err).NotTo(HaveOccurred()) - ext := createNewExtension(shootNamespace1, extSpecJSON) + ext := createNewExtension(shootNamespace1, extSpecJSON, extensionsv1alpha1.ExtensionClassShoot) Expect(ext).To(Not(BeNil())) // act @@ -149,7 +149,7 @@ var _ = Describe("actuator test", func() { } extSpecJSON, err := json.Marshal(extSpec) Expect(err).NotTo(HaveOccurred()) - ext := createNewExtension(shootNamespace1, extSpecJSON) + ext := createNewExtension(shootNamespace1, extSpecJSON, extensionsv1alpha1.ExtensionClassShoot) Expect(ext).To(Not(BeNil())) Expect(a.Reconcile(ctx, logger, ext)).To(Succeed()) @@ -174,7 +174,7 @@ var _ = Describe("actuator test", func() { } extSpecJSON, err := json.Marshal(extSpec) Expect(err).NotTo(HaveOccurred()) - ext := createNewExtension(shootNamespace1, extSpecJSON) + ext := createNewExtension(shootNamespace1, extSpecJSON, extensionsv1alpha1.ExtensionClassShoot) Expect(ext).To(Not(BeNil())) Expect(a.Reconcile(ctx, logger, ext)).To(Succeed()) @@ -212,11 +212,11 @@ var _ = Describe("actuator test", func() { } extSpecJSON1, err := json.Marshal(extSpec1) Expect(err).NotTo(HaveOccurred()) - ext1 := createNewExtension(shootNamespace1, extSpecJSON1) + ext1 := createNewExtension(shootNamespace1, extSpecJSON1, extensionsv1alpha1.ExtensionClassShoot) Expect(ext1).To(Not(BeNil())) // contents of the seconds extension don't matter, it just needs to exist - ext2 := createNewExtension(shootNamespace2, []byte("{}")) + ext2 := createNewExtension(shootNamespace2, []byte("{}"), extensionsv1alpha1.ExtensionClassShoot) Expect(ext2).To(Not(BeNil())) // simulate a hibernated cluster by deleting the Gateway object @@ -337,7 +337,7 @@ var _ = Describe("actuator test", func() { } extSpecJSON, err := json.Marshal(extSpec) Expect(err).NotTo(HaveOccurred()) - ext := createNewExtension(shootNamespace1, extSpecJSON) + ext := createNewExtension(shootNamespace1, extSpecJSON, extensionsv1alpha1.ExtensionClassShoot) Expect(ext).To(Not(BeNil())) // act @@ -405,7 +405,7 @@ var _ = Describe("actuator test", func() { } extSpecJSON, err := json.Marshal(extSpec) Expect(err).NotTo(HaveOccurred()) - ext := createNewExtension(shootNamespace1, extSpecJSON) + ext := createNewExtension(shootNamespace1, extSpecJSON, extensionsv1alpha1.ExtensionClassShoot) Expect(ext).To(Not(BeNil())) Expect(a.Reconcile(ctx, logger, ext)).To(Succeed()) diff --git a/pkg/controller/add.go b/pkg/controller/add.go index 4b237430..85845d9d 100644 --- a/pkg/controller/add.go +++ b/pkg/controller/add.go @@ -151,12 +151,21 @@ func watchInfrastructure(mgr manager.Manager) extensionscontroller.WatchBuilder // watchShootsOfManagedSeeds watches for Shoot changes that are a managed seed and triggers the Extension reconciliation. func watchShootsOfManagedSeeds(mgr manager.Manager, gardenCluster cluster.Cluster) extensionscontroller.WatchBuilder { - // Map Infrastructure changes to the Extension - mapFunc := func(ctx context.Context, shoot *gardencorev1beta1.Shoot) []reconcile.Request { + // Watch for Infrastructure changes outside shoot reconciliation + return extensionscontroller.NewWatchBuilder(func(ctrl controller.Controller) error { + return ctrl.Watch(source.Kind(gardenCluster.GetCache(), &gardencorev1beta1.Shoot{}, + handler.TypedEnqueueRequestsFromMapFunc(mapShootsOfManagedSeedsToExtensions(mgr.GetClient())), + shootsOfManagedSeedsPredicate(gardenCluster.GetClient()), + )) + }) +} + +func mapShootsOfManagedSeedsToExtensions(r client.Reader) handler.TypedMapFunc[*gardencorev1beta1.Shoot, reconcile.Request] { + return func(ctx context.Context, shoot *gardencorev1beta1.Shoot) []reconcile.Request { log := logf.FromContext(ctx).WithValues("shoot", shoot) exts := &extensionsv1alpha1.ExtensionList{} - if err := mgr.GetCache().List(ctx, exts, client.InNamespace(v1beta1constants.GardenNamespace)); err != nil { + if err := r.List(ctx, exts, client.InNamespace(v1beta1constants.GardenNamespace)); err != nil { log.Error(err, "listing extensions for managedseed enqueue requests") return nil } @@ -176,14 +185,6 @@ func watchShootsOfManagedSeeds(mgr manager.Manager, gardenCluster cluster.Cluste } return reqs } - - // Watch for Infrastructure changes outside shoot reconciliation - return extensionscontroller.NewWatchBuilder(func(ctrl controller.Controller) error { - return ctrl.Watch(source.Kind(gardenCluster.GetCache(), &gardencorev1beta1.Shoot{}, - handler.TypedEnqueueRequestsFromMapFunc(mapFunc), - shootsOfManagedSeedsPredicate(gardenCluster.GetClient()), - )) - }) } // shootsOfManagedSeedsPredicate filters change events to only enqueue if the shoot has a managed seed associated with it and the EgressCIDRs changes @@ -203,9 +204,6 @@ func shootsOfManagedSeedsPredicate(c client.Reader) predicate.TypedFuncs[*garden log.V(1).Info("no ManagedSeed available for shoot") return false } - if e.ObjectNew.Status.Networking == nil || e.ObjectOld.Status.Networking == nil { - return false - } newEgress := ptr.Deref(e.ObjectNew.Status.Networking, gardencorev1beta1.NetworkingStatus{}).EgressCIDRs oldEgress := ptr.Deref(e.ObjectOld.Status.Networking, gardencorev1beta1.NetworkingStatus{}).EgressCIDRs return !slices.Equal(slices.Sorted(slices.Values(newEgress)), slices.Sorted(slices.Values(oldEgress))) diff --git a/pkg/controller/add_test.go b/pkg/controller/add_test.go index 91892dac..2c93c83b 100644 --- a/pkg/controller/add_test.go +++ b/pkg/controller/add_test.go @@ -15,14 +15,26 @@ package controller import ( + "context" "slices" + "github.com/gardener/gardener/pkg/api/indexer" gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1" extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" + "github.com/gardener/gardener/pkg/apis/seedmanagement" + seedmanagementv1alpha1 "github.com/gardener/gardener/pkg/apis/seedmanagement/v1alpha1" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" + + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/predicate" + "sigs.k8s.io/controller-runtime/pkg/reconcile" ) var _ = Describe("infrastructurePredicate", func() { @@ -88,3 +100,142 @@ var _ = Describe("infrastructurePredicate", func() { }) }) }) + +var _ = Describe("shootsOfManagedSeeds", func() { + Describe("predicate", func() { + var ( + p predicate.TypedPredicate[*gardencorev1beta1.Shoot] + shoot *gardencorev1beta1.Shoot + ms *seedmanagementv1alpha1.ManagedSeed + c client.Client + ) + BeforeEach(func(ctx context.Context) { + scheme := runtime.NewScheme() + Expect(gardencorev1beta1.AddToScheme(scheme)).To(Succeed()) + Expect(seedmanagementv1alpha1.AddToScheme(scheme)).To(Succeed()) + c = fake.NewClientBuilder(). + WithScheme(scheme). + WithIndex(&seedmanagementv1alpha1.ManagedSeed{}, seedmanagement.ManagedSeedShootName, indexer.ManagedSeedShootNameIndexerFunc). + Build() + + p = shootsOfManagedSeedsPredicate(c) + shoot = &gardencorev1beta1.Shoot{ + ObjectMeta: v1.ObjectMeta{ + Name: "foo", + }, + Status: gardencorev1beta1.ShootStatus{ + Networking: &gardencorev1beta1.NetworkingStatus{}, + }, + } + ms = &seedmanagementv1alpha1.ManagedSeed{ + ObjectMeta: v1.ObjectMeta{ + Name: "seed", + }, + Spec: seedmanagementv1alpha1.ManagedSeedSpec{ + Shoot: &seedmanagementv1alpha1.Shoot{ + Name: shoot.Name, + }, + }, + } + Expect(c.Create(ctx, shoot)).To(Succeed()) + Expect(c.Create(ctx, ms)).To(Succeed()) + }) + + It("should return true if egressCIDR of shoot with managedseed changed", func() { + shootNew := shoot.DeepCopy() + shootNew.Status.Networking.EgressCIDRs = []string{"192.168.3.4/32"} + Expect(p.Update(event.TypedUpdateEvent[*gardencorev1beta1.Shoot]{ + ObjectNew: shootNew, + ObjectOld: shoot, + })).To(BeTrue(), "update predicate") + }) + + It("should return false if managedseed is not found for shoot", func() { + Expect(c.Delete(ctx, ms)).To(Succeed()) + Expect(p.Update(event.TypedUpdateEvent[*gardencorev1beta1.Shoot]{ + ObjectNew: shoot, + ObjectOld: shoot, + })).To(BeFalse(), "update predicate") + }) + }) + + Describe("mapToExtensions", func() { + var ( + shoot *gardencorev1beta1.Shoot + c client.Client + ) + BeforeEach(func() { + scheme := runtime.NewScheme() + Expect(gardencorev1beta1.AddToScheme(scheme)).To(Succeed()) + Expect(extensionsv1alpha1.AddToScheme(scheme)).To(Succeed()) + c = fake.NewClientBuilder(). + WithScheme(scheme). + Build() + shoot = &gardencorev1beta1.Shoot{ + ObjectMeta: v1.ObjectMeta{ + Name: "foo", + }, + } + }) + + It("should return only acl extensions and extensions of class garden inside garden namespace", func(ctx context.Context) { + extensions := []*extensionsv1alpha1.Extension{ + { + ObjectMeta: v1.ObjectMeta{ + Name: "not-in-garden-namespace", + }, + Spec: extensionsv1alpha1.ExtensionSpec{ + DefaultSpec: extensionsv1alpha1.DefaultSpec{ + Class: ptr.To(extensionsv1alpha1.ExtensionClassGarden), + Type: "acl", + }, + }, + }, + { + ObjectMeta: v1.ObjectMeta{ + Name: "not-garden-extension", + Namespace: "garden", + }, + + Spec: extensionsv1alpha1.ExtensionSpec{ + DefaultSpec: extensionsv1alpha1.DefaultSpec{ + Type: "acl", + }, + }, + }, + { + ObjectMeta: v1.ObjectMeta{ + Name: "not-acl-extension", + Namespace: "garden", + }, + Spec: extensionsv1alpha1.ExtensionSpec{ + DefaultSpec: extensionsv1alpha1.DefaultSpec{ + Type: "foo", + Class: ptr.To(extensionsv1alpha1.ExtensionClassGarden), + }, + }, + }, + { + ObjectMeta: v1.ObjectMeta{ + Name: "garden-acl-extension", + Namespace: "garden", + }, + Spec: extensionsv1alpha1.ExtensionSpec{ + DefaultSpec: extensionsv1alpha1.DefaultSpec{ + Type: "acl", + Class: ptr.To(extensionsv1alpha1.ExtensionClassGarden), + }, + }, + }, + } + + for _, e := range extensions { + Expect(c.Create(ctx, e)).To(Succeed()) + } + requests := mapShootsOfManagedSeedsToExtensions(c)(ctx, shoot) + Expect(requests).To(HaveExactElements(reconcile.Request{ + NamespacedName: types.NamespacedName{Namespace: "garden", Name: "garden-acl-extension"}, + })) + }) + }) +}) diff --git a/pkg/controller/allowedcidrs/garden_test.go b/pkg/controller/allowedcidrs/garden_test.go new file mode 100644 index 00000000..82136a17 --- /dev/null +++ b/pkg/controller/allowedcidrs/garden_test.go @@ -0,0 +1,108 @@ +package allowedcidrs + +import ( + "context" + + gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1" + "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants" + operatorv1alpha1 "github.com/gardener/gardener/pkg/apis/operator/v1alpha1" + seedmanagementv1alpha1 "github.com/gardener/gardener/pkg/apis/seedmanagement/v1alpha1" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client/fake" +) + +var _ = Describe("#Garden", func() { + var garden *Garden + nodeCIDR := "192.168.0.0/16" + podCIDR := "10.0.0.0/16" + + BeforeEach(func() { + scheme := runtime.NewScheme() + Expect(seedmanagementv1alpha1.AddToScheme(scheme)).To(Succeed()) + Expect(gardencorev1beta1.AddToScheme(scheme)).To(Succeed()) + garden = &Garden{ + Client: fake.NewClientBuilder().WithScheme(scheme).Build(), + Garden: &operatorv1alpha1.Garden{ + Spec: operatorv1alpha1.GardenSpec{ + RuntimeCluster: operatorv1alpha1.RuntimeCluster{ + Networking: operatorv1alpha1.RuntimeNetworking{ + Pods: []string{podCIDR}, + Nodes: []string{nodeCIDR}, + }, + }, + }, + }, + } + }) + + Describe("#AllowedCIDRs", func() { + Context("without managed seeds", func() { + It("should return pod and node cidr from garden runtime cluster", func(ctx context.Context) { + cidrs, err := garden.AllowedCIDRs(ctx, nil) + Expect(err).NotTo(HaveOccurred()) + Expect(cidrs).To(ConsistOf(podCIDR, nodeCIDR)) + }) + }) + Context("with managed seeds", func() { + BeforeEach(func(ctx context.Context) { + managedSeed := &seedmanagementv1alpha1.ManagedSeed{ + ObjectMeta: metav1.ObjectMeta{ + Name: "seed", + Namespace: constants.GardenNamespace, + }, + Spec: seedmanagementv1alpha1.ManagedSeedSpec{ + Shoot: &seedmanagementv1alpha1.Shoot{ + Name: "shoot", + }, + }, + } + shoot := &gardencorev1beta1.Shoot{ + ObjectMeta: metav1.ObjectMeta{ + Name: "shoot", + Namespace: constants.GardenNamespace, + }, + Status: gardencorev1beta1.ShootStatus{ + Networking: &gardencorev1beta1.NetworkingStatus{ + EgressCIDRs: []string{"192.168.198.20/32"}, + }, + }, + } + Expect(garden.Client.Create(ctx, managedSeed)).To(Succeed(), "managed seed create") + Expect(garden.Client.Create(ctx, shoot)).To(Succeed(), "shoot create") + }) + It("should add egress cidrs of managed seed shoots", func(ctx context.Context) { + cidrs, err := garden.AllowedCIDRs(ctx, nil) + Expect(err).NotTo(HaveOccurred()) + Expect(cidrs).To(ContainElements("192.168.198.20/32")) + }) + }) + }) + + Describe("#Hosts", func() { + It("should ErrNoAdvertisedAddresses if no AdvertisedAddresses is present in garden", func() { + _, err := garden.Hosts() + Expect(err).To(MatchError(ErrNoAdvertisedAddresses)) + }) + + It("should return only addresses of virtual garden", func() { + garden.Garden.Status.VirtualClusterStatus = &operatorv1alpha1.VirtualClusterStatus{ + AdvertisedAddresses: []operatorv1alpha1.AdvertisedAddress{ + { + Name: "foo", + URL: "https://foo", + }, + { + Name: operatorv1alpha1.AdvertisedAddressVirtual, + URL: "https://bar", + }, + }, + } + hosts, err := garden.Hosts() + Expect(err).NotTo(HaveOccurred()) + Expect(hosts).To(ConsistOf("bar")) + }) + }) +}) diff --git a/pkg/controller/allowedcidrs/suite_test.go b/pkg/controller/allowedcidrs/suite_test.go new file mode 100644 index 00000000..7e187842 --- /dev/null +++ b/pkg/controller/allowedcidrs/suite_test.go @@ -0,0 +1,14 @@ +package allowedcidrs + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestAllowedCIDRs(t *testing.T) { + RegisterFailHandler(Fail) + + RunSpecs(t, "allowedcidrs Test Suite") +} diff --git a/pkg/controller/suite_test.go b/pkg/controller/suite_test.go index 43c2d3d6..02ae06a6 100644 --- a/pkg/controller/suite_test.go +++ b/pkg/controller/suite_test.go @@ -2,6 +2,7 @@ package controller import ( "context" + "net/netip" "path/filepath" "strconv" "strings" @@ -10,9 +11,12 @@ import ( gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1" gardenercorev1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants" extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" + operatorv1alpha1 "github.com/gardener/gardener/pkg/apis/operator/v1alpha1" resourcesv1alpha1 "github.com/gardener/gardener/pkg/apis/resources/v1alpha1" + seedmanagementinstall "github.com/gardener/gardener/pkg/apis/seedmanagement/install" + gardenlogger "github.com/gardener/gardener/pkg/logger" + gardenerenvtest "github.com/gardener/gardener/test/envtest" "github.com/go-logr/logr" - "github.com/go-logr/logr/testr" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "istio.io/api/networking/v1beta1" @@ -30,45 +34,61 @@ import ( "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" ) -var cfg *rest.Config -var k8sClient client.Client -var testEnv *envtest.Environment -var clientScheme *runtime.Scheme -var logger logr.Logger -var ctx = context.TODO() -var shootNamespaceCounter = 1 -var istioNamespaceCounter = 1 +var ( + cfg *rest.Config + k8sClient client.Client + testEnv *envtest.Environment + gardenTestEnv *gardenerenvtest.GardenerTestEnvironment + clientScheme *runtime.Scheme + logger logr.Logger + ctx = context.TODO() + shootNamespaceCounter = 1 + istioNamespaceCounter = 1 +) func TestAPIs(t *testing.T) { RegisterFailHandler(Fail) - logger = testr.New(t) - RunSpecs(t, "Extension Test Suite") } var _ = BeforeSuite(func() { var err error + logf.SetLogger(gardenlogger.MustNewZapLogger(gardenlogger.DebugLevel, gardenlogger.FormatJSON, zap.WriteTo(GinkgoWriter))) + logger = logf.Log.WithName("foo") + By("bootstrapping test environment") testEnv = &envtest.Environment{ - CRDDirectoryPaths: []string{filepath.Join("..", "..", "upstream-crds")}, + CRDDirectoryPaths: []string{ + filepath.Join("..", "..", "upstream-crds"), + }, ErrorIfCRDPathMissing: true, } + gardenTestEnv = &gardenerenvtest.GardenerTestEnvironment{ + Environment: testEnv, + GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{ + Args: []string{"--disable-admission-plugins="}, + }, + } + clientScheme = runtime.NewScheme() Expect(clientgoscheme.AddToScheme(clientScheme)).To(Succeed()) Expect(extensionsv1alpha1.AddToScheme(clientScheme)).To(Succeed()) Expect(resourcesv1alpha1.AddToScheme(clientScheme)).To(Succeed()) Expect(apiextensions.AddToScheme(clientScheme)).To(Succeed()) + Expect(operatorv1alpha1.AddToScheme(clientScheme)).To(Succeed()) Expect(istionetworkingv1beta1.AddToScheme(clientScheme)).To(Succeed()) Expect(istionetworkingv1alpha3.AddToScheme(clientScheme)).To(Succeed()) + Expect(seedmanagementinstall.AddToScheme(clientScheme)).To(Succeed()) - cfg, err = testEnv.Start() + cfg, err = gardenTestEnv.Start() Expect(err).ToNot(HaveOccurred()) - Expect(cfg).NotTo(BeNil()) //+kubebuilder:scaffold:scheme @@ -80,8 +100,7 @@ var _ = BeforeSuite(func() { var _ = AfterSuite(func() { By("tearing down the test environment") - err := testEnv.Stop() - Expect(err).ToNot(HaveOccurred()) + Expect(gardenTestEnv.Stop()).To(Succeed()) }) func createGardenNamespace() { @@ -188,7 +207,7 @@ func updateServiceStatus(name, namespace string, status corev1.ServiceStatus) { Expect(k8sClient.Status().Update(ctx, svc)).ShouldNot(HaveOccurred()) } -func createNewExtension(shootNamespace string, providerConfig []byte) *extensionsv1alpha1.Extension { +func createNewExtension(shootNamespace string, providerConfig []byte, class extensionsv1alpha1.ExtensionClass) *extensionsv1alpha1.Extension { ext := &extensionsv1alpha1.Extension{ ObjectMeta: metav1.ObjectMeta{ Name: "acl", @@ -196,7 +215,8 @@ func createNewExtension(shootNamespace string, providerConfig []byte) *extension }, Spec: extensionsv1alpha1.ExtensionSpec{ DefaultSpec: extensionsv1alpha1.DefaultSpec{ - Type: "acl", + Class: &class, + Type: "acl", ProviderConfig: &runtime.RawExtension{ Raw: providerConfig, }, @@ -276,6 +296,65 @@ func createNewCluster(shootNamespace string) { Expect(k8sClient.Create(ctx, cluster)).ShouldNot(HaveOccurred()) } +var ( + virtualGardenPodCIDR = netip.MustParsePrefix("10.0.0.0/16") + virtualGardenNodeCIDR = netip.MustParsePrefix("192.168.0.0/16") + virtualGardenURL = "virtual-garden" +) + +func createNewGarden() { + garden := &operatorv1alpha1.Garden{ + ObjectMeta: metav1.ObjectMeta{ + Name: "garden", + }, + Spec: operatorv1alpha1.GardenSpec{ + VirtualCluster: operatorv1alpha1.VirtualCluster{ + Networking: operatorv1alpha1.Networking{ + Services: []string{"10.254.0.0/16"}, + }, + Gardener: operatorv1alpha1.Gardener{ + ClusterIdentity: "foo", + }, + Kubernetes: operatorv1alpha1.Kubernetes{ + Version: "1.30.1", + }, + Maintenance: operatorv1alpha1.Maintenance{ + TimeWindow: gardencorev1beta1.MaintenanceTimeWindow{ + Begin: "220000+0100", + End: "230000+0100", + }, + }, + }, + RuntimeCluster: operatorv1alpha1.RuntimeCluster{ + Networking: operatorv1alpha1.RuntimeNetworking{ + Pods: []string{virtualGardenPodCIDR.String()}, + Nodes: []string{virtualGardenNodeCIDR.String()}, + Services: []string{"10.255.0.0/16"}, + }, + Ingress: operatorv1alpha1.Ingress{ + Controller: gardencorev1beta1.IngressController{ + Kind: "nginx", + }, + }, + }, + }, + } + + Expect(k8sClient.Create(ctx, garden)).ShouldNot(HaveOccurred()) + garden.Status = operatorv1alpha1.GardenStatus{ + VirtualClusterStatus: &operatorv1alpha1.VirtualClusterStatus{ + AdvertisedAddresses: []operatorv1alpha1.AdvertisedAddress{ + { + Name: operatorv1alpha1.AdvertisedAddressVirtual, + URL: "https://" + virtualGardenURL, + }, + }, + }, + } + + Expect(k8sClient.Status().Update(ctx, garden)).To(Succeed()) +} + func createShootInfo(cidrs []string) { cm := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ diff --git a/upstream-crds/10-crd-extensions.gardener.cloud_extensions.yaml b/upstream-crds/10-crd-extensions.gardener.cloud_extensions.yaml index 9530cbd8..37d57eec 100644 --- a/upstream-crds/10-crd-extensions.gardener.cloud_extensions.yaml +++ b/upstream-crds/10-crd-extensions.gardener.cloud_extensions.yaml @@ -1,11 +1,9 @@ - --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.7.0 - creationTimestamp: null + controller-gen.kubebuilder.io/version: v0.20.1 name: extensions.extensions.gardener.cloud spec: group: extensions.gardener.cloud @@ -37,20 +35,34 @@ spec: description: Extension is a specification for a Extension resource. properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object spec: - description: ExtensionSpec is the spec for a Extension resource. + description: |- + Specification of the Extension. + If the object's deletion timestamp is set, this field is immutable. properties: + class: + description: Class holds the extension class used to control the responsibility + for multiple provider extensions. + type: string + x-kubernetes-validations: + - message: Value is immutable + rule: self == oldSelf providerConfig: description: ProviderConfig is the provider specific configuration. type: object @@ -156,7 +168,7 @@ spec: type: string type: description: Type of the last operation, one of Create, Reconcile, - Delete. + Delete, Migrate, Restore. type: string required: - description @@ -187,18 +199,21 @@ spec: description: ResourceRef is a reference to a resource. properties: apiVersion: - description: API version of the referent + description: apiVersion is the API version of the referent type: string kind: - description: 'Kind of the referent; More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds"' + description: 'kind is the kind of the referent; More info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string name: - description: 'Name of the referent; More info: http://kubernetes.io/docs/user-guide/identifiers#names' + description: 'name is the name of the referent; More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string required: - kind - name type: object + x-kubernetes-map-type: atomic required: - name - resourceRef @@ -217,9 +232,3 @@ spec: storage: true subresources: status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] \ No newline at end of file diff --git a/upstream-crds/10-crd-operator.gardener.cloud_gardens.yaml b/upstream-crds/10-crd-operator.gardener.cloud_gardens.yaml new file mode 100644 index 00000000..7616db5c --- /dev/null +++ b/upstream-crds/10-crd-operator.gardener.cloud_gardens.yaml @@ -0,0 +1,2409 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.20.1 + name: gardens.operator.gardener.cloud +spec: + group: operator.gardener.cloud + names: + kind: Garden + listKind: GardenList + plural: gardens + shortNames: + - grdn + singular: garden + scope: Cluster + versions: + - additionalPrinterColumns: + - description: Kubernetes version of virtual cluster. + jsonPath: .spec.virtualCluster.kubernetes.version + name: K8S Version + type: string + - description: Version of the Gardener components. + jsonPath: .status.gardener.version + name: Gardener Version + type: string + - description: Status of the last operation + jsonPath: .status.lastOperation.state + name: Last Operation + type: string + - description: Indicates whether the components related to the runtime cluster + are healthy. + jsonPath: .status.conditions[?(@.type=="RuntimeComponentsHealthy")].status + name: Runtime + type: string + - description: Indicates whether the components related to the virtual cluster + are healthy. + jsonPath: .status.conditions[?(@.type=="VirtualComponentsHealthy")].status + name: Virtual + type: string + - description: Indicates whether the API server of the virtual cluster is available. + jsonPath: .status.conditions[?(@.type=="VirtualGardenAPIServerAvailable")].status + name: API Server + type: string + - description: Indicates whether the observability components related to the runtime + cluster are healthy. + jsonPath: .status.conditions[?(@.type=="ObservabilityComponentsHealthy")].status + name: Observability + type: string + - description: creation timestamp + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: Garden describes a list of gardens. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec contains the specification of this garden. + properties: + dns: + description: DNS contains specifications of DNS providers. + properties: + providers: + description: Providers is a list of DNS providers. + items: + description: DNSProvider contains the configuration for a DNS + provider. + properties: + name: + description: Name is the name of the DNS provider. + minLength: 1 + type: string + providerConfig: + description: Config is the provider-specific configuration + passed to DNSRecord resources. + type: object + x-kubernetes-preserve-unknown-fields: true + secretRef: + description: SecretRef is a reference to a Secret object + containing the DNS provider credentials. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + type: + description: Type is the type of the DNS provider. + minLength: 1 + type: string + required: + - name + - secretRef + - type + type: object + minItems: 1 + type: array + required: + - providers + type: object + extensions: + description: Extensions contain type and provider information for + Garden extensions. + items: + description: GardenExtension contains type and provider information + for Garden extensions. + properties: + providerConfig: + description: ProviderConfig is the configuration passed to extension + resource. + type: object + x-kubernetes-preserve-unknown-fields: true + type: + description: Type is the type of the extension resource. + minLength: 1 + type: string + required: + - type + type: object + type: array + resources: + description: Resources holds a list of named resource references that + can be referred to in extension configs by their names. + items: + description: NamedResourceReference is a named reference to a resource. + properties: + name: + description: Name of the resource reference. + type: string + resourceRef: + description: ResourceRef is a reference to a resource. + properties: + apiVersion: + description: apiVersion is the API version of the referent + type: string + kind: + description: 'kind is the kind of the referent; More info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'name is the name of the referent; More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + required: + - name + - resourceRef + type: object + type: array + runtimeCluster: + description: RuntimeCluster contains configuration for the runtime + cluster. + properties: + ingress: + description: Ingress configures Ingress specific settings for + the Garden cluster. + properties: + controller: + description: Controller configures a Gardener managed Ingress + Controller listening on the ingressDomain. + properties: + kind: + description: Kind defines which kind of IngressController + to use. At the moment only `nginx` is supported + enum: + - nginx + type: string + providerConfig: + description: ProviderConfig specifies infrastructure specific + configuration for the ingressController + type: object + x-kubernetes-preserve-unknown-fields: true + required: + - kind + type: object + domains: + description: |- + Domains specify the ingress domains of the cluster pointing to the ingress controller endpoint. They will be used + to construct ingress URLs for system applications running in runtime cluster. + items: + description: DNSDomain defines a DNS domain with optional + provider. + properties: + name: + description: Name is the domain name. + minLength: 1 + type: string + provider: + description: |- + Provider is the name of the DNS provider as declared in the '.spec.dns.providers' section. + It is only optional, if the `.spec.dns` section is not provided at all. + type: string + required: + - name + type: object + minItems: 1 + type: array + required: + - controller + type: object + networking: + description: Networking defines the networking configuration of + the runtime cluster. + properties: + blockCIDRs: + description: BlockCIDRs is a list of network addresses that + should be blocked. + items: + type: string + type: array + ipFamilies: + description: |- + IPFamilies specifies the IP protocol versions to use for the runtime cluster's networking. This field is + immutable. + Defaults to ["IPv4"]. + items: + description: IPFamily is a type for specifying an IP protocol + version to use in Gardener clusters. + type: string + type: array + nodes: + description: Nodes are the CIDRs of the node network. Elements + can be appended to this list, but not removed. + items: + type: string + type: array + pods: + description: Pods are the CIDRs of the pod network. Elements + can be appended to this list, but not removed. + items: + type: string + minItems: 1 + type: array + services: + description: Services are the CIDRs of the service network. + Elements can be appended to this list, but not removed. + items: + type: string + minItems: 1 + type: array + required: + - pods + - services + type: object + provider: + description: Provider defines the provider-specific information + for this cluster. + properties: + region: + description: Region is the region the cluster is deployed + to. + type: string + zones: + description: Zones is the list of availability zones the cluster + is deployed to. + items: + type: string + type: array + type: object + settings: + description: Settings contains certain settings for this cluster. + properties: + loadBalancerServices: + description: |- + LoadBalancerServices controls certain settings for services of type load balancer that are created in the runtime + cluster. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of annotations that + will be injected/merged into every load balancer service + object. + type: object + externalTrafficPolicy: + description: |- + ExternalTrafficPolicy specifies how nodes distribute service traffic they receive on one of the service's + externally-facing addresses. + Defaults to "Cluster". Can be set to "Local" when the load balancer is transparent (preserves client IP). + type: string + proxyProtocol: + description: |- + ProxyProtocol controls whether ProxyProtocol is (optionally) allowed for the load balancer services. + Defaults to nil, which is equivalent to not allowing ProxyProtocol. + properties: + allowed: + description: |- + Allowed controls whether the ProxyProtocol is optionally allowed for the load balancer services. + This should only be enabled if the load balancer services are already using ProxyProtocol or will be reconfigured to use it soon. + Until the load balancers are configured with ProxyProtocol, enabling this setting may allow clients to spoof their source IP addresses. + The option allows a migration from non-ProxyProtocol to ProxyProtocol without downtime (depending on the infrastructure). + Defaults to false. + type: boolean + required: + - allowed + type: object + type: object + topologyAwareRouting: + description: |- + TopologyAwareRouting controls certain settings for topology-aware traffic routing in the cluster. + See https://github.com/gardener/gardener/blob/master/docs/operations/topology_aware_routing.md. + properties: + enabled: + description: |- + Enabled controls whether certain Services deployed in the cluster should be topology-aware. + These Services are virtual-garden-etcd-main-client, virtual-garden-etcd-events-client and virtual-garden-kube-apiserver. + Additionally, other components that are deployed to the runtime cluster via other means can read this field and + according to its value enable/disable topology-aware routing for their Services. + type: boolean + required: + - enabled + type: object + verticalPodAutoscaler: + description: |- + VerticalPodAutoscaler controls certain settings for the vertical pod autoscaler components deployed in the + cluster. + properties: + enabled: + default: true + description: |- + Enabled controls whether the VPA components shall be deployed into this cluster. It is true by default because + the operator (and Gardener) heavily rely on a VPA being deployed. You should only disable this if your runtime + cluster already has another, manually/custom managed VPA deployment. If this is not the case, but you still + disable it, then reconciliation will fail. + type: boolean + featureGates: + additionalProperties: + type: boolean + description: FeatureGates contains information about enabled + feature gates. + type: object + maxAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + MaxAllowed specifies the global maximum allowed (maximum amount of resources) that vpa-recommender can recommend for a container. + The VerticalPodAutoscaler-level maximum allowed takes precedence over the global maximum allowed. + For more information, see https://github.com/kubernetes/autoscaler/blob/master/vertical-pod-autoscaler/docs/examples.md#specifying-global-maximum-allowed-resources-to-prevent-pods-from-being-unschedulable. + + Defaults to nil (no maximum). + type: object + type: object + type: object + volume: + description: Volume contains settings for persistent volumes created + in the runtime cluster. + properties: + minimumSize: + anyOf: + - type: integer + - type: string + description: MinimumSize defines the minimum size that should + be used for PVCs in the runtime cluster. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + required: + - ingress + - networking + - provider + type: object + virtualCluster: + description: VirtualCluster contains configuration for the virtual + cluster. + properties: + controlPlane: + description: ControlPlane holds information about the general + settings for the control plane of the virtual cluster. + properties: + highAvailability: + description: HighAvailability holds the configuration settings + for high availability settings. + type: object + type: object + dns: + description: DNS holds information about DNS settings. + properties: + domains: + description: |- + Domains are the external domains of the virtual garden cluster. + The first given domain in this list is immutable. + items: + description: DNSDomain defines a DNS domain with optional + provider. + properties: + name: + description: Name is the domain name. + minLength: 1 + type: string + provider: + description: |- + Provider is the name of the DNS provider as declared in the '.spec.dns.providers' section. + It is only optional, if the `.spec.dns` section is not provided at all. + type: string + required: + - name + type: object + minItems: 1 + type: array + type: object + etcd: + description: ETCD contains configuration for the etcds of the + virtual garden cluster. + properties: + events: + description: Events contains configuration for the events + etcd. + properties: + autoscaling: + description: Autoscaling contains auto-scaling configuration + options for etcd. + properties: + minAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + MinAllowed configures the minimum allowed resource requests for vertical pod autoscaling.. + Configuration of minAllowed resources is an advanced feature that can help clusters to overcome scale-up delays. + Default values are not applied to this field. + type: object + required: + - minAllowed + type: object + storage: + description: Storage contains storage configuration. + properties: + capacity: + anyOf: + - type: integer + - type: string + default: 10Gi + description: Capacity is the storage capacity for + the volumes. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + className: + description: ClassName is the name of a storage class. + type: string + type: object + type: object + main: + description: Main contains configuration for the main etcd. + properties: + autoscaling: + description: Autoscaling contains auto-scaling configuration + options for etcd. + properties: + minAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + MinAllowed configures the minimum allowed resource requests for vertical pod autoscaling.. + Configuration of minAllowed resources is an advanced feature that can help clusters to overcome scale-up delays. + Default values are not applied to this field. + type: object + required: + - minAllowed + type: object + backup: + description: Backup contains the object store configuration + for backups for the virtual garden etcd. + properties: + bucketName: + description: |- + BucketName is the name of the backup bucket. If not provided, gardener-operator attempts to manage a new bucket. + In this case, the cloud provider credentials provided in the SecretRef must have enough privileges for creating + and deleting buckets. + type: string + x-kubernetes-validations: + - message: BucketName is immutable + rule: self == oldSelf + provider: + description: Provider is a provider name. This field + is immutable. + type: string + x-kubernetes-validations: + - message: Provider is immutable + rule: self == oldSelf + providerConfig: + description: ProviderConfig is the provider-specific + configuration passed to BackupBucket resource. + type: object + x-kubernetes-preserve-unknown-fields: true + region: + description: Region is a region name. If undefined, + the provider region is used. This field is immutable. + type: string + x-kubernetes-validations: + - message: Region is immutable + rule: self == oldSelf + secretRef: + description: |- + SecretRef is a reference to a Secret object containing the cloud provider credentials for the object store where + backups should be stored. It should have enough privileges to manipulate the objects as well as buckets. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + required: + - provider + - secretRef + type: object + storage: + description: Storage contains storage configuration. + properties: + capacity: + anyOf: + - type: integer + - type: string + default: 10Gi + description: Capacity is the storage capacity for + the volumes. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + className: + description: ClassName is the name of a storage class. + type: string + type: object + type: object + type: object + gardener: + description: Gardener contains the configuration options for the + Gardener control plane components. + properties: + clusterIdentity: + description: ClusterIdentity is the identity of the garden + cluster. This field is immutable. + minLength: 1 + type: string + x-kubernetes-validations: + - message: Value is immutable + rule: self == oldSelf + gardenerAPIServer: + description: APIServer contains configuration settings for + the gardener-apiserver. + properties: + admissionPlugins: + description: |- + AdmissionPlugins contains the list of user-defined admission plugins (additional to those managed by Gardener), + and, if desired, the corresponding configuration. + items: + description: AdmissionPlugin contains information about + a specific admission plugin and its corresponding + configuration. + properties: + config: + description: Config is the configuration of the + plugin. + type: object + x-kubernetes-preserve-unknown-fields: true + disabled: + description: Disabled specifies whether this plugin + should be disabled. + type: boolean + kubeconfigSecretName: + description: KubeconfigSecretName specifies the + name of a secret containing the kubeconfig for + this admission plugin. + type: string + name: + description: Name is the name of the plugin. + type: string + required: + - name + type: object + type: array + auditConfig: + description: AuditConfig contains configuration settings + for the audit of the kube-apiserver. + properties: + auditPolicy: + description: AuditPolicy contains configuration settings + for audit policy of the kube-apiserver. + properties: + configMapRef: + description: |- + ConfigMapRef is a reference to a ConfigMap object in the same namespace, + which contains the audit policy for the kube-apiserver. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + type: object + type: object + auditWebhook: + description: AuditWebhook contains settings related to + an audit webhook configuration. + properties: + batchMaxSize: + default: 30 + description: BatchMaxSize is the maximum size of a + batch. + format: int32 + minimum: 1 + type: integer + kubeconfigSecretName: + description: KubeconfigSecretName specifies the name + of a secret containing the kubeconfig for this webhook. + minLength: 1 + type: string + version: + default: audit.k8s.io/v1 + description: Version is the API version to send and + expect from the webhook. + enum: + - audit.k8s.io/v1 + type: string + required: + - kubeconfigSecretName + type: object + encryptionConfig: + description: EncryptionConfig contains customizable encryption + configuration of the Gardener API server. + properties: + provider: + description: Provider contains information about the + encryption provider. + properties: + type: + description: |- + Type contains the type of the encryption provider. + + Supported types: + - "aescbc" + - "aesgcm" + - "secretbox" + Defaults to aescbc. + type: string + type: object + resources: + description: |- + Resources contains the list of resources that shall be encrypted in addition to secrets. + Each item is a Kubernetes resource name in plural (resource or resource.group) that should be encrypted. + Wildcards are not supported for now. + See https://github.com/gardener/gardener/blob/master/docs/usage/security/etcd_encryption_config.md for more details. + items: + type: string + type: array + required: + - provider + type: object + featureGates: + additionalProperties: + type: boolean + description: FeatureGates contains information about enabled + feature gates. + type: object + goAwayChance: + description: |- + GoAwayChance can be used to prevent HTTP/2 clients from getting stuck on a single apiserver, randomly close a + connection (GOAWAY). The client's other in-flight requests won't be affected, and the client will reconnect, + likely landing on a different apiserver after going through the load balancer again. This field sets the fraction + of requests that will be sent a GOAWAY. Min is 0 (off), Max is 0.02 (1/50 requests); 0.001 (1/1000) is a + recommended starting point. + maximum: 0.02 + minimum: 0 + type: number + logging: + description: Logging contains configuration for the log + level and HTTP access logs. + properties: + httpAccessVerbosity: + description: HTTPAccessVerbosity is the kube-apiserver + access logs level + format: int32 + type: integer + verbosity: + description: |- + Verbosity is the kube-apiserver log verbosity level + Defaults to 2. + format: int32 + type: integer + type: object + requests: + description: Requests contains configuration for request-specific + settings for the kube-apiserver. + properties: + maxMutatingInflight: + description: |- + MaxMutatingInflight is the maximum number of mutating requests in flight at a given time. When the server + exceeds this, it rejects requests. + format: int32 + type: integer + maxNonMutatingInflight: + description: |- + MaxNonMutatingInflight is the maximum number of non-mutating requests in flight at a given time. When the server + exceeds this, it rejects requests. + format: int32 + type: integer + type: object + shootAdminKubeconfigMaxExpiration: + description: |- + ShootAdminKubeconfigMaxExpiration is the maximum validity duration of a credential requested to a Shoot by an AdminKubeconfigRequest. + If an otherwise valid AdminKubeconfigRequest with a validity duration larger than this value is requested, + a credential will be issued with a validity duration of this value. + type: string + watchCacheSizes: + description: |- + WatchCacheSizes contains configuration of the API server's watch cache sizes. + Configuring these flags might be useful for large-scale Garden clusters with a lot of parallel update requests + and a lot of watching controllers (e.g. large ManagedSeed clusters). When the API server's watch cache's + capacity is too small to cope with the amount of update requests and watchers for a particular resource, it + might happen that controller watches are permanently stopped with `too old resource version` errors. + Starting from kubernetes v1.19, the API server's watch cache size is adapted dynamically and setting the watch + cache size flags will have no effect, except when setting it to 0 (which disables the watch cache). + properties: + default: + description: |- + Default is not respected anymore by kube-apiserver. + The cache is sized automatically. + + Deprecated: This field is deprecated. Setting the default cache size will be forbidden starting from Kubernetes 1.35. + format: int32 + type: integer + resources: + description: |- + Resources configures the watch cache size of the kube-apiserver per resource + (flag `--watch-cache-sizes`). + See: https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/ + items: + description: ResourceWatchCacheSize contains configuration + of the API server's watch cache size for one specific + resource. + properties: + apiGroup: + description: |- + APIGroup is the API group of the resource for which the watch cache size should be configured. + An unset value is used to specify the legacy core API (e.g. for `secrets`). + type: string + resource: + description: |- + Resource is the name of the resource for which the watch cache size should be configured + (in lowercase plural form, e.g. `secrets`). + type: string + size: + description: CacheSize specifies the watch cache + size that should be configured for the specified + resource. + format: int32 + type: integer + required: + - resource + - size + type: object + type: array + type: object + type: object + gardenerAdmissionController: + description: AdmissionController contains configuration settings + for the gardener-admission-controller. + properties: + logLevel: + default: info + description: |- + LogLevel is the configured log level for the gardener-admission-controller. Must be one of [info,debug,error]. + Defaults to info. + enum: + - info + - debug + - error + type: string + resourceAdmissionConfiguration: + description: ResourceAdmissionConfiguration is the configuration + for resource size restrictions for arbitrary Group-Version-Kinds. + properties: + limits: + description: Limits contains configuration for resources + which are subjected to size limitations. + items: + description: ResourceLimit contains settings about + a kind and the size each resource should have + at most. + properties: + apiGroups: + description: APIGroups is the name of the APIGroup + that contains the limited resource. WildcardAll + represents all groups. + items: + type: string + type: array + apiVersions: + description: APIVersions is the version of the + resource. WildcardAll represents all versions. + items: + type: string + type: array + count: + description: Count specifies the maximum number + of resources of the given kind. Only cluster-scoped + resources are considered. + format: int64 + type: integer + resources: + description: Resources is the name of the resource + this rule applies to. WildcardAll represents + all resources. + items: + type: string + type: array + size: + anyOf: + - type: integer + - type: string + description: Size specifies the imposed limit. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + required: + - resources + type: object + type: array + operationMode: + description: OperationMode specifies the mode the + webhooks operates in. Allowed values are "block" + and "log". Defaults to "block". + type: string + unrestrictedSubjects: + description: UnrestrictedSubjects contains references + to users, groups, or service accounts which aren't + subjected to any resource size limit. + items: + description: |- + Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, + or a value for non-objects such as user and group names. + properties: + apiGroup: + description: |- + APIGroup holds the API group of the referenced subject. + Defaults to "" for ServiceAccount subjects. + Defaults to "rbac.authorization.k8s.io" for User and Group subjects. + type: string + kind: + description: |- + Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". + If the Authorizer does not recognized the kind value, the Authorizer should report an error. + type: string + name: + description: Name of the object being referenced. + type: string + namespace: + description: |- + Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty + the Authorizer should report an error. + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + type: array + required: + - limits + type: object + type: object + gardenerControllerManager: + description: ControllerManager contains configuration settings + for the gardener-controller-manager. + properties: + defaultProjectQuotas: + description: |- + DefaultProjectQuotas is the default configuration matching projects are set up with if a quota is not already + specified. + items: + description: ProjectQuotaConfiguration defines quota + configurations. + properties: + config: + description: Config is the corev1.ResourceQuota + specification used for the project set-up. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + description: |- + Standard object's metadata. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + type: object + spec: + description: |- + Spec defines the desired quota. + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status + properties: + hard: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + hard is the set of desired hard limits for each named resource. + More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/ + type: object + scopeSelector: + description: |- + scopeSelector is also a collection of filters like scopes that must match each object tracked by a quota + but expressed using ScopeSelectorOperator in combination with possible values. + For a resource to match, both scopes AND scopeSelector (if specified in spec), must be matched. + properties: + matchExpressions: + description: A list of scope selector + requirements by scope of the resources. + items: + description: |- + A scoped-resource selector requirement is a selector that contains values, a scope name, and an operator + that relates the scope name and values. + properties: + operator: + description: |- + Represents a scope's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. + type: string + scopeName: + description: The name of the scope + that the selector applies to. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - operator + - scopeName + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + scopes: + description: |- + A collection of filters that must match each object tracked by a quota. + If not specified, the quota matches all objects. + items: + description: A ResourceQuotaScope defines + a filter that must match each object + tracked by a quota + type: string + type: array + x-kubernetes-list-type: atomic + type: object + status: + description: |- + Status defines the actual enforced quota and its current usage. + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status + properties: + hard: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Hard is the set of enforced hard limits for each named resource. + More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/ + type: object + used: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Used is the current observed + total usage of the resource in the namespace. + type: object + type: object + type: object + projectSelector: + description: |- + ProjectSelector is an optional setting to select the projects considered for quotas. + Defaults to empty LabelSelector, which matches all projects. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - config + type: object + type: array + featureGates: + additionalProperties: + type: boolean + description: FeatureGates contains information about enabled + feature gates. + type: object + logLevel: + default: info + description: |- + LogLevel is the configured log level for the gardener-controller-manager. Must be one of [info,debug,error]. + Defaults to info. + enum: + - info + - debug + - error + type: string + type: object + gardenerDashboard: + description: Dashboard contains configuration settings for + the gardener-dashboard. + properties: + assetsConfigMapRef: + description: AssetsConfigMapRef is the reference to a + ConfigMap in the garden namespace containing the assets + (logos/icons). + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + enableTokenLogin: + default: true + description: |- + EnableTokenLogin specifies whether it is possible to log into the dashboard with a JWT token. If disabled, OIDC + must be configured. + type: boolean + frontendConfigMapRef: + description: |- + FrontendConfigMapRef is the reference to a ConfigMap in the garden namespace containing the frontend + configuration. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + gitHub: + description: GitHub contains configuration for the GitHub + ticketing feature. + properties: + apiURL: + default: https://api.github.com + description: APIURL is the URL to the GitHub API. + minLength: 1 + type: string + organisation: + description: Organisation is the name of the GitHub + organisation. + minLength: 1 + type: string + pollInterval: + description: |- + PollInterval is the interval of how often the GitHub API is polled for issue updates. This field is used as a + fallback mechanism to ensure state synchronization, even when there is a GitHub webhook configuration. If a + webhook event is missed or not successfully delivered, the polling will help catch up on any missed updates. + If this field is not provided and there is no 'webhookSecret' key in the referenced secret, it will be + implicitly defaulted to `15m`. + pattern: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$ + type: string + repository: + description: Repository is the name of the GitHub + repository. + minLength: 1 + type: string + secretRef: + description: SecretRef is the reference to a secret + in the garden namespace containing the GitHub credentials. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + required: + - apiURL + - organisation + - repository + - secretRef + type: object + ingress: + description: Ingress contains configuration for the ingress + settings. + properties: + enabled: + default: true + description: Enabled controls whether the Dashboard + Ingress resource will be deployed to the cluster. + type: boolean + type: object + logLevel: + default: info + description: |- + LogLevel is the configured log level. Must be one of [trace,debug,info,warn,error]. + Defaults to info. + enum: + - trace + - debug + - info + - warn + - error + type: string + oidcConfig: + description: OIDCConfig contains configuration for the + OIDC provider. This field must be provided when EnableTokenLogin + is false. + properties: + additionalScopes: + description: AdditionalScopes is the list of additional + OIDC scopes. + items: + type: string + type: array + certificateAuthoritySecretRef: + description: CertificateAuthoritySecretRef is the + reference to a secret in the garden namespace containing + a custom CA certificate under the "ca.crt" key + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + clientIDPublic: + description: |- + ClientIDPublic is the public client ID. + Falls back to the API server's OIDC client ID configuration if not set here. + minLength: 1 + type: string + issuerURL: + description: |- + The URL of the OpenID issuer, only HTTPS scheme will be accepted. Used to verify the OIDC JSON Web Token (JWT). + Falls back to the API server's OIDC issuer URL configuration if not set here. + minLength: 1 + type: string + secretRef: + description: SecretRef is the reference to a secret + in the garden namespace containing the OIDC client + ID and secret for the dashboard. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + sessionLifetime: + description: SessionLifetime is the maximum duration + of a session. + pattern: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$ + type: string + required: + - secretRef + type: object + propagateCAFromSNI: + description: |- + PropagateCAFromSNI specifies whether to propagate the CA certificate from the kube-apiserver + SNI TLS secret to the dashboard's apiServerCaData configuration (used for all kubeconfigs + generated by the dashboard, e.g. for terminal sessions, OIDC login, or service account access). + Enable this when the CA that signed the SNI TLS certificate is not present + in the clients' trust stores (e.g. a private CA not distributed to end users). + When the CA is already trusted by clients — whether publicly trusted (e.g. Let's Encrypt) + or a corporate CA installed in client trust stores — leave this disabled to allow + transparent CA rotation without requiring kubeconfig re-downloads. + This field is only relevant when .spec.virtualCluster.kubernetes.kubeAPIServer.sni is configured. + Defaults to false. + type: boolean + terminal: + description: Terminal contains configuration for the terminal + settings. + properties: + allowedHosts: + description: |- + AllowedHosts should consist of permitted hostnames (without the scheme) for terminal connections. + It is important to consider that the usage of wildcards follows the rules defined by the content security policy. + '*.seed.local.gardener.cloud', or '*.other-seeds.local.gardener.cloud'. For more information, see + https://github.com/gardener/dashboard/blob/master/docs/operations/webterminals.md#allowlist-for-hosts. + items: + type: string + type: array + container: + description: Container contains configuration for + the dashboard terminal container. + properties: + description: + description: Description is a description for + the dashboard terminal container with hints + for the user. + type: string + image: + description: Image is the container image for + the dashboard terminal container. + type: string + required: + - image + type: object + required: + - container + type: object + type: object + gardenerDiscoveryServer: + description: |- + DiscoveryServer contains configuration settings for the gardener-discovery-server. + Once enabled, the gardener-discovery-server deployment cannot be removed and its domain cannot be changed. + Otherwise, workload identity and/or shoot service account tokens referencing the gardener-discovery-server in the + issuer URL might become unusable. + This field is optional, but once set, it cannot be removed anymore. + properties: + domain: + description: |- + Domain overrides the default ingress domain and optionally the DNS provider for the gardener-discovery-server. + This field is optional, but once the gardener-discovery-server is enabled, its domain cannot be changed anymore. + Defaults to "discovery.". + properties: + name: + description: Name is the domain name. + minLength: 1 + type: string + provider: + description: |- + Provider is the name of the DNS provider as declared in the '.spec.dns.providers' section. + It is only optional, if the `.spec.dns` section is not provided at all. + type: string + required: + - name + type: object + tlsSecretName: + description: |- + TLSSecretName is the name of a secret (in the garden namespace) containing + a trusted TLS certificate for the domain. If not configured, Gardener falls + back to a secret labelled with 'gardener.cloud/role=garden-cert', if in turn not + configured it generates a self-signed certificate. + type: string + type: object + gardenerResourceManager: + description: ResourceManager contains configuration settings + for the gardener-resource-manager. + properties: + additionalTargetNamespaces: + description: AdditionalTargetNamespaces allows specifying + custom target namespaces for the gardener-resource-manager + instance. + items: + type: string + type: array + type: object + gardenerScheduler: + description: Scheduler contains configuration settings for + the gardener-scheduler. + properties: + featureGates: + additionalProperties: + type: boolean + description: FeatureGates contains information about enabled + feature gates. + type: object + logLevel: + default: info + description: |- + LogLevel is the configured log level for the gardener-scheduler. Must be one of [info,debug,error]. + Defaults to info. + enum: + - info + - debug + - error + type: string + type: object + required: + - clusterIdentity + type: object + kubernetes: + description: |- + Kubernetes contains the version and configuration options for the Kubernetes components of the virtual garden + cluster. + properties: + kubeAPIServer: + description: KubeAPIServer contains configuration settings + for the kube-apiserver. + properties: + admissionPlugins: + description: |- + AdmissionPlugins contains the list of user-defined admission plugins (additional to those managed by Gardener), and, if desired, the corresponding + configuration. + items: + description: AdmissionPlugin contains information about + a specific admission plugin and its corresponding + configuration. + properties: + config: + description: Config is the configuration of the + plugin. + type: object + x-kubernetes-preserve-unknown-fields: true + disabled: + description: Disabled specifies whether this plugin + should be disabled. + type: boolean + kubeconfigSecretName: + description: KubeconfigSecretName specifies the + name of a secret containing the kubeconfig for + this admission plugin. + type: string + name: + description: Name is the name of the plugin. + type: string + required: + - name + type: object + type: array + apiAudiences: + description: |- + APIAudiences are the identifiers of the API. The service account token authenticator will + validate that tokens used against the API are bound to at least one of these audiences. + Defaults to ["kubernetes"]. + items: + type: string + type: array + auditConfig: + description: AuditConfig contains configuration settings + for the audit of the kube-apiserver. + properties: + auditPolicy: + description: AuditPolicy contains configuration settings + for audit policy of the kube-apiserver. + properties: + configMapRef: + description: |- + ConfigMapRef is a reference to a ConfigMap object in the same namespace, + which contains the audit policy for the kube-apiserver. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + type: object + type: object + auditWebhook: + description: AuditWebhook contains settings related to + an audit webhook configuration. + properties: + batchMaxSize: + default: 30 + description: BatchMaxSize is the maximum size of a + batch. + format: int32 + minimum: 1 + type: integer + kubeconfigSecretName: + description: KubeconfigSecretName specifies the name + of a secret containing the kubeconfig for this webhook. + minLength: 1 + type: string + version: + default: audit.k8s.io/v1 + description: Version is the API version to send and + expect from the webhook. + enum: + - audit.k8s.io/v1 + type: string + required: + - kubeconfigSecretName + type: object + authentication: + description: Authentication contains settings related + to authentication. + properties: + webhook: + description: Webhook contains settings related to + an authentication webhook configuration. + properties: + cacheTTL: + description: CacheTTL is the duration to cache + responses from the webhook authenticator. + pattern: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$ + type: string + kubeconfigSecretName: + description: KubeconfigSecretName specifies the + name of a secret containing the kubeconfig for + this webhook. + minLength: 1 + type: string + version: + default: v1beta1 + description: Version is the API version to send + and expect from the webhook. + enum: + - v1alpha1 + - v1beta1 + - v1 + type: string + required: + - kubeconfigSecretName + type: object + type: object + autoscaling: + description: Autoscaling contains auto-scaling configuration + options for the kube-apiserver. + properties: + minAllowed: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + MinAllowed configures the minimum allowed resource requests for vertical pod autoscaling.. + Configuration of minAllowed resources is an advanced feature that can help clusters to overcome scale-up delays. + Default values are not applied to this field. + type: object + required: + - minAllowed + type: object + defaultNotReadyTolerationSeconds: + description: |- + DefaultNotReadyTolerationSeconds indicates the tolerationSeconds of the toleration for notReady:NoExecute + that is added by default to every pod that does not already have such a toleration (flag `--default-not-ready-toleration-seconds`). + The field has effect only when the `DefaultTolerationSeconds` admission plugin is enabled. + Defaults to 300. + format: int64 + type: integer + defaultUnreachableTolerationSeconds: + description: |- + DefaultUnreachableTolerationSeconds indicates the tolerationSeconds of the toleration for unreachable:NoExecute + that is added by default to every pod that does not already have such a toleration (flag `--default-unreachable-toleration-seconds`). + The field has effect only when the `DefaultTolerationSeconds` admission plugin is enabled. + Defaults to 300. + format: int64 + type: integer + enableAnonymousAuthentication: + description: |- + EnableAnonymousAuthentication defines whether anonymous requests to the secure port + of the API server should be allowed (flag `--anonymous-auth`). + See: https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/ + + Deprecated: This field is deprecated and will be removed after support for Kubernetes v1.34 is dropped. + This field is forbidden for clusters with Kubernetes version >= 1.35. + Please use anonymous authentication configuration instead. + type: boolean + encryptionConfig: + description: EncryptionConfig contains customizable encryption + configuration of the Kube API server. + properties: + provider: + description: Provider contains information about the + encryption provider. + properties: + type: + description: |- + Type contains the type of the encryption provider. + + Supported types: + - "aescbc" + - "aesgcm" + - "secretbox" + Defaults to aescbc. + type: string + type: object + resources: + description: |- + Resources contains the list of resources that shall be encrypted in addition to secrets. + Each item is a Kubernetes resource name in plural (resource or resource.group) that should be encrypted. + Wildcards are not supported for now. + See https://github.com/gardener/gardener/blob/master/docs/usage/security/etcd_encryption_config.md for more details. + items: + type: string + type: array + required: + - provider + type: object + eventTTL: + description: |- + EventTTL controls the amount of time to retain events. + Defaults to 1h. + type: string + featureGates: + additionalProperties: + type: boolean + description: FeatureGates contains information about enabled + feature gates. + type: object + logging: + description: Logging contains configuration for the log + level and HTTP access logs. + properties: + httpAccessVerbosity: + description: HTTPAccessVerbosity is the kube-apiserver + access logs level + format: int32 + type: integer + verbosity: + description: |- + Verbosity is the kube-apiserver log verbosity level + Defaults to 2. + format: int32 + type: integer + type: object + requests: + description: Requests contains configuration for request-specific + settings for the kube-apiserver. + properties: + maxMutatingInflight: + description: |- + MaxMutatingInflight is the maximum number of mutating requests in flight at a given time. When the server + exceeds this, it rejects requests. + format: int32 + type: integer + maxNonMutatingInflight: + description: |- + MaxNonMutatingInflight is the maximum number of non-mutating requests in flight at a given time. When the server + exceeds this, it rejects requests. + format: int32 + type: integer + type: object + resourcesToStoreInETCDEvents: + description: |- + ResourcesToStoreInETCDEvents contains a list of resources which should be stored in etcd-events instead of + etcd-main. The 'events' resource is always stored in etcd-events. Note that adding or removing resources from + this list will not migrate them automatically from the etcd-main to etcd-events or vice versa. + items: + description: GroupResource contains a list of resources + which should be stored in etcd-events instead of etcd-main. + properties: + group: + description: Group is the API group name. + minLength: 1 + type: string + resource: + description: Resource is the resource name. + minLength: 1 + type: string + required: + - group + - resource + type: object + type: array + runtimeConfig: + additionalProperties: + type: boolean + description: RuntimeConfig contains information about + enabled or disabled APIs. + type: object + serviceAccountConfig: + description: |- + ServiceAccountConfig contains configuration settings for the service account handling + of the kube-apiserver. + properties: + acceptedIssuers: + description: |- + AcceptedIssuers is an additional set of issuers that are used to determine which service account tokens are accepted. + These values are not used to generate new service account tokens. Only useful when service account tokens are also + issued by another external system or a change of the current issuer that is used for generating tokens is being performed. + items: + type: string + type: array + extendTokenExpiration: + description: |- + ExtendTokenExpiration turns on projected service account expiration extension during token generation, which + helps safe transition from legacy token to bound service account token feature. If this flag is enabled, + admission injected tokens would be extended up to 1 year to prevent unexpected failure during transition, + ignoring value of service-account-max-token-expiration. + type: boolean + issuer: + description: |- + Issuer is the identifier of the service account token issuer. The issuer will assert this + identifier in "iss" claim of issued tokens. This value is used to generate new service account tokens. + This value is a string or URI. Defaults to URI of the API server. + type: string + maxTokenExpiration: + description: |- + MaxTokenExpiration is the maximum validity duration of a token created by the service account token issuer. If an + otherwise valid TokenRequest with a validity duration larger than this value is requested, a token will be issued + with a validity duration of this value. + This field must be within [30d,90d]. + type: string + type: object + sni: + description: SNI contains configuration options for the + TLS SNI settings. + properties: + domainPatterns: + description: |- + DomainPatterns is a list of fully qualified domain names, possibly with prefixed wildcard segments. The domain + patterns also allow IP addresses, but IPs should only be used if the apiserver has visibility to the IP address + requested by a client. If no domain patterns are provided, the names of the certificate are extracted. + Non-wildcard matches trump over wildcard matches, explicit domain patterns trump over extracted names. + items: + type: string + type: array + secretName: + description: |- + SecretName is the name of a secret containing the TLS certificate and private key. + If not configured, Gardener falls back to a secret labelled with 'gardener.cloud/role=garden-cert'. + minLength: 1 + type: string + type: object + structuredAuthentication: + description: StructuredAuthentication contains configuration + settings for structured authentication for the kube-apiserver. + properties: + configMapName: + description: |- + ConfigMapName is the name of the ConfigMap in the project namespace which contains AuthenticationConfiguration + for the kube-apiserver. + type: string + required: + - configMapName + type: object + structuredAuthorization: + description: StructuredAuthorization contains configuration + settings for structured authorization for the kube-apiserver. + properties: + configMapName: + description: |- + ConfigMapName is the name of the ConfigMap in the project namespace which contains AuthorizationConfiguration for + the kube-apiserver. + type: string + kubeconfigs: + description: Kubeconfigs is a list of references for + kubeconfigs for the authorization webhooks. + items: + description: AuthorizerKubeconfigReference is a + reference for a kubeconfig for a authorization + webhook. + properties: + authorizerName: + description: AuthorizerName is the name of a + webhook authorizer. + type: string + secretName: + description: SecretName is the name of a secret + containing the kubeconfig. + type: string + required: + - authorizerName + - secretName + type: object + type: array + required: + - configMapName + - kubeconfigs + type: object + watchCacheSizes: + description: |- + WatchCacheSizes contains configuration of the API server's watch cache sizes. + Configuring these flags might be useful for large-scale Shoot clusters with a lot of parallel update requests + and a lot of watching controllers (e.g. large ManagedSeed clusters). When the API server's watch cache's + capacity is too small to cope with the amount of update requests and watchers for a particular resource, it + might happen that controller watches are permanently stopped with `too old resource version` errors. + Starting from kubernetes v1.19, the API server's watch cache size is adapted dynamically and setting the watch + cache size flags will have no effect, except when setting it to 0 (which disables the watch cache). + properties: + default: + description: |- + Default is not respected anymore by kube-apiserver. + The cache is sized automatically. + + Deprecated: This field is deprecated. Setting the default cache size will be forbidden starting from Kubernetes 1.35. + format: int32 + type: integer + resources: + description: |- + Resources configures the watch cache size of the kube-apiserver per resource + (flag `--watch-cache-sizes`). + See: https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/ + items: + description: ResourceWatchCacheSize contains configuration + of the API server's watch cache size for one specific + resource. + properties: + apiGroup: + description: |- + APIGroup is the API group of the resource for which the watch cache size should be configured. + An unset value is used to specify the legacy core API (e.g. for `secrets`). + type: string + resource: + description: |- + Resource is the name of the resource for which the watch cache size should be configured + (in lowercase plural form, e.g. `secrets`). + type: string + size: + description: CacheSize specifies the watch cache + size that should be configured for the specified + resource. + format: int32 + type: integer + required: + - resource + - size + type: object + type: array + type: object + type: object + kubeControllerManager: + description: KubeControllerManager contains configuration + settings for the kube-controller-manager. + properties: + certificateSigningDuration: + default: 48h + description: |- + CertificateSigningDuration is the maximum length of duration signed certificates will be given. Individual CSRs + may request shorter certs by setting `spec.expirationSeconds`. + pattern: ^([0-9]+(\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$ + type: string + featureGates: + additionalProperties: + type: boolean + description: FeatureGates contains information about enabled + feature gates. + type: object + horizontalPodAutoscaler: + description: HorizontalPodAutoscalerConfig contains horizontal + pod autoscaler configuration settings for the kube-controller-manager. + properties: + cpuInitializationPeriod: + description: The period after which a ready pod transition + is considered to be the first. + type: string + downscaleStabilization: + description: The configurable window at which the + controller will choose the highest recommendation + for autoscaling. + type: string + initialReadinessDelay: + description: The configurable period at which the + horizontal pod autoscaler considers a Pod “not yet + ready” given that it’s unready and it has transitioned + to unready during that time. + type: string + syncPeriod: + description: The period for syncing the number of + pods in horizontal pod autoscaler. + type: string + tolerance: + description: The minimum change (from 1.0) in the + desired-to-actual metrics ratio for the horizontal + pod autoscaler to consider scaling. + type: number + type: object + nodeCIDRMaskSize: + description: NodeCIDRMaskSize defines the mask size for + node cidr in cluster (default is 24). This field is + immutable. + format: int32 + type: integer + nodeCIDRMaskSizeIPv6: + description: NodeCIDRMaskSizeIPv6 defines the mask size + for node cidr in cluster (default is 64). This field + is immutable. + format: int32 + type: integer + nodeMonitorGracePeriod: + description: NodeMonitorGracePeriod defines the grace + period before an unresponsive node is marked unhealthy. + type: string + podEvictionTimeout: + description: |- + PodEvictionTimeout defines the grace period for deleting pods on failed nodes. Defaults to 2m. + + Deprecated: The corresponding kube-controller-manager flag `--pod-eviction-timeout` is deprecated + in favor of the kube-apiserver flags `--default-not-ready-toleration-seconds` and `--default-unreachable-toleration-seconds`. + The `--pod-eviction-timeout` flag does not have effect when the taint based eviction is enabled. The taint + based eviction is beta (enabled by default) since Kubernetes 1.13 and GA since Kubernetes 1.18. Hence, + instead of setting this field, set the `spec.kubernetes.kubeAPIServer.defaultNotReadyTolerationSeconds` and + `spec.kubernetes.kubeAPIServer.defaultUnreachableTolerationSeconds`. Setting this field is forbidden starting + from Kubernetes 1.33. + type: string + type: object + version: + description: Version is the semantic Kubernetes version to + use for the virtual garden cluster. + minLength: 1 + type: string + required: + - version + type: object + maintenance: + description: Maintenance contains information about the time window + for maintenance operations. + properties: + timeWindow: + description: TimeWindow contains information about the time + window for maintenance operations. + properties: + begin: + description: |- + Begin is the beginning of the time window in the format HHMMSS+ZONE, e.g. "220000+0100". + If not present, a random value will be computed. + pattern: ([0-1][0-9]|2[0-3])[0-5][0-9][0-5][0-9]\+[0-1][0-4]00 + type: string + end: + description: |- + End is the end of the time window in the format HHMMSS+ZONE, e.g. "220000+0100". + If not present, the value will be computed based on the "Begin" value. + pattern: ([0-1][0-9]|2[0-3])[0-5][0-9][0-5][0-9]\+[0-1][0-4]00 + type: string + required: + - begin + - end + type: object + required: + - timeWindow + type: object + networking: + description: Networking contains information about cluster networking + such as CIDRs, etc. + properties: + services: + description: Services are the CIDRs of the service network. + Elements can be appended to this list, but not removed. + items: + type: string + minItems: 1 + type: array + required: + - services + type: object + required: + - dns + - gardener + - kubernetes + - maintenance + - networking + type: object + required: + - runtimeCluster + - virtualCluster + type: object + status: + description: Status contains the status of this garden. + properties: + conditions: + description: Conditions is a list of conditions. + items: + description: Condition holds the information about the state of + a resource. + properties: + codes: + description: Well-defined error codes in case the condition + reports a problem. + items: + description: ErrorCode is a string alias. + type: string + type: array + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. + format: date-time + type: string + lastUpdateTime: + description: Last time the condition was updated. + format: date-time + type: string + message: + description: A human readable message indicating details about + the transition. + type: string + reason: + description: The reason for the condition's last transition. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: Type of the condition. + type: string + required: + - lastTransitionTime + - lastUpdateTime + - message + - reason + - status + - type + type: object + type: array + credentials: + description: Credentials contains information about the virtual garden + cluster credentials. + properties: + encryptionAtRest: + description: EncryptionAtRest contains information about garden + data encryption at rest. + properties: + provider: + description: Provider contains information about virtual garden + encryption provider. + properties: + type: + description: Type is the used encryption provider type. + type: string + required: + - type + type: object + resources: + description: |- + Resources is the list of resources which are currently encrypted in the virtual garden by the virtual kube-apiserver. + Resources which are encrypted by default will not appear here. + See https://github.com/gardener/gardener/blob/master/docs/concepts/operator.md#etcd-encryption-config for more details. + items: + type: string + type: array + required: + - provider + type: object + rotation: + description: Rotation contains information about the credential + rotations. + properties: + certificateAuthorities: + description: CertificateAuthorities contains information about + the certificate authority credential rotation. + properties: + lastCompletionTime: + description: |- + LastCompletionTime is the most recent time when the certificate authority credential rotation was successfully + completed. + format: date-time + type: string + lastCompletionTriggeredTime: + description: |- + LastCompletionTriggeredTime is the recent time when the certificate authority credential rotation completion was + triggered. + format: date-time + type: string + lastInitiationFinishedTime: + description: |- + LastInitiationFinishedTime is the recent time when the certificate authority credential rotation initiation was + completed. + format: date-time + type: string + lastInitiationTime: + description: LastInitiationTime is the most recent time + when the certificate authority credential rotation was + initiated. + format: date-time + type: string + pendingWorkersRollouts: + description: |- + PendingWorkersRollouts contains the name of a worker pool and the initiation time of their last rollout due to + credentials rotation. + items: + description: PendingWorkersRollout contains the name + of a worker pool and the initiation time of their + last rollout. + properties: + lastInitiationTime: + description: LastInitiationTime is the most recent + time when the worker rollout was initiated. + format: date-time + type: string + name: + description: Name is the name of a worker pool. + type: string + required: + - name + type: object + type: array + phase: + description: Phase describes the phase of the certificate + authority credential rotation. + type: string + required: + - phase + type: object + etcdEncryptionKey: + description: ETCDEncryptionKey contains information about + the ETCD encryption key credential rotation. + properties: + autoCompleteAfterPrepared: + description: |- + AutoCompleteAfterPrepared indicates whether the current ETCD encryption key rotation should be auto completed after the preparation phase has finished. + Such rotation can be triggered by the `rotate-etcd-encryption-key` annotation. + This field is needed while we support two types of key rotations: two-operation and single operation rotation. + + Deprecated: This field will be removed in a future release. The field will be no longer needed with + the removal `rotate-etcd-encryption-key-start` & `rotate-etcd-encryption-key-complete` annotations. + type: boolean + lastCompletionTime: + description: |- + LastCompletionTime is the most recent time when the ETCD encryption key credential rotation was successfully + completed. + format: date-time + type: string + lastCompletionTriggeredTime: + description: |- + LastCompletionTriggeredTime is the recent time when the ETCD encryption key credential rotation completion was + triggered. + format: date-time + type: string + lastInitiationFinishedTime: + description: |- + LastInitiationFinishedTime is the recent time when the ETCD encryption key credential rotation initiation was + completed. + format: date-time + type: string + lastInitiationTime: + description: LastInitiationTime is the most recent time + when the ETCD encryption key credential rotation was + initiated. + format: date-time + type: string + phase: + description: Phase describes the phase of the ETCD encryption + key credential rotation. + type: string + required: + - phase + type: object + observability: + description: Observability contains information about the + observability credential rotation. + properties: + lastCompletionTime: + description: LastCompletionTime is the most recent time + when the observability credential rotation was successfully + completed. + format: date-time + type: string + lastInitiationTime: + description: LastInitiationTime is the most recent time + when the observability credential rotation was initiated. + format: date-time + type: string + type: object + serviceAccountKey: + description: ServiceAccountKey contains information about + the service account key credential rotation. + properties: + lastCompletionTime: + description: |- + LastCompletionTime is the most recent time when the service account key credential rotation was successfully + completed. + format: date-time + type: string + lastCompletionTriggeredTime: + description: |- + LastCompletionTriggeredTime is the recent time when the service account key credential rotation completion was + triggered. + format: date-time + type: string + lastInitiationFinishedTime: + description: |- + LastInitiationFinishedTime is the recent time when the service account key credential rotation initiation was + completed. + format: date-time + type: string + lastInitiationTime: + description: LastInitiationTime is the most recent time + when the service account key credential rotation was + initiated. + format: date-time + type: string + pendingWorkersRollouts: + description: |- + PendingWorkersRollouts contains the name of a worker pool and the initiation time of their last rollout due to + credentials rotation. + items: + description: PendingWorkersRollout contains the name + of a worker pool and the initiation time of their + last rollout. + properties: + lastInitiationTime: + description: LastInitiationTime is the most recent + time when the worker rollout was initiated. + format: date-time + type: string + name: + description: Name is the name of a worker pool. + type: string + required: + - name + type: object + type: array + phase: + description: Phase describes the phase of the service + account key credential rotation. + type: string + required: + - phase + type: object + workloadIdentityKey: + description: WorkloadIdentityKey contains information about + the workload identity key credential rotation. + properties: + lastCompletionTime: + description: |- + LastCompletionTime is the most recent time when the workload identity key credential rotation was successfully + completed. + format: date-time + type: string + lastCompletionTriggeredTime: + description: |- + LastCompletionTriggeredTime is the recent time when the workload identity key credential rotation completion was + triggered. + format: date-time + type: string + lastInitiationFinishedTime: + description: |- + LastInitiationFinishedTime is the recent time when the workload identity key credential rotation initiation was + completed. + format: date-time + type: string + lastInitiationTime: + description: LastInitiationTime is the most recent time + when the workload identity key credential rotation was + initiated. + format: date-time + type: string + phase: + description: Phase describes the phase of the workload + identity key credential rotation. + type: string + required: + - phase + type: object + type: object + type: object + gardener: + description: Gardener holds information about the Gardener which last + acted on the Garden. + properties: + id: + description: ID is the container id of the Gardener which last + acted on a resource. + type: string + name: + description: Name is the hostname (pod name) of the Gardener which + last acted on a resource. + type: string + version: + description: Version is the version of the Gardener which last + acted on a resource. + type: string + required: + - id + - name + - version + type: object + lastOperation: + description: LastOperation holds information about the last operation + on the Garden. + properties: + description: + description: A human readable message indicating details about + the last operation. + type: string + lastUpdateTime: + description: Last time the operation state transitioned from one + to another. + format: date-time + type: string + progress: + description: The progress in percentage (0-100) of the last operation. + format: int32 + type: integer + state: + description: Status of the last operation, one of Aborted, Processing, + Succeeded, Error, Failed. + type: string + type: + description: Type of the last operation, one of Create, Reconcile, + Delete, Migrate, Restore. + type: string + required: + - description + - lastUpdateTime + - progress + - state + - type + type: object + observedGeneration: + description: ObservedGeneration is the most recent generation observed + for this resource. + format: int64 + type: integer + virtualClusterStatus: + description: VirtualClusterStatus holds information about the virtual + garden cluster + properties: + advertisedAddresses: + description: |- + List of addresses that are relevant to the Garden. + These include the Kube API server address of the virtual garden cluster. + items: + description: AdvertisedAddress contains information for the + Garden's servers. + properties: + name: + description: Name of the advertised address. e.g. virtual + or discovery-server + type: string + url: + description: The URL of the server. e.g. https://api.foo.bar + or https://1.2.3.4 + type: string + required: + - name + - url + type: object + type: array + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} + From 5cdd131f410ab335d8e24351ba9e39e7364f31c5 Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Mon, 18 May 2026 17:19:21 +0200 Subject: [PATCH 06/25] delete managed resource of garden extension Signed-off-by: Lukas Hoehl --- pkg/controller/actuator.go | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/pkg/controller/actuator.go b/pkg/controller/actuator.go index 07492846..fd687f8e 100644 --- a/pkg/controller/actuator.go +++ b/pkg/controller/actuator.go @@ -245,7 +245,12 @@ func (a *actuator) Delete(ctx context.Context, log logr.Logger, ex *extensionsv1 namespace := ex.GetNamespace() log.Info("Component is being deleted", "component", "", "namespace", namespace) - return a.deleteSeedResources(ctx, log, namespace) + mrName := ResourceNameSeed + if ptr.Deref(ex.GetExtensionSpec().GetExtensionClass(), extensionsv1alpha1.ExtensionClassShoot) == extensionsv1alpha1.ExtensionClassGarden { + mrName = ResourceNameGarden + } + + return a.deleteManagedResource(ctx, log, namespace, mrName) } // ForceDelete implements Network.Actuator. @@ -263,7 +268,7 @@ func (a *actuator) Migrate(ctx context.Context, log logr.Logger, ex *extensionsv return a.Delete(ctx, log, ex) } -func (a *actuator) createSeedResources( +func (a *actuator) createFilters( ctx context.Context, log logr.Logger, namespace string, @@ -358,16 +363,16 @@ func (v values) AsMap() map[string]any { return m } -func (a *actuator) deleteSeedResources(ctx context.Context, log logr.Logger, namespace string) error { - log.Info("Deleting managed resource for seed", "namespace", namespace) +func (a *actuator) deleteManagedResource(ctx context.Context, log logr.Logger, namespace, name string) error { + log.Info("Deleting managed resource", "namespace", namespace) - if err := managedresources.Delete(ctx, a.client, namespace, ResourceNameSeed, false); err != nil { + if err := managedresources.Delete(ctx, a.client, namespace, name, false); err != nil { return err } timeoutCtx, cancel := context.WithTimeout(ctx, deletionTimeout) defer cancel() - return managedresources.WaitUntilDeleted(timeoutCtx, a.client, namespace, ResourceNameSeed) + return managedresources.WaitUntilDeleted(timeoutCtx, a.client, namespace, name) } func (a *actuator) createManagedResource( From 615cee11ecbc15ba8d9b9848d8640a9c63d7a792 Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Wed, 27 May 2026 14:34:50 +0200 Subject: [PATCH 07/25] fix deployment manifest for controller Signed-off-by: Lukas Hoehl --- charts/gardener-extension-acl/templates/deployment.yaml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/charts/gardener-extension-acl/templates/deployment.yaml b/charts/gardener-extension-acl/templates/deployment.yaml index 322e542d..f8b3cd6a 100644 --- a/charts/gardener-extension-acl/templates/deployment.yaml +++ b/charts/gardener-extension-acl/templates/deployment.yaml @@ -25,9 +25,7 @@ spec: networking.resources.gardener.cloud/to-garden-virtual-garden-kube-apiserver-tcp-443: allowed {{ include "labels" . | indent 8 }} spec: - {{- if .Values.gardener.runtimeCluster.priorityClassName }} - priorityClassName: {{ .Values.gardener.runtimeCluster.priorityClassName }} - {{- end }} + priorityClassName: {{ default "gardener-system-900" .Values.gardener.runtimeCluster.priorityClassName }} serviceAccountName: {{ include "name" . }} containers: - name: {{ include "name" . }} @@ -54,7 +52,7 @@ spec: env: {{- if .Values.gardener.runtimeCluster.enabled }} - name: GARDEN_KUBECONFIG - value: /var/run/secrets/gardener.cloud/shoot/generic-kubeconfig/kubeconfig + value: /var/run/secrets/gardener.cloud/garden/generic-kubeconfig/kubeconfig {{- end }} - name: LEADER_ELECTION_NAMESPACE valueFrom: @@ -80,7 +78,7 @@ spec: volumeMounts: {{- if .Values.gardener.runtimeCluster.enabled }} - name: kubeconfig - mountPath: /var/run/secrets/gardener.cloud/shoot/generic-kubeconfig + mountPath: /var/run/secrets/gardener.cloud/garden/generic-kubeconfig readOnly: true {{- end }} {{- if .Values.imageVectorOverwrite }} From 943c5def5b38850539dcf31e3d3fa8b5d05e039f Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Wed, 27 May 2026 14:38:39 +0200 Subject: [PATCH 08/25] move garden specific allowed cidrs into own file Signed-off-by: Lukas Hoehl --- pkg/helper/garden.go | 11 +++++++++++ pkg/helper/seed.go | 9 --------- 2 files changed, 11 insertions(+), 9 deletions(-) create mode 100644 pkg/helper/garden.go diff --git a/pkg/helper/garden.go b/pkg/helper/garden.go new file mode 100644 index 00000000..760a052f --- /dev/null +++ b/pkg/helper/garden.go @@ -0,0 +1,11 @@ +package helper + +import operatorv1alpha1 "github.com/gardener/gardener/pkg/apis/operator/v1alpha1" + +// GetGardenSpecificAllowedCIDRs returns the node and pod CIDRs from the garden runtime cluster +func GetGardenSpecificAllowedCIDRs(garden *operatorv1alpha1.Garden) []string { + cidrs := make([]string, 0) + cidrs = append(cidrs, garden.Spec.RuntimeCluster.Networking.Nodes...) + cidrs = append(cidrs, garden.Spec.RuntimeCluster.Networking.Pods...) + return cidrs +} diff --git a/pkg/helper/seed.go b/pkg/helper/seed.go index 8ec3534d..da7b041f 100644 --- a/pkg/helper/seed.go +++ b/pkg/helper/seed.go @@ -2,7 +2,6 @@ package helper import ( "github.com/gardener/gardener/pkg/apis/core/v1beta1" - operatorv1alpha1 "github.com/gardener/gardener/pkg/apis/operator/v1alpha1" ) // GetSeedSpecificAllowedCIDRs returns the node and pod CIDRs from the seed @@ -25,11 +24,3 @@ func GetSeedIngressDomain(seed *v1beta1.Seed) string { } return domain } - -// GetGardenSpecificAllowedCIDRs returns the node and pod CIDRs from the garden runtime cluster -func GetGardenSpecificAllowedCIDRs(garden *operatorv1alpha1.Garden) []string { - cidrs := make([]string, 0) - cidrs = append(cidrs, garden.Spec.RuntimeCluster.Networking.Nodes...) - cidrs = append(cidrs, garden.Spec.RuntimeCluster.Networking.Pods...) - return cidrs -} From 204a8a41e6d35c4974dcfd3ac1a5f1a0b8058072 Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Wed, 27 May 2026 14:38:52 +0200 Subject: [PATCH 09/25] comment why to add node and pod cidr of runtime cluster to allowed Signed-off-by: Lukas Hoehl --- pkg/controller/allowedcidrs/garden.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/controller/allowedcidrs/garden.go b/pkg/controller/allowedcidrs/garden.go index b344d6f5..19ec0508 100644 --- a/pkg/controller/allowedcidrs/garden.go +++ b/pkg/controller/allowedcidrs/garden.go @@ -24,6 +24,7 @@ type Garden struct { // AllowedCIDRs returns always allowed cidrs for garden ACL func (g *Garden) AllowedCIDRs(ctx context.Context, _ *extensionsv1alpha1.Extension) ([]string, error) { var cidrs []string + // add node and pod CIDR from runtime cluster to ensure garden components (e.g. scheduler, controller-manager etc.) are able to access the virtual garden cidrs = append(cidrs, helper.GetGardenSpecificAllowedCIDRs(g.Garden)...) seedCidrs, err := g.managedSeedsEgressCIDRs(ctx) From ecd08d1673e8ed713b033f2884e7a2d0cadc3068 Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Wed, 27 May 2026 14:42:43 +0200 Subject: [PATCH 10/25] move rbac for extension classes into separate files Signed-off-by: Lukas Hoehl --- .../templates/rbac-garden.yaml | 32 ++++++++++++++ .../templates/rbac-shoot.yaml | 42 +++++++++++++++++++ .../templates/rbac.yaml | 31 +------------- 3 files changed, 75 insertions(+), 30 deletions(-) create mode 100644 charts/gardener-extension-acl/templates/rbac-garden.yaml create mode 100644 charts/gardener-extension-acl/templates/rbac-shoot.yaml diff --git a/charts/gardener-extension-acl/templates/rbac-garden.yaml b/charts/gardener-extension-acl/templates/rbac-garden.yaml new file mode 100644 index 00000000..1c6552d3 --- /dev/null +++ b/charts/gardener-extension-acl/templates/rbac-garden.yaml @@ -0,0 +1,32 @@ +{{- if .Values.gardener.runtimeCluster.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "name" . }}:garden + labels: +{{ include "labels" . | indent 4 }} +rules: +- apiGroups: + - operator.gardener.cloud + resources: + - gardens + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "name" . }}:garden + labels: +{{ include "labels" . | indent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "name" . }}:garden +subjects: +- kind: ServiceAccount + name: {{ include "name" . }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/charts/gardener-extension-acl/templates/rbac-shoot.yaml b/charts/gardener-extension-acl/templates/rbac-shoot.yaml new file mode 100644 index 00000000..f13938e1 --- /dev/null +++ b/charts/gardener-extension-acl/templates/rbac-shoot.yaml @@ -0,0 +1,42 @@ +{{- if not .Values.gardener.runtimeCluster.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "name" . }}:shoot + labels: +{{ include "labels" . | indent 4 }} +rules: +- apiGroups: + - extensions.gardener.cloud + resources: + - clusters + - dnsrecords + - infrastructures + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - services + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "name" . }}:shoot + labels: +{{ include "labels" . | indent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "name" . }}:shoot +subjects: +- kind: ServiceAccount + name: {{ include "name" . }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/charts/gardener-extension-acl/templates/rbac.yaml b/charts/gardener-extension-acl/templates/rbac.yaml index eefe4223..3d1972a9 100644 --- a/charts/gardener-extension-acl/templates/rbac.yaml +++ b/charts/gardener-extension-acl/templates/rbac.yaml @@ -18,35 +18,6 @@ rules: - delete resources: - envoyfilters -{{- if .Values.gardener.runtimeCluster.enabled }} -- apiGroups: - - operator.gardener.cloud - resources: - - gardens - verbs: - - get - - list - - watch -{{- else }} -- apiGroups: - - "" - resources: - - services - verbs: - - get - - list - - watch -- apiGroups: - - extensions.gardener.cloud - resources: - - clusters - - dnsrecords - - infrastructures - verbs: - - get - - list - - watch -{{- end }} - apiGroups: - extensions.gardener.cloud resources: @@ -208,4 +179,4 @@ roleRef: subjects: - kind: ServiceAccount name: {{ include "name" . }} - namespace: {{ .Release.Namespace }} \ No newline at end of file + namespace: {{ .Release.Namespace }} From e67326f720f697ba4124cdf8402a07a92e75b769 Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Wed, 27 May 2026 14:46:07 +0200 Subject: [PATCH 11/25] drop uneeded permissions Signed-off-by: Lukas Hoehl --- .../templates/rbac.yaml | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/charts/gardener-extension-acl/templates/rbac.yaml b/charts/gardener-extension-acl/templates/rbac.yaml index 3d1972a9..5e956f5f 100644 --- a/charts/gardener-extension-acl/templates/rbac.yaml +++ b/charts/gardener-extension-acl/templates/rbac.yaml @@ -49,28 +49,6 @@ rules: - get - list - watch -- apiGroups: - - apiextensions.k8s.io - resources: - - customresourcedefinitions - verbs: - - get - - create - - update - - patch -- apiGroups: - - rbac.authorization.k8s.io - resources: - - clusterroles - - clusterrolebindings - - roles - - rolebindings - verbs: - - get - - create - - update - - patch - - delete - apiGroups: - "" resources: From 2be0db3cc54fbaea3240d8476ae8ec10e61df6be Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Wed, 27 May 2026 14:51:45 +0200 Subject: [PATCH 12/25] restrict garden permissions to garden namespace Signed-off-by: Lukas Hoehl --- deploy/garden/rbac.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/deploy/garden/rbac.yaml b/deploy/garden/rbac.yaml index a0a125e7..fb39d54a 100644 --- a/deploy/garden/rbac.yaml +++ b/deploy/garden/rbac.yaml @@ -1,7 +1,8 @@ apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole +kind: Role metadata: - name: extension-acl-managedseeds + name: extensions.gardener.cloud:acl:managedseeds + namespace: garden annotations: authorization.gardener.cloud/extensions-serviceaccount-selector: '{"matchLabels":{"extension":"acl"}}' labels: From d114a2a289671f93bf6a637aa5ada4e37ecf2a65 Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Wed, 27 May 2026 14:52:24 +0200 Subject: [PATCH 13/25] kustomization for garden resources Signed-off-by: Lukas Hoehl --- deploy/garden/kustomization.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 deploy/garden/kustomization.yaml diff --git a/deploy/garden/kustomization.yaml b/deploy/garden/kustomization.yaml new file mode 100644 index 00000000..b5633ece --- /dev/null +++ b/deploy/garden/kustomization.yaml @@ -0,0 +1,4 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - rbac.yaml From c9ab15bd43e734ac9b570f19056cd55ba3f2c257 Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Wed, 27 May 2026 15:06:11 +0200 Subject: [PATCH 14/25] helper function to check if garden extension Signed-off-by: Lukas Hoehl --- pkg/controller/actuator.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pkg/controller/actuator.go b/pkg/controller/actuator.go index fd687f8e..c9b7615f 100644 --- a/pkg/controller/actuator.go +++ b/pkg/controller/actuator.go @@ -246,7 +246,7 @@ func (a *actuator) Delete(ctx context.Context, log logr.Logger, ex *extensionsv1 log.Info("Component is being deleted", "component", "", "namespace", namespace) mrName := ResourceNameSeed - if ptr.Deref(ex.GetExtensionSpec().GetExtensionClass(), extensionsv1alpha1.ExtensionClassShoot) == extensionsv1alpha1.ExtensionClassGarden { + if hasClassGarden(ex) { mrName = ResourceNameGarden } @@ -467,8 +467,7 @@ func (a *actuator) findIstioNamespaceForExtension( gw := istionetworkv1beta1.Gateway{} gatewayName := istioGatewayName - - if ex.Spec.Class != nil && *ex.Spec.Class == extensionsv1alpha1.ExtensionClassGarden { + if hasClassGarden(ex) { gatewayName = operatorv1alpha1.VirtualGardenNamePrefix + gatewayName } @@ -487,7 +486,7 @@ func (a *actuator) findIstioNamespaceForExtension( if err != nil { return "", nil, err } - if ex.Spec.Class != nil && *ex.Spec.Class == extensionsv1alpha1.ExtensionClassGarden { + if hasClassGarden(ex) { for _, dep := range deployments.Items { if dep.Namespace == operatorv1alpha1.VirtualGardenDefaultSNIIngressNamespace { return dep.Namespace, gw.Spec.Selector, nil From f279d500f2e01bc489c8c2e8d3827625388a892b Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Wed, 27 May 2026 15:10:39 +0200 Subject: [PATCH 15/25] requeue if no advertised addresses Signed-off-by: Lukas Hoehl --- pkg/controller/actuator.go | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/pkg/controller/actuator.go b/pkg/controller/actuator.go index c9b7615f..5a475e8b 100644 --- a/pkg/controller/actuator.go +++ b/pkg/controller/actuator.go @@ -30,6 +30,7 @@ import ( extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" operatorv1alpha1 "github.com/gardener/gardener/pkg/apis/operator/v1alpha1" "github.com/gardener/gardener/pkg/chartrenderer" + reconcilerutils "github.com/gardener/gardener/pkg/controllerutils/reconciler" "github.com/gardener/gardener/pkg/utils/managedresources" "github.com/go-logr/logr" "github.com/pkg/errors" @@ -68,12 +69,11 @@ const ( // Error variables for controller pkg var ( - ErrSpecAction = errors.New("action must either be 'ALLOW' or 'DENY'") - ErrSpecRule = errors.New("rule must be present") - ErrSpecType = errors.New("type must either be 'direct_remote_ip', 'remote_ip' or 'source_ip'") - ErrSpecCIDR = errors.New("CIDRs must not be empty") - ErrSpecTooManyCIDRs = errors.New("number of CIDRs exceeds the maximum allowed") - ErrNoAdvertisedAddresses = errors.New("advertised addresses are not available, likely because cluster creation has not yet completed") + ErrSpecAction = errors.New("action must either be 'ALLOW' or 'DENY'") + ErrSpecRule = errors.New("rule must be present") + ErrSpecType = errors.New("type must either be 'direct_remote_ip', 'remote_ip' or 'source_ip'") + ErrSpecCIDR = errors.New("CIDRs must not be empty") + ErrSpecTooManyCIDRs = errors.New("number of CIDRs exceeds the maximum allowed") ) // ExtensionState contains the State of the Extension @@ -173,6 +173,12 @@ func (a *actuator) Reconcile(ctx context.Context, log logr.Logger, ex *extension hosts, err := allowedCIDRer.Hosts() if err != nil { + if errors.Is(err, allowedcidrs.ErrNoAdvertisedAddresses) { + return &reconcilerutils.RequeueAfterError{ + Cause: err, + RequeueAfter: 10 * time.Second, + } + } return err } From c1e63401d935bc8e8d3c24a18d7ab9276e640d1b Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Wed, 27 May 2026 15:12:05 +0200 Subject: [PATCH 16/25] drop special findIstioNamespace logic for garden extension Signed-off-by: Lukas Hoehl --- pkg/controller/actuator.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pkg/controller/actuator.go b/pkg/controller/actuator.go index 5a475e8b..a6faf273 100644 --- a/pkg/controller/actuator.go +++ b/pkg/controller/actuator.go @@ -492,13 +492,6 @@ func (a *actuator) findIstioNamespaceForExtension( if err != nil { return "", nil, err } - if hasClassGarden(ex) { - for _, dep := range deployments.Items { - if dep.Namespace == operatorv1alpha1.VirtualGardenDefaultSNIIngressNamespace { - return dep.Namespace, gw.Spec.Selector, nil - } - } - } if len(deployments.Items) != 1 { return "", nil, fmt.Errorf("no istio namespace could be selected, because the number of deployments found is %d", len(deployments.Items)) From 659ced458c0434d6e413b9677c67a82f8782827e Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Wed, 27 May 2026 16:15:31 +0200 Subject: [PATCH 17/25] tidy Signed-off-by: Lukas Hoehl --- go.mod | 18 ++++++++++++++++++ go.sum | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/go.mod b/go.mod index f5d378ef..131be6ff 100644 --- a/go.mod +++ b/go.mod @@ -35,6 +35,7 @@ require ( github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.5.0 // indirect github.com/Masterminds/sprig/v3 v3.3.0 // indirect + github.com/NYTimes/gziphandler v1.1.1 // indirect github.com/PaesslerAG/gval v1.2.4 // indirect github.com/PaesslerAG/jsonpath v0.1.2-0.20240726212847-3a740cf7976f // indirect github.com/VictoriaMetrics/VictoriaLogs v1.36.2-0.20251008164716-21c0fb3de84d // indirect @@ -60,10 +61,12 @@ require ( github.com/aws/aws-sdk-go-v2/service/sts v1.41.7 // indirect github.com/aws/smithy-go v1.24.1 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/blang/semver/v4 v4.0.0 // indirect github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect github.com/brunoga/deep v1.3.1 // indirect github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-systemd/v22 v22.7.0 // indirect github.com/cyphar/filepath-securejoin v0.6.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect @@ -72,6 +75,7 @@ require ( github.com/emicklei/go-restful/v3 v3.13.0 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/fatih/color v1.19.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fluent/fluent-operator/v3 v3.7.0 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect @@ -97,6 +101,7 @@ require ( github.com/go-openapi/swag/typeutils v0.25.5 // indirect github.com/go-openapi/swag/yamlutils v0.25.5 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect + github.com/go-test/deep v1.1.0 // indirect github.com/gobuffalo/flect v1.0.3 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/goccy/go-yaml v1.19.2 // indirect @@ -109,6 +114,8 @@ require ( github.com/google/pprof v0.0.0-20260402051712-545e8a4df936 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect + github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 // indirect + github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect @@ -118,6 +125,7 @@ require ( github.com/json-iterator/go v1.1.13-0.20220915233716-71ac16282d12 // indirect github.com/klauspost/compress v1.18.6 // indirect github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect github.com/labstack/echo/v4 v4.15.1 // indirect github.com/labstack/gommon v0.4.2 // indirect github.com/mattn/go-colorable v0.1.14 // indirect @@ -144,6 +152,7 @@ require ( github.com/prometheus/otlptranslator v1.0.0 // indirect github.com/prometheus/procfs v0.20.1 // indirect github.com/prometheus/sigv4 v0.3.0 // indirect + github.com/robfig/cron v1.2.0 // indirect github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.4 // indirect @@ -158,7 +167,12 @@ require ( github.com/x448/float16 v0.8.4 // indirect github.com/zitadel/oidc/v3 v3.45.4 // indirect github.com/zitadel/schema v1.3.2 // indirect + go.etcd.io/etcd/api/v3 v3.6.8 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.6.8 // indirect + go.etcd.io/etcd/client/v3 v3.6.8 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.65.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect go.opentelemetry.io/contrib/otelconf v0.23.0 // indirect go.opentelemetry.io/otel v1.43.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0 // indirect @@ -203,17 +217,21 @@ require ( google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // indirect gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect helm.sh/helm/v4 v4.1.4 // indirect + k8s.io/apiserver v0.36.1 // indirect k8s.io/autoscaler/vertical-pod-autoscaler v1.6.0 // indirect k8s.io/gengo/v2 v2.0.0-20251215205346-5ee0d033ba5b // indirect k8s.io/klog/v2 v2.140.0 // indirect + k8s.io/kms v0.36.1 // indirect k8s.io/kube-aggregator v0.35.5 // indirect k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a // indirect k8s.io/kubelet v0.35.5 // indirect k8s.io/metrics v0.35.5 // indirect k8s.io/pod-security-admission v0.35.5 // indirect k8s.io/streaming v0.36.1 // indirect + sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 // indirect sigs.k8s.io/controller-tools v0.20.1 // indirect sigs.k8s.io/gateway-api v1.5.0 // indirect sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect diff --git a/go.sum b/go.sum index a4f7b5bf..554db828 100644 --- a/go.sum +++ b/go.sum @@ -39,6 +39,8 @@ github.com/Masterminds/semver/v3 v3.5.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lpr github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= +github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/PaesslerAG/gval v1.2.2/go.mod h1:XRFLwvmkTEdYziLdaCeCa5ImcGVrfQbeNUbVR+C6xac= github.com/PaesslerAG/gval v1.2.4 h1:rhX7MpjJlcxYwL2eTTYIOBUyEKZ+A96T9vQySWkVUiU= github.com/PaesslerAG/gval v1.2.4/go.mod h1:XRFLwvmkTEdYziLdaCeCa5ImcGVrfQbeNUbVR+C6xac= @@ -112,6 +114,8 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR 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= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= +github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA= github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= @@ -126,6 +130,8 @@ github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxK github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/elastic/crd-ref-docs v0.3.0 h1:9bGSUkBR56Z7TuDGQAu3KGbBkagwwZ6RkZmS+qvDuDM= github.com/elastic/crd-ref-docs v0.3.0/go.mod h1:8td3UC8CaO5M+G115O3FRKLmplmX+p0EqLMLGM6uNdk= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= @@ -234,6 +240,8 @@ github.com/go-openapi/testify/v2 v2.4.0 h1:8nsPrHVCWkQ4p8h1EsRVymA2XABB4OT40gcvA github.com/go-openapi/testify/v2 v2.4.0/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54= 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/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= +github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/gobuffalo/flect v1.0.3 h1:xeWBM2nui+qnVvNM4S3foBhCAL2XgPU+a7FdpelbTq4= github.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= @@ -270,6 +278,8 @@ github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/cel-go v0.27.0 h1:e7ih85+4qVrBuqQWTW4FKSqZYokVuc3HnhH5keboFTo= github.com/google/cel-go v0.27.0/go.mod h1:tTJ11FWqnhw5KKpnWpvW9CJC3Y9GK4EIS0WXnBbebzw= github.com/google/gnostic-models v0.7.1 h1:SisTfuFKJSKM5CPZkffwi6coztzzeYUhc3v4yxLWH8c= @@ -301,6 +311,10 @@ github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3i github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 h1:B+8ClL/kCQkRiU82d9xajRPKYMrB7E0MbtzWVi1K4ns= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3/go.mod h1:NbCUVmiS4foBGBHOYlCT25+YmGpJ32dZPi75pGEUpj4= github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -317,6 +331,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1: github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I= +github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60= github.com/joshdk/go-junit v1.0.0 h1:S86cUKIdwBHWwA6xCmFlf3RTLfVXYQfvanM5Uh+K6GE= github.com/joshdk/go-junit v1.0.0/go.mod h1:TiiV0PqkaNfFXjEiyjWM3XXrhVyCa1K4Zfga6W52ung= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= @@ -429,6 +445,8 @@ github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEy github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= github.com/prometheus/sigv4 v0.3.0 h1:QIG7nTbu0JTnNidGI1Uwl5AGVIChWUACxn2B/BQ1kms= github.com/prometheus/sigv4 v0.3.0/go.mod h1:fKtFYDus2M43CWKMNtGvFNHGXnAJJEGZbiYCmVp/F8I= +github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= +github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= @@ -440,6 +458,8 @@ github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= +github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= +github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= @@ -473,6 +493,8 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE= +github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ= @@ -489,6 +511,8 @@ github.com/valyala/quicktemplate v1.8.0 h1:zU0tjbIqTRgKQzFY1L42zq0qR3eh4WoQQdIdq github.com/valyala/quicktemplate v1.8.0/go.mod h1:qIqW8/igXt8fdrUln5kOSb+KWMaJ4Y8QUsfd1k6L2jM= 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/xiang90/probing v0.0.0-20221125231312-a49e3df8f510 h1:S2dVYn90KE98chqDkyE9Z4N61UnQd+KOfgp5Iu53llk= +github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -498,11 +522,27 @@ github.com/zitadel/oidc/v3 v3.45.4 h1:GKyWaPRVQ8sCu9XgJ3NgNGtG52FzwVJpzXjIUG2+Yr github.com/zitadel/oidc/v3 v3.45.4/go.mod h1:XALmFXS9/kSom9B6uWin1yJ2WTI/E4Ti5aXJdewAVEs= github.com/zitadel/schema v1.3.2 h1:gfJvt7dOMfTmxzhscZ9KkapKo3Nei3B6cAxjav+lyjI= github.com/zitadel/schema v1.3.2/go.mod h1:IZmdfF9Wu62Zu6tJJTH3UsArevs3Y4smfJIj3L8fzxw= +go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo= +go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E= +go.etcd.io/etcd/api/v3 v3.6.8 h1:gqb1VN92TAI6G2FiBvWcqKtHiIjr4SU2GdXxTwyexbM= +go.etcd.io/etcd/api/v3 v3.6.8/go.mod h1:qyQj1HZPUV3B5cbAL8scG62+fyz5dSxxu0w8pn28N6Q= +go.etcd.io/etcd/client/pkg/v3 v3.6.8 h1:Qs/5C0LNFiqXxYf2GU8MVjYUEXJ6sZaYOz0zEqQgy50= +go.etcd.io/etcd/client/pkg/v3 v3.6.8/go.mod h1:GsiTRUZE2318PggZkAo6sWb6l8JLVrnckTNfbG8PWtw= +go.etcd.io/etcd/client/v3 v3.6.8 h1:B3G76t1UykqAOrbio7s/EPatixQDkQBevN8/mwiplrY= +go.etcd.io/etcd/client/v3 v3.6.8/go.mod h1:MVG4BpSIuumPi+ELF7wYtySETmoTWBHVcDoHdVupwt8= +go.etcd.io/etcd/pkg/v3 v3.6.8 h1:Xe+LIL974spy8b4nEx3H0KMr1ofq3r0kh6FbU3aw4es= +go.etcd.io/etcd/pkg/v3 v3.6.8/go.mod h1:TRibVNe+FqJIe1abOAA1PsuQ4wqO87ZaOoprg09Tn8c= +go.etcd.io/etcd/server/v3 v3.6.8 h1:U2strdSEy1U8qcSzRIdkYpvOPtBy/9i/IfaaCI9flZ4= +go.etcd.io/etcd/server/v3 v3.6.8/go.mod h1:88dCtwUnSirkUoJbflQxxWXqtBSZa6lSG0Kuej+dois= +go.etcd.io/raft/v3 v3.6.0 h1:5NtvbDVYpnfZWcIHgGRk9DyzkBIXOi8j+DDp1IcnUWQ= +go.etcd.io/raft/v3 v3.6.0/go.mod h1:nLvLevg6+xrVtHUmVaTcTz603gQPHfh7kUAwV6YpfGo= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.65.0 h1:XmiuHzgJt067+a6kwyAzkhXooYVv3/TOw9cM2VfJgUM= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.65.0/go.mod h1:KDgtbWKTQs4bM+VPUr6WlL9m/WXcmkCcBlIzqxPGzmI= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo= go.opentelemetry.io/contrib/otelconf v0.23.0 h1:s3C7KdMYiutf4rC8hKFA0WOIDG+gIru8ajjQKS59ir8= @@ -766,6 +806,8 @@ gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWM gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -815,6 +857,8 @@ k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= +k8s.io/kms v0.36.1 h1:XdvKpywoW4k7YUHDh5uYP4mahJXECswHGfCddBBYLZs= +k8s.io/kms v0.36.1/go.mod h1:g91diTD9h0oJCCHkTb00krlF+Qm5HTnkWLi9Q/TpRoc= k8s.io/kube-aggregator v0.35.5 h1:oLflHAqh8tEoEcXtrzGhr4hctwhcRr5B1sM+T96N1rs= k8s.io/kube-aggregator v0.35.5/go.mod h1:L3GflyN8a8CDjej2UxgeGwRiXYuI+aTZ0GE7qssdN2w= k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= From d21eac847d2c963392824547bcce1664f481274c Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Thu, 28 May 2026 10:28:07 +0200 Subject: [PATCH 18/25] clusterCompability in extension Signed-off-by: Lukas Hoehl --- Makefile | 3 ++- example/extension.yaml | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c88ec1df..27f62b30 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,7 @@ VERSION := $(shell git describe --tag --always --dirty) export TAG := $(VERSION) LEADER_ELECTION := false IGNORE_OPERATION_ANNOTATION := false +REGISTRY := registry.local.gardener.cloud:5001 SHELL=/usr/bin/env bash -o pipefail @@ -146,7 +147,7 @@ verify-extended: verify-tidy verify-generate check format test artifacts # speed-up skaffold deployments by building all images concurrently extension-%: export SKAFFOLD_BUILD_CONCURRENCY = 0 -extension-%: export SKAFFOLD_DEFAULT_REPO ?= registry.local.gardener.cloud:5001 +extension-%: export SKAFFOLD_DEFAULT_REPO ?= $(REGISTRY) extension-%: export SKAFFOLD_PUSH = true # use static label for skaffold to prevent rolling all gardener components on every `skaffold` invocation extension-%: export SKAFFOLD_LABEL = skaffold.dev/run-id=acl diff --git a/example/extension.yaml b/example/extension.yaml index 011a28eb..933583ec 100644 --- a/example/extension.yaml +++ b/example/extension.yaml @@ -8,6 +8,9 @@ spec: primary: true reconcileTimeout: 3m0s type: acl + clusterCompatibility: + - shoot + - garden deployment: extension: helm: From 0210f9e7f14a6e711c77e39b007281e8c1e2c56b Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Thu, 28 May 2026 10:29:17 +0200 Subject: [PATCH 19/25] move gardencluster setup to app.go Signed-off-by: Lukas Hoehl --- cmd/gardener-extension-acl/app/app.go | 50 +++++++++++++++++++++++++++ pkg/cmd/options.go | 2 -- pkg/controller/add.go | 47 ++----------------------- 3 files changed, 53 insertions(+), 46 deletions(-) diff --git a/cmd/gardener-extension-acl/app/app.go b/cmd/gardener-extension-acl/app/app.go index f9891459..9eb43696 100644 --- a/cmd/gardener-extension-acl/app/app.go +++ b/cmd/gardener-extension-acl/app/app.go @@ -17,12 +17,18 @@ package app import ( "context" + "errors" "fmt" + "os" + "slices" extensionscontroller "github.com/gardener/gardener/extensions/pkg/controller" "github.com/gardener/gardener/extensions/pkg/util" + "github.com/gardener/gardener/pkg/api/indexer" v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants" + extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" operatorv1alpha1 "github.com/gardener/gardener/pkg/apis/operator/v1alpha1" + "github.com/gardener/gardener/pkg/client/kubernetes" "github.com/spf13/cobra" istionetworkv1alpha3 "istio.io/client-go/pkg/apis/networking/v1alpha3" istionetworkv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1" @@ -33,6 +39,7 @@ import ( componentbaseconfigv1alpha1 "k8s.io/component-base/config/v1alpha1" "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/manager" "github.com/stackitcloud/gardener-extension-acl/pkg/controller" @@ -126,6 +133,21 @@ func (o *Options) run(ctx context.Context) error { return fmt.Errorf("could not add controllers to manager: %s", err) } + var gardenCluster cluster.Cluster + if slices.Contains(controller.DefaultAddOptions.ExtensionClasses, extensionsv1alpha1.ExtensionClassGarden) { + gardenCluster, err = setupGardenCluster(mgr) + if err != nil { + return fmt.Errorf("unable to set up garden cluster: %w", err) + } + if err := indexer.AddManagedSeedShootName(ctx, gardenCluster.GetFieldIndexer()); err != nil { + return fmt.Errorf("adding index for managedSeed to garden cluster: %w", err) + } + } + + if err := controller.AddToManager(ctx, mgr, gardenCluster); err != nil { + return fmt.Errorf("could not add controller to manager: %w", err) + } + // TODO(Wieneo): Remove this once a couple extension versions included the migration code // migration code: remove mutating webhook from cluster as it is not served by this controller anymore if err := mgr.Add(manager.RunnableFunc(func(ctx context.Context) error { @@ -143,3 +165,31 @@ func (o *Options) run(ctx context.Context) error { return nil } + +func setupGardenCluster(mgr manager.Manager) (cluster.Cluster, error) { + // configure garden + kubeconfigFile := os.Getenv("GARDEN_KUBECONFIG") + if kubeconfigFile == "" { + return nil, errors.New("GARDEN_KUBECONFIG environment variable is empty, cannot setup garden cluster") + } + gardenRESTConfig, err := kubernetes.RESTConfigFromKubeconfigFile(kubeconfigFile, kubernetes.AuthTokenFile, kubernetes.AuthExec) + if err != nil { + return nil, err + } + + gardenCluster, err := cluster.New(gardenRESTConfig, func(opts *cluster.Options) { + opts.Scheme = kubernetes.GardenScheme + opts.Cache = cache.Options{ + DefaultNamespaces: map[string]cache.Config{ + // ManagedSeeds (and their underlying Shoots) must always be in the "garden" namespace, so that is the + // only one we need to watch. + v1beta1constants.GardenNamespace: {}, + }, + } + }) + if err != nil { + return nil, err + } + + return gardenCluster, mgr.Add(gardenCluster) +} diff --git a/pkg/cmd/options.go b/pkg/cmd/options.go index b8ea9653..ed20d1ec 100644 --- a/pkg/cmd/options.go +++ b/pkg/cmd/options.go @@ -23,7 +23,6 @@ import ( extensionshealthcheckcontroller "github.com/gardener/gardener/extensions/pkg/controller/healthcheck" "github.com/spf13/pflag" - "github.com/stackitcloud/gardener-extension-acl/pkg/controller" controllerconfig "github.com/stackitcloud/gardener-extension-acl/pkg/controller/config" healthcheckcontroller "github.com/stackitcloud/gardener-extension-acl/pkg/controller/healthcheck" ) @@ -80,7 +79,6 @@ func (o *ExtensionOptions) ApplyHealthCheckConfig(config *extensionsconfigv1alph // ControllerSwitches are the cmd.SwitchOptions for the provider controllers. func ControllerSwitches() *extensionscmdcontroller.SwitchOptions { return extensionscmdcontroller.NewSwitchOptions( - extensionscmdcontroller.Switch(controller.Type, controller.AddToManager), extensionscmdcontroller.Switch(extensionshealthcheckcontroller.ControllerName, healthcheckcontroller.AddToManager), ) } diff --git a/pkg/controller/add.go b/pkg/controller/add.go index 85845d9d..185bc81f 100644 --- a/pkg/controller/add.go +++ b/pkg/controller/add.go @@ -17,22 +17,17 @@ package controller import ( "context" - "fmt" - "os" "slices" "time" extensionscontroller "github.com/gardener/gardener/extensions/pkg/controller" "github.com/gardener/gardener/extensions/pkg/controller/extension" - "github.com/gardener/gardener/pkg/api/indexer" gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1" v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants" extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" - "github.com/gardener/gardener/pkg/client/kubernetes" kubernetesutil "github.com/gardener/gardener/pkg/utils/kubernetes" "k8s.io/apimachinery/pkg/types" "k8s.io/utils/ptr" - "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/controller" @@ -69,26 +64,13 @@ type AddOptions struct { } // AddToManager adds a controller with the default Options to the given Controller Manager. -func AddToManager(ctx context.Context, mgr manager.Manager) error { - return AddToManagerWithOptions(ctx, mgr, &DefaultAddOptions) +func AddToManager(ctx context.Context, mgr manager.Manager, gardenCluster cluster.Cluster) error { + return AddToManagerWithOptions(ctx, mgr, gardenCluster, &DefaultAddOptions) } // AddToManagerWithOptions adds a controller with the given Options to the given manager. // The opts.Reconciler is being set with a newly instantiated actuator. -func AddToManagerWithOptions(ctx context.Context, mgr manager.Manager, opts *AddOptions) error { - // configure garden - var gardenCluster cluster.Cluster - if kFile := os.Getenv("GARDEN_KUBECONFIG"); kFile != "" { - var err error - gardenCluster, err = setupGardenCluster(mgr, kFile) - if err != nil { - return fmt.Errorf("unable to set up garden cluster: %w", err) - } - - if err := indexer.AddManagedSeedShootName(ctx, gardenCluster.GetFieldIndexer()); err != nil { - return fmt.Errorf("adding index for managedSeed to garden cluster: %w", err) - } - } +func AddToManagerWithOptions(ctx context.Context, mgr manager.Manager, gardenCluster cluster.Cluster, opts *AddOptions) error { args := extension.AddArgs{ Actuator: NewActuator(mgr, gardenCluster, opts.ExtensionConfig), ControllerOptions: opts.ControllerOptions, @@ -220,26 +202,3 @@ func shootsOfManagedSeedsPredicate(c client.Reader) predicate.TypedFuncs[*garden }, } } - -func setupGardenCluster(mgr manager.Manager, kubeconfigFile string) (cluster.Cluster, error) { - gardenRESTConfig, err := kubernetes.RESTConfigFromKubeconfigFile(kubeconfigFile, kubernetes.AuthTokenFile, kubernetes.AuthExec) - if err != nil { - return nil, err - } - - gardenCluster, err := cluster.New(gardenRESTConfig, func(opts *cluster.Options) { - opts.Scheme = kubernetes.GardenScheme - opts.Cache = cache.Options{ - DefaultNamespaces: map[string]cache.Config{ - // ManagedSeeds (and their underlying Shoots) must always be in the "garden" namespace, so that is the - // only one we need to watch. - v1beta1constants.GardenNamespace: {}, - }, - } - }) - if err != nil { - return nil, err - } - - return gardenCluster, mgr.Add(gardenCluster) -} From e544c2d2bfaa9835480a4f21b924cf75f1ad1469 Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Thu, 28 May 2026 10:29:21 +0200 Subject: [PATCH 20/25] format Signed-off-by: Lukas Hoehl --- pkg/controller/add_test.go | 19 +++++++++---------- pkg/controller/allowedcidrs/shoot.go | 7 +++---- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/pkg/controller/add_test.go b/pkg/controller/add_test.go index 2c93c83b..9610050a 100644 --- a/pkg/controller/add_test.go +++ b/pkg/controller/add_test.go @@ -25,11 +25,10 @@ import ( seedmanagementv1alpha1 "github.com/gardener/gardener/pkg/apis/seedmanagement/v1alpha1" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/utils/ptr" - - "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/event" @@ -120,7 +119,7 @@ var _ = Describe("shootsOfManagedSeeds", func() { p = shootsOfManagedSeedsPredicate(c) shoot = &gardencorev1beta1.Shoot{ - ObjectMeta: v1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: "foo", }, Status: gardencorev1beta1.ShootStatus{ @@ -128,7 +127,7 @@ var _ = Describe("shootsOfManagedSeeds", func() { }, } ms = &seedmanagementv1alpha1.ManagedSeed{ - ObjectMeta: v1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: "seed", }, Spec: seedmanagementv1alpha1.ManagedSeedSpec{ @@ -172,7 +171,7 @@ var _ = Describe("shootsOfManagedSeeds", func() { WithScheme(scheme). Build() shoot = &gardencorev1beta1.Shoot{ - ObjectMeta: v1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: "foo", }, } @@ -181,7 +180,7 @@ var _ = Describe("shootsOfManagedSeeds", func() { It("should return only acl extensions and extensions of class garden inside garden namespace", func(ctx context.Context) { extensions := []*extensionsv1alpha1.Extension{ { - ObjectMeta: v1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: "not-in-garden-namespace", }, Spec: extensionsv1alpha1.ExtensionSpec{ @@ -192,7 +191,7 @@ var _ = Describe("shootsOfManagedSeeds", func() { }, }, { - ObjectMeta: v1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: "not-garden-extension", Namespace: "garden", }, @@ -204,7 +203,7 @@ var _ = Describe("shootsOfManagedSeeds", func() { }, }, { - ObjectMeta: v1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: "not-acl-extension", Namespace: "garden", }, @@ -216,7 +215,7 @@ var _ = Describe("shootsOfManagedSeeds", func() { }, }, { - ObjectMeta: v1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: "garden-acl-extension", Namespace: "garden", }, diff --git a/pkg/controller/allowedcidrs/shoot.go b/pkg/controller/allowedcidrs/shoot.go index 70edd831..57a4c77c 100644 --- a/pkg/controller/allowedcidrs/shoot.go +++ b/pkg/controller/allowedcidrs/shoot.go @@ -9,14 +9,13 @@ import ( "github.com/gardener/gardener/extensions/pkg/controller" v1beta1helper "github.com/gardener/gardener/pkg/api/core/v1beta1/helper" - extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" - "sigs.k8s.io/controller-runtime/pkg/client" - logf "sigs.k8s.io/controller-runtime/pkg/log" - v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants" + extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + logf "sigs.k8s.io/controller-runtime/pkg/log" "github.com/stackitcloud/gardener-extension-acl/pkg/helper" ) From 2a6d3632e9a24d3fd80877b2d6c985057c90246a Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Thu, 28 May 2026 11:42:28 +0200 Subject: [PATCH 21/25] generate Signed-off-by: Lukas Hoehl --- deploy/extension/base/controller-registration.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/extension/base/controller-registration.yaml b/deploy/extension/base/controller-registration.yaml index 501fa4f8..cc0892ab 100644 --- a/deploy/extension/base/controller-registration.yaml +++ b/deploy/extension/base/controller-registration.yaml @@ -4,7 +4,7 @@ kind: ControllerDeployment metadata: name: acl helm: - rawChart: H4sIAAAAAAAAA+0ba2/jNnI/61fwvFd0t6jkRxynNbBA0yS3DZAXkm0Oh6IIaIm22UiiSkrOeh/3229IyhKtR2Q7u97b1vPBlsjhcMh5cIakJph7JCTcJm9jEgrKQhu7fvvZp4QOwMH+vvoHKP6r5+5ev9vb7w0Gsrzb73a7z9D+J+WiBhIRY47QM85Y/BheU/1XCpNq+TtT4gd0EjJOnt6HFPCg36+VP4i9IP9Brz94hjpP77oZ/ubyf46ucBwTHgoUM6Qljh6mJESjhPoeDScowu49nhDhWM/RmykVSCRRxHgMD6AlPpr4bIQCHLtTwP4eceLjmM4ItIunRjkOPSAQkgnUshC9iDgZ07fEQw8U8P7x0kGXoT9HLFQtJUsoIhz5NCSO5Rzf3N3EwBuQOGJBAARuj26QR7mwnAmN2+pXs285o3e8rX4XBdNJW/4sXsUsbOeERjC+JEJj6hNhfeeIhwh+R/gefuMAnv8LqLeYU5YIdHp8Ah1GnP1B3NhyqEdwW+NBkeXMhMs80ra+tFRXhxr7P5piHjtzHPifoI8m++91Dor239nb39n/NgBH9JZwKfchmnUtHEXZa6vrdFqWR4TLaRSrokP0C6wLyJXagcaMo3hK0OtUhdDh0RnK1MixQhyQIapWMGu26KXjQDdfkcH8xaDG/mMSRODGifgUkeD68d+gCy5hF/9tARrlfwdrPKzDwomjTdeCBv/f7fUK/r/X6e/t7fz/NuD9ext5EIhB1NWSDruF7I8frRqnLZFJ6CkUy2zp4xHxhQOrh3NP5pqGeklGEMcR0COHsrakv0SjhsQM+0nKyPv3iIaun3gZew5KGz7CSLltkUFJZYhqMNL+VU/lUdAQNCZ0iWruXBOfYEGcC2DuUc5oADG0ZgwhWUHH6J6G3qlALRFzCJGhx1vZM/QicVGGWVMM7BJJZYrFlYqlgdAU9/YHwwIlJ8aTvFkEfcVj1PpG/PSNKGJyEjFBIdCeP0ZC9VxBcLgxQZgxY/I+fvzSZvG3gUb/77JwTCcBjmwltxnkPYzbDOK3B05jskqO0BT/9weF/B8eDnb+fyuQeqIl27xVMr5ciFhapm3bViFVkM5rCDm0VI9zHFkBibGHYzwEm9ahf7XzrtajtJGIcJVnVcXaXWg/Pazw7pL8BygEfY5RX2Iv2FE9irtlpR2iD5LIoyNfJvdXdE+N9u+RyGfzACZh4+2ABvvf398rxn/d7mCX/28FioYN8Y5oZ9Z9nAl/ZfNe25ARwJROpjaeYQqF1Kfx3NbLDoQPgiXcBftcKKrj+izx2vE8AvKAFXPm+4Sv5A9ERFzZISczKof7CxUyMjmjAY2HqKNqIp+6WGjOU9eQFh6xBAgp3gUMSXoKzb3a4zxbzS8NNIGFfaUEjLmVgMOQxWqbVCyKVvTTKAV3Stx7kQTG8p0beKUDXpLnCxXToX86b1I+nZ9BgldyQ7e1UkTQeqkGreNR4CPnzQj3dIGpBxIg0H5gHPRvUpI5sz2YEYR9nz0Qb7UWHIRGA2KDkgvCgcm8fYOofljwuFAbCTAxDEY5P/KxEBfLO1xiLkCu9o+dToosO6QuOXRdqToXj1uNEhvoM4Z0gWfzYTcZmwYliWWsNOEoo10lvn/FQKPnS1peqDObYT4xBGQj2w7wW2mibsI5TJXNiXyRG+ivDIq5darnFPlmHrrCpC7pTQn246nS2vVpG42b+vGowCOf2EZzk2pafZTXgjr8wWiIWt+3irT0aYLNIsKVrdq52dZxqptcLlocZg2KtMFjenJRlm5Gmaz3qiaaKmAuUVH7tLY8h3nVVs8iqy74E+x5VDbH/qE2jiPq8dLs5Vh2akO2K/HM4dZQqp7GkjMoMZYZdLphXGQpM7603mTlsbYVPZNwZiq5truzk8Pjk+u7k7OTozenlxd3F4fnJzdXh0cnGSZCar/gX5wFQ6MQoTElvndNxsulabn0pcPM8TvZklk3D00Of8Hv6fnh65NbYPby+u7y9uT639enb0q8DlGqDnlI3K6MkdcQVLZSmzhZoVoXY/YfoFnR4gOKOQ1yz9vtNIhKEDBy6YXBtmBdM2dYKeYVpzPwGBNyIlzsY314Mca+IAamiyMdbVAilmXkcRYN0W+HZ2e/G+WwkhyKCxZeQyQ4BI4TUqz8VcjlZQABba9Y9ZqzJCrXwUBcFkRXnMnjx2UudIhzrdevYzLGiR9vqh4z5icBOZfLkCgreUNoYHAVSApad8sqZI4ZvJI8zi3MU0mUaw1DD6K0NK7KvbtIVc1p3ihTzfREC+WceUCj3+sYg0pH+aXD+0ZozP8iBg5d8ESdAI4Sb0LWTgQb73/0i/s/e52D3f2PrUBqgJMYvZARf1XK8xJ1q7aAIhUm5rniFfOOM0X5WSnK50sa18n2IJ78NUyTS1+TF8mocbxPzvK+CjfQaP98hN0nXgRp2v85KJ3/Hhx0+jv73wYUrVqJGyfxFLLcdypwcu5/UOde+ZavD3NG+DXzyToGvo7p8sSX67yNgDUVOalF3zYzfSqAOeALymFlHqUI0unIfx+q1cODtFr1FGVPSQQsE/XoQqCSPnpg7erRCFplOaQFbA7RGQxZlDlqtcot0rRfrMRaiWJmiMU9r3JHrpaE0PyHQqbK3NOvNBxzLCD6cuOEb4GXHLXw2gYDi5PVGKiUU4mruk3BMlMBDiGC87LSBiYMbXio0pactVRZVlKHbGXbUAjwashBW2OFLoAqsGBRqE6dVR5e06kx1NIAyxNe5xRqVZIzn4hiwQhMHExXl+cYhao1mV1XGi1IuTiJRUu/QXgf6pfPrBhyY72Knfx8pZGLvOtNJ8Rl4B9o+LgIVeBVkETa4RMJLspVUKfrVt7VMpgxhryYozrT8QIqpN1wMoFZ5I/zGSRyMy6cPJDRlLF7nS8mutHq/mtT2VSvbQUWJ0DvAc9X9CTrr+2lRX2dVXudGF/eqUk3zGtX+yrzzQ4favRJgORiGxa/isDgabHOz9pFfbaQB7pINwsX0/AIh4BVDsYa+IGkR95aVzOtG98snU+sJb/aHG1Dpdtgdmu0aSvT/n8z30+N/xvzvzSYxZrnjTLBpv2fvW63sP/Tg8Jd/rcNqL3YU9DVL7qTA6bI1M7zMlNv2D3J9vW/9ER+pdBo/7MIP/U7oKb733vF+3/dg/3Bwc7+twGFAxgpbRLKfVKvajGXhihP1GSQWlzFASmmUHfFvMMUjfBP7Tf0nm4F04tQ0Ly8sFymd3GzGxaqkJqnSVmVvqjx7XffWtmxFw3T02zz7MiNEsUqJ38mlMOMteo5cnISDrRDVGTNWo8MpNjMONKT14YCxucbsaCbbsJF2nJ5fxshMCIIsbPT7qorZbK8dK2s6QwOEHQWZQpRl+hjN+O8XzJuIjs53lezH79tqPH/Mz2jn+YD0Eb/v79X+v57d/63HdAXx5SzXHyoMUSTqculb4epce9prO/S1XwTJE1/MkQqWIit0gWz0/EFi6/AnUhjt8xjtiHqyQIju5euCIikLll519Z+J2hZprNrDfrntGVZYOwSL12ssnsGVT6/7L0VbSBtLTtSSbrR4bSuid7iASaMu10SsXD5DLqAwto7X/mNFOMCW7ZKFQlZ5btpQ/Tb75ZVfeFK1z1HVTcq5M3352hxLX6onvPLFBgiP6LKENJzeW2oxjSOIzFst4U7fcD8HY1/8sjMwe8SThyXBXl5/uSIe9K+kx/pp8SN23dpP6bycTJx1OGFbOeQpNN1Uj1ML3VKcstsKg1sdZye8yMIZaGoQ70DlH7M3No5/R3sYAc72MEOdrCDHezgf4TOeGQAUAAA + rawChart: H4sIAAAAAAAAA+1cbW/jNhLez/oVPO0V2xaV/BLHaQ0UaDZJt8FlkyDZ5nAoioCWGJuNJOpIyal3u/fbb0jqzbJk2U7W+1LNh0SiyOGInHk4HA09wdwlAeEW+TMigaAssLDjdZ49JXWBDvb31X+g8n913dsb9Pr7/eFQlvcGvV7vGdp/UilqKBYR5gg944xFq+o1Pf9MaVI9//aUeD6dBIyTx/chJ3g4GNTOP0x7af6H/cHwGeo+vutm+pvP/3N0iaOI8ECgiCE94+hhSgI0jqnn0mCCQuzc4wkRtvEcvZlSgUQchoxHcAFa4qGJx8bIx5EzhdrfIU48HNEZgXbRtFCOAxcYBGQCT1mAvg45uaN/Ehc9UKj3j29sdBF4c8QC1VKKhELCkUcDYhv28fXtdQSyAYsj5vvA4OboGrmUC8Oe0Kij/mrxDXv8lnfU37RgOunIP+mtmAWdnNEY3i8O0R31iDC+tcVDCH/H+B7+Rj5c/w+q3mBOWSzQ6fEJdBhy9gdxIsOmLsEdXQ+KDHsmHOaSjvGxZ3V9qrH/oynmkT3HvvcEfTTZf797ULb/7t5+a/+7IBzSG8LlvI/QrGfgMMxuzZ7dNQ2XCIfTMFJFh+gXWBeQI7UD3TGOoilBrxIVQodHZyhTI9sIsE9GqFrBjFnaS9eGbj4jg/nCqMb+I+KHAONEPIUnuLn/N+wBJLT+3w6ocf5vYY2HdVjYUbjtWtCA/71+v4T//e5gb6/F/13Qu3cWcsERA6/LlIBtIuv9e6MGtGVlEriqilFs6eEx8YQNq4d9T+aah7qJx+DHEdAjm7KO5L/Ao4bFDHtxIsi7d4gGjhe7mXg2ShquEGS5bVlAyWWEamok/auelt+CBqAxgUNUc/uKeAQLYp+DcCsloz740FowhOQDeofuaeCeCmSKiIOLDD3eyJ6hF1kXZTVrikFcIrlMsbhUvjQwmuL+/nBU4mRHeJI3C6Gv6A6ZX4mfvhLlmpyETFBwtOerWKieKxiOtmYII1YYvPfvP7ZZ/G2oEf8dFtzRiY9DS83bDPY9jFsM/LcHTiOyzh6hyf8fDEv7f7g4aPF/J5Qg0YJt3qg5vkinWFqmZVlGaasgwWsEe2ipHq9xaPgkwi6O8AhsWrv+1eBdrUdJIxHiKmRVxRouNE6PKtBdsv8LCkGfIzSQtVNxVI/idlFpR+gvyWTlmy+y+xLhqdH+XRJ6bO7DIGwdDmiw/4NhOf7X7/WGbfxvJ1Q2bPB3RCez7uNs8tc2740NGQFN6WRq4RmmUEg9Gs0tveyA+yBYzB2wz1RRbcdjsduJ5iGwh1oRZ55H+Fp4IELiyA45mVH5ur9QIT2TM+rTaIS66knoUQcLLXkCDUnhEYuBkZJdwCtJpNDSqxjn2Xq4NNQMUvtKGBTGVhIOAhapMKlIi9bEaZSQMyXOvYj9wvKdG3glAC/M59fKp0P/tN8kctovYQYvZUDXXMsjML9RL639UZAjl63g7umCoh5IAkf7gXHQv8nSnDPLhRFB2PPYA3HXa8Fh0qhPLFByQTgIubJ9vb4xS5dYM8qjGHvprdwc5MytyAmtwWAv76RBH75PByLVTUkw+gyGcn7kYSHOU2ODnQSOvQiZGWaLuQBFsn7odnO3O5M7efEjDxAObpd45jMgRacOOXQcqeHnq41baReYHYZdDc+mzWrCBE1KYRZrJfui5WqXseddMjC8+YIxlp4Vm2E+KeiRhSzLx39KJHFizmGwLU7kjYzz/1jgmIOIuk4qX88DRxS5S35Tgr1oqoxrc96Fxk39uFTgsUesQvMi1+TxUf4UFOoPRgNkfmeWeemPHhYLCVeQYuXoUiepbnKRtjjMGpR5A7C70neQaKiQxf2xxukr1VzgosLJlvxc9GNHXYvscQn2sOtS2Rx7h9q8jqjLl0Yvr2UlVmg5sl7xdWs4VQ/jEmYtCZZZXRLXLouUmWzyvCjKqrYb9FyydxJIFXHLguSrgCOBALRVM1jsMdvfr2oopuASrZKUBLPRk4itseXV4dXxyfntv359eXJ0cf7z6ausBkIqZDNCnRnmHeDYEcThJBKdEorr285EFlFHYbdezTr55ao3SkU5Ozk8Prm6PTk7OXpzenF+e374+uT68vDopCzSz5z5o0IhQneUeO4VuVssTcrlCjvK3AE7c6TqRrHJDUjlPX19+OrkBoS9uLq9uDm5+vfV6ZslWWH4tPXlG6VO5c5pA+3M1tNinaxQeUsR+w/wrGjxF4o49fOlstdtsAyY9FgtcQBloK7FEVY4cMnpDAB6Qk6Egz2sP2ndYVD2Qk0Hh9oHpUQszpHLWThCvx2enf1eKAdtOxTnLLgCYxiBxDEpP/xVSKdjuL+/1y8/esVZHC4/gxdxmB9eciY/Si9KoR3fK201x9olyCrMmBf75LVcxsVTml6FdYDXKrvRGru13RUHBFYImQFQGsRmHVvXCBoc4Jo3WzKJLUTW07KdL7+p9E4akCmqzVbxmJQSv/M1c4HHoN+tc+S3VbMVSpYkWhB31CyPpAxX8iILaZ0s4y28oy/KhRa6J/MadU8kUlpRW6H4zbtazSWxULsei+hTGNDd7f8b4z8hA09J8FiJPI7dCdk4ENSY/zUox3/2ugdt/GcnlBjtJEJfyx1/VcjjG9SrCgGHav+Vx4oumXucKcpLpSgfLmi0SbQHNmq/BklwydPsRTxufN9HR3k+ij1vSo32z8fYSbYv2waAG7//L33/6fUGbf7XTmjzRbuIAVI5bBxHU8bpW+VQ2/ffq6/k+QcizeGKeWRtOBhle9JN7J3Hnlz6LQQSKsdaLe8W0pEPxkshPWNhIyIr6ucy+ABe0DgtJJH671GhLx4kDiyh4WYj8RIKaDD50AMCPSU7zXRIVggKtZZnbD2xAE6lm6YGX/O4XggpPg36fxZ4+rnRevivQj0f6vsfYH05/6vXHbTf/3dCCf4HLPrU1oA0vPgUS0Cm3OXvOsuLgKNlFerGDYSM63NX39LgjmMBe30niqHZegtFWRbTXO40+QLzSS49W83DB195tFTtwvNYWgv/H3kQpAH/B8P9Xin/++Cg123xfxf0ODDZZIP/FDhe+FIPmEiZBo9myJRXYXYVhyAy0WjPSXrpgumryxI2k2DG5nfUU4vCY1aWvGrptgMqGMXrgX/lmyxJVZfGsCyUjwM8IW5W2iBEYbweqsYzFy0ZzrWWvwyEn3BJNZNPEaa+IzNQLnXzgV9PJlBViZPn0TVKkXddkGcjKRwGPgsNSotsSSS10pVGPOnwkQzTcrWK6mdrpwUUhCm8cjpGNQqAXZ8KaUucTGAU+Wo5/VhmMwSTBzIGL+Jeh+hj3Wh9K9x2bqoxbCkUEZEHPP9gDuESeG+Czps4VSo9Sucp1aJ6lflmSWY1+qT8Pwsc8ooFYLcO8qfmGu/IKd5S6bYY3Rpt2smwfzrj/YH8v0b/Xy+jj9oBNMZ/4Fnp/F9/2MZ/dkKVhzqu1ZwbOtXkIsT/jRcXi6X85CR+gbXC12fRllMZ5KHCTdrTQFqa5WBrHAeu/JhnyswLcyMmCWygF+/MTBITOIEw5vsXxmJGci0XlQWXfupfXTWMecgECBuxexJYnMB4ysRzY1W+wDqYoM8NHiezkjeXR1ukRKXJlUVpeEu/XRbuyhMh0iTpaRTB+tzprEx3Tt7UFjPHTjjZHnNwmiKmX88tZCk5Ojcr77+cq5UKtNBKUqzSqNQQ1nNPknFTrgsPiweWjJRjJohmVmSvO3z3BQZ9CrQG/i9Y1TbrQFP+x16vFP/p96Gwxf9dUO3BvpIP81EzOcBFYyonb1GoN9JY0xyqjz2Qnyk12v8sxI/9HaAm/2+vnP/RO9gfHrT2vwsq5X/I2S5851s6HQiGKHOnZfCivLuDShGFZ5fMPUyqEf7UuKFzuiqETp2v4qmgxbJR5n+oo0uqsJDjbeWP9AmoF9++yHwPnwbJMZFixqgTxkpU6dBRDiNm1ktk5yxsaIeoyJqZK16k3KyQ1iyPDfqMz7cSQTfdRoqk5eJnMYTAiCYkys41VB0pzX2wwrHS3I+r1QsdXStOoi7RCcCFgzRS8GJlO6/3pX/G25pq8H+mR/RpfgCuOf+jv/T7j23+725In8hUYJn+UAvsR6cOl9gOQ+Pc06h4hmPpN4Gk6cOGUzkLkbF0cvP07pxFlwAn0tiNYprtCPVlQSHqm2yME0hW6Grud329u0/BzhwOXlPTMMDYZb1kscpOYFRh/jJ6K97A2lgEUsm6EXDMK6JD/yBE4dCkrFg61QldQGHtYco8+79wMjRbpcqMjOVDnyP02++GUX2SUT97jqoOl8jwwHOU/izGSF3nx0wweH5ElaXnKa4KqpGGBYQzfcD8LY1+csnMxm9jTmyH+Xl5fmWLe9K5lT/SmTAvHGtN+ikqHycTWyXayHY2ibs9O9HDJJwi2S2KqTTQ7Np9+weYlFRRR/rLQPJjhuobw0JCkx7qTIHyoxgVx6+h+ce21JZaaqmlllpqqaWWWmqppZZaaqmlllpqqaWWWmqppZZaaqmlllqqp/8DTkCg6gB4AAA= values: image: tag: latest From 8fd4a43599e660182b9a2cf6c58f85e07372c69b Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Thu, 28 May 2026 16:26:55 +0200 Subject: [PATCH 22/25] adapt tests to gardener version Signed-off-by: Lukas Hoehl --- pkg/controller/allowedcidrs/garden_test.go | 18 +++---- pkg/controller/suite_test.go | 10 ++-- ...0-crd-operator.gardener.cloud_gardens.yaml | 49 ++++++++----------- 3 files changed, 33 insertions(+), 44 deletions(-) diff --git a/pkg/controller/allowedcidrs/garden_test.go b/pkg/controller/allowedcidrs/garden_test.go index 82136a17..d805bec9 100644 --- a/pkg/controller/allowedcidrs/garden_test.go +++ b/pkg/controller/allowedcidrs/garden_test.go @@ -88,16 +88,14 @@ var _ = Describe("#Garden", func() { }) It("should return only addresses of virtual garden", func() { - garden.Garden.Status.VirtualClusterStatus = &operatorv1alpha1.VirtualClusterStatus{ - AdvertisedAddresses: []operatorv1alpha1.AdvertisedAddress{ - { - Name: "foo", - URL: "https://foo", - }, - { - Name: operatorv1alpha1.AdvertisedAddressVirtual, - URL: "https://bar", - }, + garden.Garden.Status.AdvertisedAddresses = []operatorv1alpha1.AdvertisedAddress{ + { + Name: "foo", + URL: "https://foo", + }, + { + Name: operatorv1alpha1.AdvertisedAddressVirtualGarden, + URL: "https://bar", }, } hosts, err := garden.Hosts() diff --git a/pkg/controller/suite_test.go b/pkg/controller/suite_test.go index 02ae06a6..479112f8 100644 --- a/pkg/controller/suite_test.go +++ b/pkg/controller/suite_test.go @@ -342,12 +342,10 @@ func createNewGarden() { Expect(k8sClient.Create(ctx, garden)).ShouldNot(HaveOccurred()) garden.Status = operatorv1alpha1.GardenStatus{ - VirtualClusterStatus: &operatorv1alpha1.VirtualClusterStatus{ - AdvertisedAddresses: []operatorv1alpha1.AdvertisedAddress{ - { - Name: operatorv1alpha1.AdvertisedAddressVirtual, - URL: "https://" + virtualGardenURL, - }, + AdvertisedAddresses: []operatorv1alpha1.AdvertisedAddress{ + { + Name: operatorv1alpha1.AdvertisedAddressVirtualGarden, + URL: "https://" + virtualGardenURL, }, }, } diff --git a/upstream-crds/10-crd-operator.gardener.cloud_gardens.yaml b/upstream-crds/10-crd-operator.gardener.cloud_gardens.yaml index 7616db5c..91c5aadf 100644 --- a/upstream-crds/10-crd-operator.gardener.cloud_gardens.yaml +++ b/upstream-crds/10-crd-operator.gardener.cloud_gardens.yaml @@ -1,4 +1,3 @@ ---- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: @@ -2030,6 +2029,27 @@ spec: status: description: Status contains the status of this garden. properties: + advertisedAddresses: + description: |- + List of addresses that are relevant to the Garden. + These include the Kube API server address of the virtual garden cluster. + items: + description: AdvertisedAddress contains information for the Garden's + servers. + properties: + name: + description: Name of the advertised address. e.g. virtual or + discovery-server + type: string + url: + description: The URL of the server. e.g. https://api.foo.bar + or https://1.2.3.4 + type: string + required: + - name + - url + type: object + type: array conditions: description: Conditions is a list of conditions. items: @@ -2374,36 +2394,9 @@ spec: for this resource. format: int64 type: integer - virtualClusterStatus: - description: VirtualClusterStatus holds information about the virtual - garden cluster - properties: - advertisedAddresses: - description: |- - List of addresses that are relevant to the Garden. - These include the Kube API server address of the virtual garden cluster. - items: - description: AdvertisedAddress contains information for the - Garden's servers. - properties: - name: - description: Name of the advertised address. e.g. virtual - or discovery-server - type: string - url: - description: The URL of the server. e.g. https://api.foo.bar - or https://1.2.3.4 - type: string - required: - - name - - url - type: object - type: array - type: object type: object type: object served: true storage: true subresources: status: {} - From 78038ca66cd57234545ee8bc393f80b2de147dc2 Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Thu, 28 May 2026 16:27:06 +0200 Subject: [PATCH 23/25] downgrade kubernetes packages to 1.35 Signed-off-by: Lukas Hoehl --- go.mod | 21 +- go.sum | 632 ++++++++++++++++++++++++++++++++++----------------------- 2 files changed, 395 insertions(+), 258 deletions(-) diff --git a/go.mod b/go.mod index 131be6ff..a1d3898e 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,19 @@ go 1.26.0 toolchain go1.26.3 +// gardener still uses v0.35 and build is breaking with v0.36 +replace ( + k8s.io/api => k8s.io/api v0.35.5 + k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.35.5 + k8s.io/apimachinery => k8s.io/apimachinery v0.35.5 + k8s.io/apimachinery/pkg/sharding => k8s.io/apimachinery/pkg/sharding v0.35.5 + k8s.io/apiserver => k8s.io/apiserver v0.35.5 + k8s.io/client-go => k8s.io/client-go v0.35.5 + k8s.io/code-generator => k8s.io/code-generator v0.35.5 + k8s.io/component-base => k8s.io/component-base v0.35.5 + sigs.k8s.io/controller-runtime => sigs.k8s.io/controller-runtime v0.23.3 +) + require ( github.com/gardener/gardener v1.143.1 github.com/gardener/gardener/pkg/apis v1.143.1 @@ -19,10 +32,10 @@ require ( istio.io/api v1.29.3 istio.io/client-go v1.29.2 k8s.io/api v0.36.1 - k8s.io/apiextensions-apiserver v0.36.1 + k8s.io/apiextensions-apiserver v0.36.0 k8s.io/apimachinery v0.36.1 k8s.io/client-go v0.36.1 - k8s.io/code-generator v0.36.1 + k8s.io/code-generator v0.36.0 k8s.io/component-base v0.36.1 k8s.io/utils v0.0.0-20260507154919-ff6756f316d2 sigs.k8s.io/controller-runtime v0.24.1 @@ -108,6 +121,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v5 v5.3.1 // indirect github.com/golang/protobuf v1.5.4 // indirect + github.com/google/btree v1.1.3 // indirect github.com/google/cel-go v0.27.0 // indirect github.com/google/gnostic-models v0.7.1 // indirect github.com/google/go-cmp v0.7.0 // indirect @@ -116,6 +130,7 @@ require ( github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 // indirect + github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect @@ -139,6 +154,7 @@ require ( github.com/muhlemmer/gu v0.3.1 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect + github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/nexucis/lamenv v0.5.2 // indirect github.com/perses/common v0.30.2 // indirect github.com/perses/perses v0.53.1 // indirect @@ -230,7 +246,6 @@ require ( k8s.io/kubelet v0.35.5 // indirect k8s.io/metrics v0.35.5 // indirect k8s.io/pod-security-admission v0.35.5 // indirect - k8s.io/streaming v0.36.1 // indirect sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 // indirect sigs.k8s.io/controller-tools v0.20.1 // indirect sigs.k8s.io/gateway-api v1.5.0 // indirect diff --git a/go.sum b/go.sum index 554db828..59b945ca 100644 --- a/go.sum +++ b/go.sum @@ -1,44 +1,21 @@ cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= -github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= -github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= -github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= -github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= -github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= -github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= -github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= -github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= -github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 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.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Masterminds/semver/v3 v3.5.0 h1:kQceYJfbupGfZOKZQg0kou0DgAKhzDg2NZPAwZ/2OOE= github.com/Masterminds/semver/v3 v3.5.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/PaesslerAG/gval v1.2.2/go.mod h1:XRFLwvmkTEdYziLdaCeCa5ImcGVrfQbeNUbVR+C6xac= @@ -47,10 +24,6 @@ github.com/PaesslerAG/gval v1.2.4/go.mod h1:XRFLwvmkTEdYziLdaCeCa5ImcGVrfQbeNUbV github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8= github.com/PaesslerAG/jsonpath v0.1.2-0.20240726212847-3a740cf7976f h1:TxDCeKRCgHea2hUiMOjWwqzWmrIGqSOZYkEPuClXzDo= github.com/PaesslerAG/jsonpath v0.1.2-0.20240726212847-3a740cf7976f/go.mod h1:zTyVtYhYjcHpfCtqnCMxejgp0pEEwb/xJzhn05NrkJk= -github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/VictoriaMetrics/VictoriaLogs v1.36.2-0.20251008164716-21c0fb3de84d h1:fV15mhBCGpCCBbuOAbOflO8Air+tLklMt8bG35FimzQ= github.com/VictoriaMetrics/VictoriaLogs v1.36.2-0.20251008164716-21c0fb3de84d/go.mod h1:JKZK8LZ9O38pW3+CbBSqL64nswBg6nJ0GE788b0Ps/8= github.com/VictoriaMetrics/VictoriaMetrics v1.131.0 h1:OHO0EnZ8zEm0cOtxzMFiQWJV6sn0+gnd0WbdBy00eUE= @@ -97,8 +70,11 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.41.7 h1:NITQpgo9A5NrDZ57uOWj+abvXSb8 github.com/aws/aws-sdk-go-v2/service/sts v1.41.7/go.mod h1:sks5UWBhEuWYDPdwlnRFn1w7xWdH29Jcpe+/PJQefEs= github.com/aws/smithy-go v1.24.1 h1:VbyeNfmYkWoxMVpGUAbQumkODcYmfMRfZ8yQiH30SK0= github.com/aws/smithy-go v1.24.1/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= +github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= +github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= 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/bits-and-blooms/bitset v1.22.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bmatcuk/doublestar/v4 v4.10.0 h1:zU9WiOla1YA122oLM6i4EXvGW62DvKZVxIe6TYWexEs= @@ -107,43 +83,50 @@ github.com/brunoga/deep v1.3.1 h1:bSrL6FhAZa6JlVv4vsi7Hg8SLwroDb1kgDERRVipBCo= github.com/brunoga/deep v1.3.1/go.mod h1:GDV6dnXqn80ezsLSZ5Wlv1PdKAWAO4L5PnKYtv2dgaI= github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 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/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= +github.com/charmbracelet/colorprofile v0.3.1/go.mod h1:/GkGusxNs8VB/RSOh3fu0TJmQ4ICMMPApIIVn0KszZ0= +github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= +github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q= +github.com/charmbracelet/x/ansi v0.9.2/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE= +github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= +github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= +github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= +github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= +github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= +github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= +github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA= github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= 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= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/elastic/crd-ref-docs v0.3.0 h1:9bGSUkBR56Z7TuDGQAu3KGbBkagwwZ6RkZmS+qvDuDM= github.com/elastic/crd-ref-docs v0.3.0/go.mod h1:8td3UC8CaO5M+G115O3FRKLmplmX+p0EqLMLGM6uNdk= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elliotchance/orderedmap/v3 v3.1.0 h1:j4DJ5ObEmMBt/lcwIecKcoRxIQUEnw0L804lXYDt/pg= github.com/elliotchance/orderedmap/v3 v3.1.0/go.mod h1:G+Hc2RwaZvJMcS4JpGCOyViCnGeKf0bTYCGTO4uhjSo= -github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes= github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8= github.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= @@ -172,19 +155,21 @@ github.com/gardener/gardener/pkg/apis v1.143.1 h1:zNhbd4ak2k3+gQU9RV7oyjjgPGfHfY github.com/gardener/gardener/pkg/apis v1.143.1/go.mod h1:zGVoiiKNeCwH7f6+4pQI9lOGVqkJueaONqyfyoiLDpk= github.com/gardener/machine-controller-manager v0.61.3 h1:w0JuHCKLmcK7B8E7mx3TvE3e0hSYwikchsMSiMhocqw= github.com/gardener/machine-controller-manager v0.61.3/go.mod h1:8eE1qLztrWIbOM71mHSQGaC6Q+pl5lvOyN08qP39D7o= -github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BNhXs= github.com/gkampitakis/ciinfo v0.3.2/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo= github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M= github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk= github.com/gkampitakis/go-snaps v0.5.15 h1:amyJrvM1D33cPHwVrjo9jQxX8g/7E2wYdZ+01KS3zGE= github.com/gkampitakis/go-snaps v0.5.15/go.mod h1:HNpx/9GoKisdhw9AFOBT1N7DBs9DiHo/hGheFGBZ+mc= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +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.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= @@ -193,21 +178,16 @@ 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.22.7 h1:JLFBGC0Apwdzw3484MmBqspjPbwa2SHvpDm0u5aGhUA= github.com/go-openapi/errors v0.22.7/go.mod h1://QW6SD9OsWtH6gHllUCddOXDL0tk0ZGNYHwsw4sW3w= -github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= -github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/jsonpointer v0.22.5 h1:8on/0Yp4uTb9f4XvTrM2+1CPrV05QPZXu+rvu2o9jcA= github.com/go-openapi/jsonpointer v0.22.5/go.mod h1:gyUR3sCvGSWchA2sUBJGluYMbe1zazrYWIkWPjjMUY0= -github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= -github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/jsonreference v0.21.5 h1:6uCGVXU/aNF13AQNggxfysJ+5ZcU4nEAe+pJyVWRdiE= github.com/go-openapi/jsonreference v0.21.5/go.mod h1:u25Bw85sX4E2jzFodh1FOKMTZLcfifd1Q+iKKOUxExw= -github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= -github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= -github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-openapi/swag v0.25.4 h1:OyUPUFYDPDBMkqyxOTkqDYFnrhuhi9NR6QVUvIochMU= github.com/go-openapi/swag v0.25.4/go.mod h1:zNfJ9WZABGHCFg2RnY0S4IOkAcVTzJ6z2Bi+Q4i6qFQ= github.com/go-openapi/swag/cmdutils v0.25.4 h1:8rYhB5n6WawR192/BfUu2iVlxqVR9aRgGJP6WaBoW+4= @@ -238,6 +218,8 @@ github.com/go-openapi/testify/enable/yaml/v2 v2.4.0 h1:7SgOMTvJkM8yWrQlU8Jm18VeD github.com/go-openapi/testify/enable/yaml/v2 v2.4.0/go.mod h1:14iV8jyyQlinc9StD7w1xVPW3CO3q1Gj04Jy//Kw4VM= github.com/go-openapi/testify/v2 v2.4.0 h1:8nsPrHVCWkQ4p8h1EsRVymA2XABB4OT40gcvAu+voFM= github.com/go-openapi/testify/v2 v2.4.0/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= 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/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= @@ -246,75 +228,70 @@ github.com/gobuffalo/flect v1.0.3 h1:xeWBM2nui+qnVvNM4S3foBhCAL2XgPU+a7FdpelbTq4 github.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= 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/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= +github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/cel-go v0.27.0 h1:e7ih85+4qVrBuqQWTW4FKSqZYokVuc3HnhH5keboFTo= github.com/google/cel-go v0.27.0/go.mod h1:tTJ11FWqnhw5KKpnWpvW9CJC3Y9GK4EIS0WXnBbebzw= +github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= github.com/google/gnostic-models v0.7.1 h1:SisTfuFKJSKM5CPZkffwi6coztzzeYUhc3v4yxLWH8c= github.com/google/gnostic-models v0.7.1/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.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/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= +github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= +github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/pprof v0.0.0-20260402051712-545e8a4df936 h1:EwtI+Al+DeppwYX2oXJCETMO23COyaKGP6fHVpkpWpg= github.com/google/pprof v0.0.0-20260402051712-545e8a4df936/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 h1:B+8ClL/kCQkRiU82d9xajRPKYMrB7E0MbtzWVi1K4ns= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3/go.mod h1:NbCUVmiS4foBGBHOYlCT25+YmGpJ32dZPi75pGEUpj4= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -322,38 +299,32 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY 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/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.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I= github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/joshdk/go-junit v1.0.0 h1:S86cUKIdwBHWwA6xCmFlf3RTLfVXYQfvanM5Uh+K6GE= github.com/joshdk/go-junit v1.0.0/go.mod h1:TiiV0PqkaNfFXjEiyjWM3XXrhVyCa1K4Zfga6W52ung= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/json-iterator/go v1.1.13-0.20220915233716-71ac16282d12 h1:9Nu54bhS/H/Kgo2/7xNSUuC5G28VR8ljfrLKU2G4IjU= github.com/json-iterator/go v1.1.13-0.20220915233716-71ac16282d12/go.mod h1:TBzl5BIHNXfS9+C35ZyJaklL7mLDbgUkcgXzSLa8Tk0= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= 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.18.6 h1:2jupLlAwFm95+YDR+NwD2MEfFO9d4z4Prjl1XXDjuao= github.com/klauspost/compress v1.18.6/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= @@ -365,16 +336,16 @@ github.com/labstack/echo/v4 v4.15.1 h1:S9keusg26gZpjMmPqB5hOEvNKnmd1lNmcHrbbH2ln github.com/labstack/echo/v4 v4.15.1/go.mod h1:xmw1clThob0BSVRX1CRQkGQ/vjwcpOMjQZSZa9fKA/c= github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= -github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo= github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE= github.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= @@ -388,34 +359,82 @@ github.com/moby/spdystream v0.5.1/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVO 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= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= github.com/muhlemmer/gu v0.3.1 h1:7EAqmFrW7n3hETvuAdmFmn4hS8W+z3LgKtrnow+YzNM= github.com/muhlemmer/gu v0.3.1/go.mod h1:YHtHR+gxM+bKEIIs7Hmi9sPT3ZDUvTN/i88wQpZkrdM= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 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/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +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/nexucis/lamenv v0.5.2 h1:tK/u3XGhCq9qIoVNcXsK9LZb8fKopm0A5weqSRvHd7M= github.com/nexucis/lamenv v0.5.2/go.mod h1:HusJm6ltmmT7FMG8A750mOLuME6SHCsr2iFYxp5fFi0= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= -github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= +github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= +github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0= +github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= +github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw= +github.com/onsi/ginkgo/v2 v2.7.0/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo= +github.com/onsi/ginkgo/v2 v2.8.1/go.mod h1:N1/NbDngAFcSLdyZ+/aYTYGSlq9qMCS/cNKGJjy+csc= +github.com/onsi/ginkgo/v2 v2.9.0/go.mod h1:4xkjoL/tZv4SMWeww56BU5kAt19mVB47gTWxmrTcxyk= +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.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= +github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0= +github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= +github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= +github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= +github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= +github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= +github.com/onsi/ginkgo/v2 v2.20.1/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI= +github.com/onsi/ginkgo/v2 v2.22.1/go.mod h1:S6aTpoRsSq2cZOd+pssHAlKW/Q/jZt6cPrPlnj4a1xM= +github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= +github.com/onsi/ginkgo/v2 v2.25.1/go.mod h1:ppTWQ1dh9KM/F1XgpeRqelR+zHVwV81DGRSDnFxK7Sk= +github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= github.com/onsi/ginkgo/v2 v2.29.0 h1:rfh+ZFjgJhYWRoIqVf3Uwx/W20yLrcrE2h2GmYVRaag= github.com/onsi/ginkgo/v2 v2.29.0/go.mod h1:+aXOY+vzZ5mu2iI2HpTZUPmM//oQfsNFX6gU9kNcA44= -github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +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= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= +github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc= +github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM= +github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= +github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM= +github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= +github.com/onsi/gomega v1.27.1/go.mod h1:aHX5xOykVYzWOV4WqQy0sy8BQptgukenXpCXfadcIAw= +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.27.7/go.mod h1:1p8OOlwo2iUUDsHnOrjE5UKYJ+e3W8eQ3qSlRahPmr4= +github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/onsi/gomega v1.33.0/go.mod h1:+925n5YtiFsLzzafLUHzVMBpvvRAzrydIBiSIxjX3wY= +github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= +github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= +github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= +github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= +github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= +github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= github.com/onsi/gomega v1.41.0 h1:OwKp4pXNgVxf6sCplzYo794OFNuoL2q2SBMU5NSWOjA= github.com/onsi/gomega v1.41.0/go.mod h1:M/Uqpu/8qTjtzCLUA2zJHX9Iilrau25x1PdoSRbWh5A= +github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= github.com/perses/common v0.30.2 h1:RAiVxUpX76lTCb4X7pfcXSvYdXQmZwKi4oDKAEO//u0= github.com/perses/common v0.30.2/go.mod h1:DFtur1QPah2/ChXbKKhw7djYdwNgz27s5fPKpiK0Xao= github.com/perses/perses v0.53.1 h1:9VY/6p9QWrZwPSV7qiwTMSOsgcB37Lb1AXKT0ORXc6I= @@ -423,18 +442,19 @@ github.com/perses/perses v0.53.1/go.mod h1:ro8fsgBkHYOdrL/MV+fdP9mflKzYCy/+gcbxi github.com/perses/perses-operator v0.4.0 h1:BA5LG7xUCB0Z/FYIrYXcxtsH9/W53cyTn+hXn4xtRFI= github.com/perses/perses-operator v0.4.0/go.mod h1:6eDQZrm6lpIemcsfrDHOzpOE4yXr5wSXL2G4aGxjP/M= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= 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/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.91.0 h1:m2SZ2z5edgk0nXx7W6VHLfIsKZwgKbr+E5c2RNYyJB8= github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.91.0/go.mod h1:Gfzi4500QCMnptFIQc8YdDi8YZ4QA0vs22LROWZ3+YU= github.com/prometheus/alertmanager v0.29.0 h1:/ET4NmAGx2Dv9kStrXIBqBgHyiSgIk4OetY+hoZRfgc= github.com/prometheus/alertmanager v0.29.0/go.mod h1:SjI2vhrfdWg10UaRUxTz27rgdJVG3HXrhI5WFjCdBgs= github.com/prometheus/client_golang v1.23.3-0.20260518105423-c9d5bc4c50a9 h1:rneH9T2i7VvR/2yKvhQ8bkmFEdJ6yuP/2UC8Wx71vIM= github.com/prometheus/client_golang v1.23.3-0.20260518105423-c9d5bc4c50a9/go.mod h1:QRA+KSZEtitKV4dtGtD9gCh8T2Gy4gifR1dqcT1MMss= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.67.6-0.20260224092343-e4c38a0aea47 h1:DXz2mpU9UOivlNi73hwwVm7KSYGImaPDdYsniI6uOdE= @@ -445,9 +465,13 @@ github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEy github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= github.com/prometheus/sigv4 v0.3.0 h1:QIG7nTbu0JTnNidGI1Uwl5AGVIChWUACxn2B/BQ1kms= github.com/prometheus/sigv4 v0.3.0/go.mod h1:fKtFYDus2M43CWKMNtGvFNHGXnAJJEGZbiYCmVp/F8I= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -460,35 +484,40 @@ github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= -github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= @@ -513,11 +542,14 @@ 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/xiang90/probing v0.0.0-20221125231312-a49e3df8f510 h1:S2dVYn90KE98chqDkyE9Z4N61UnQd+KOfgp5Iu53llk= github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zitadel/oidc/v3 v3.45.4 h1:GKyWaPRVQ8sCu9XgJ3NgNGtG52FzwVJpzXjIUG2+YrI= github.com/zitadel/oidc/v3 v3.45.4/go.mod h1:XALmFXS9/kSom9B6uWin1yJ2WTI/E4Ti5aXJdewAVEs= github.com/zitadel/schema v1.3.2 h1:gfJvt7dOMfTmxzhscZ9KkapKo3Nei3B6cAxjav+lyjI= @@ -530,15 +562,12 @@ go.etcd.io/etcd/client/pkg/v3 v3.6.8 h1:Qs/5C0LNFiqXxYf2GU8MVjYUEXJ6sZaYOz0zEqQg go.etcd.io/etcd/client/pkg/v3 v3.6.8/go.mod h1:GsiTRUZE2318PggZkAo6sWb6l8JLVrnckTNfbG8PWtw= go.etcd.io/etcd/client/v3 v3.6.8 h1:B3G76t1UykqAOrbio7s/EPatixQDkQBevN8/mwiplrY= go.etcd.io/etcd/client/v3 v3.6.8/go.mod h1:MVG4BpSIuumPi+ELF7wYtySETmoTWBHVcDoHdVupwt8= -go.etcd.io/etcd/pkg/v3 v3.6.8 h1:Xe+LIL974spy8b4nEx3H0KMr1ofq3r0kh6FbU3aw4es= -go.etcd.io/etcd/pkg/v3 v3.6.8/go.mod h1:TRibVNe+FqJIe1abOAA1PsuQ4wqO87ZaOoprg09Tn8c= -go.etcd.io/etcd/server/v3 v3.6.8 h1:U2strdSEy1U8qcSzRIdkYpvOPtBy/9i/IfaaCI9flZ4= -go.etcd.io/etcd/server/v3 v3.6.8/go.mod h1:88dCtwUnSirkUoJbflQxxWXqtBSZa6lSG0Kuej+dois= +go.etcd.io/etcd/pkg/v3 v3.6.5 h1:byxWB4AqIKI4SBmquZUG1WGtvMfMaorXFoCcFbVeoxM= +go.etcd.io/etcd/pkg/v3 v3.6.5/go.mod h1:uqrXrzmMIJDEy5j00bCqhVLzR5jEJIwDp5wTlLwPGOU= +go.etcd.io/etcd/server/v3 v3.6.5 h1:4RbUb1Bd4y1WkBHmuF+cZII83JNQMuNXzyjwigQ06y0= +go.etcd.io/etcd/server/v3 v3.6.5/go.mod h1:PLuhyVXz8WWRhzXDsl3A3zv/+aK9e4A9lpQkqawIaH0= go.etcd.io/raft/v3 v3.6.0 h1:5NtvbDVYpnfZWcIHgGRk9DyzkBIXOi8j+DDp1IcnUWQ= go.etcd.io/raft/v3 v3.6.0/go.mod h1:nLvLevg6+xrVtHUmVaTcTz603gQPHfh7kUAwV6YpfGo= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.65.0 h1:XmiuHzgJt067+a6kwyAzkhXooYVv3/TOw9cM2VfJgUM= @@ -587,6 +616,7 @@ go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09 go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= +go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= 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.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= @@ -595,21 +625,20 @@ 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.28.0 h1:IZzaP1Fv73/T/pBMLk4VutPl36uNC+OSUh3JLG3FIjo= go.uber.org/zap v1.28.0/go.mod h1:rDLpOi171uODNm/mxFcuYWxDsqWSAVkFdX4XojSKg/Q= +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= +go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= go.yaml.in/yaml/v4 v4.0.0-rc.2 h1:/FrI8D64VSr4HtGIlUtlFMGsm7H7pWTbj6vOLVZcA6s= go.yaml.in/yaml/v4 v4.0.0-rc.2/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988= -golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc= +golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= +golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -617,129 +646,250 @@ golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm0 golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 h1:jiDhWWeC7jfWqR9c/uplMOqJ0sbNlNWv0UkzE0vX1MA= golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90/go.mod h1:xE1HEv6b+1SCZ5/uscMRjUBKtIxworgEcEi+/n9NQDQ= -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= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 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/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +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.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= +golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= +golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4= golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ= 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= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/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-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= +golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= +golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w= golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ= -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= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= 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= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= -golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= +golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/telemetry v0.0.0-20260508192327-42602be52be6 h1:HjU6IWBiAgRIdAJ9/y1rwCn+UELEmwV+VsTLzj/W4sE= golang.org/x/telemetry v0.0.0-20260508192327-42602be52be6/go.mod h1:Eqhaxk/wZsWEH8CRxLwj6xzEJbz7k1EFGqx7nyCoabE= 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= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= +golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= +golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0= +golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= +golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= +golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= 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= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +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.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= +golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= -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= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +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.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= +golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= +golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= +golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= +golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= +golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= +golang.org/x/tools v0.34.1-0.20250613162507-3f93fece84c7/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= +golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= +golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= +golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8= golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0= +golang.org/x/tools/go/expect v0.1.0-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= @@ -752,36 +902,11 @@ gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0 gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto/googleapis/api v0.0.0-20260406210006-6f92a3bedf2d h1:/aDRtSZJjyLQzm75d+a1wOJaqyKBMvIAfeQmoa3ORiI= google.golang.org/genproto/googleapis/api v0.0.0-20260406210006-6f92a3bedf2d/go.mod h1:etfGUgejTiadZAUaEP14NP97xi1RGeawqkjDARA/UOs= google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d h1:wT2n40TBqFY6wiwazVK9/iTWbsQrgk5ZfCSVFLO9LQA= google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -789,18 +914,23 @@ google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI= google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= 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= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo= gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= @@ -810,9 +940,9 @@ gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 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.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -820,48 +950,40 @@ 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/v4 v4.1.4 h1:zwTrNkalG4f7SYigRSdQnYrTj0QEz1qzetzAlYoDVSo= helm.sh/helm/v4 v4.1.4/go.mod h1:5dSo8rRgn3OTkDAc/k0Ipw5/Q+BlqKIKZwa0XwSiINI= -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= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= istio.io/api v1.29.3 h1:olbjGA/wLDB62U3SsBn+lFHHnugnDTLoCRE0pBWXZ8M= istio.io/api v1.29.3/go.mod h1:+brQWcBHoROuyA6fv8rbgg8Kfn0RCGuqoY0duCMuSLA= istio.io/client-go v1.29.2 h1:aljV/qXcEGgRYisPTJ7L0Nx8GXWbM8rZgr1eEAC3bCw= istio.io/client-go v1.29.2/go.mod h1:RazwM5KR3FzhWXrvjCq1o85ReFNrHcG3cF2lcs5anzg= -k8s.io/api v0.19.0/go.mod h1:I1K45XlvTrDjmj5LoM5LuP/KYrhWbjUKT/SoPG0qTjw= -k8s.io/api v0.36.1 h1:XbL/EMj8K2aJpJtePmqUyQMsM0D4QI2pvl7YKJ20FTY= -k8s.io/api v0.36.1/go.mod h1:KOWo4ey3TINlXjeHVuwB3i+tXXnu+UcwFBHlI/9dvEo= -k8s.io/apiextensions-apiserver v0.36.1 h1:6JfYmPUsuUIHuN+3QxutXYWj492RqF5fBSx67GYK5Ks= -k8s.io/apiextensions-apiserver v0.36.1/go.mod h1:pLzZin90riwisdzKwv/GoTwENooytoIx5zWJb4Hkby8= -k8s.io/apimachinery v0.19.0/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= -k8s.io/apimachinery v0.36.1 h1:G63Gjx2W+q0YD+72Vo8oY0nDnePVwnuzTmmy5ENrVSA= -k8s.io/apimachinery v0.36.1/go.mod h1:ibYOR00vW/I1kzvi5SF0dRuJ52BvKtfvRdOn35GPQ+8= -k8s.io/apiserver v0.36.1 h1:iMS5V+rPUertv5P9RaqJgmHHTuh4quWpoxchvMUY+JY= -k8s.io/apiserver v0.36.1/go.mod h1:Cby1PbLWztu0GDOxoO6iFOyyqIsziHNEW+w9zVQ22Kw= +k8s.io/api v0.35.5 h1:BrFeUDGY/LBtlA1R5RoxhlYRHs76RnQBc6xbm/y7hsQ= +k8s.io/api v0.35.5/go.mod h1:xWkFhMnoPZdTAQh95Rlw3zZpUUNVlFHcuESUYd06BWM= +k8s.io/apiextensions-apiserver v0.35.5 h1:HttlJjgsx3ddLsASCqklkKvfBlwUoXma8VLpeMG5YL8= +k8s.io/apiextensions-apiserver v0.35.5/go.mod h1:4xbAgP/jbt8sVHE3H4DfE1gSPLUoSzXrNqhZz1lTHKc= +k8s.io/apimachinery v0.35.5 h1:lbjjjUfVeVqFbiOpyhqZHc8DhiYkWOxSNij7lHx2U8Y= +k8s.io/apimachinery v0.35.5/go.mod h1:NNi1taPOpep0jOj+oRha3mBJPqvi0hGdaV8TCqGQ+cc= +k8s.io/apiserver v0.35.5 h1:ZtFpSEmxf/VmOdbL3bo7hLxyNRorRegqOLmYSW0mxEo= +k8s.io/apiserver v0.35.5/go.mod h1:6NNWFTq/UosCwUmqhQDC+3ApzSx5ekeYMIwzSG+49VU= k8s.io/autoscaler/vertical-pod-autoscaler v1.6.0 h1:JC2YsVS6njOY8+a2mr8YX2FwZCpWfe7oVzjk98YPKZg= k8s.io/autoscaler/vertical-pod-autoscaler v1.6.0/go.mod h1:w7pOVKXZAZsct/dXWsGJflrGOTkMpBxI75KyQjUYg7Y= -k8s.io/client-go v0.19.0/go.mod h1:H9E/VT95blcFQnlyShFgnFT9ZnJOAceiUHM3MlRC+mU= -k8s.io/client-go v0.36.1 h1:FN/K8QIT2CEDt+2WB2HnWrUANZ50AP5GII43/SP2JR0= -k8s.io/client-go v0.36.1/go.mod h1:s6rAnCtTGYDQnpNjEhSaISV+2O8jwruZ6m3QOYBFbtU= -k8s.io/code-generator v0.19.0/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= -k8s.io/code-generator v0.36.1 h1:5bHQ7NbBcFFLHcoyo/hgU3m2tQV5RLz2nv4QNDlsbXc= -k8s.io/code-generator v0.36.1/go.mod h1:oCv8WmrW2RGdcMyvSk1aYbBfSs51ggtSFQr1YNeuAuo= -k8s.io/component-base v0.36.1 h1:iG6GsELftXqTNG9HG6kiVjatSgAw1sf5pJ6R5a6N0kA= -k8s.io/component-base v0.36.1/go.mod h1:nf9XPlntRdqO6WMeEWAA5F93Y4ICZQdeT9GeqLDB3JI= -k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/client-go v0.35.5 h1:wUrgqVSmFRw75bgSHY7X0G/hZM/QYpV0Hg7SYYOYpFk= +k8s.io/client-go v0.35.5/go.mod h1:Z0mDcAJsX1Y7RQfuQlJipiRtqf8Mhk2VDu1/JvRqdGo= +k8s.io/code-generator v0.35.5 h1:g2ZIw7LCjmX2p5WDjtkVYwmvtx+pDF0Pq1dfgCoHkhQ= +k8s.io/code-generator v0.35.5/go.mod h1:W46pDvFxY2SlphV3MBI/6KDZ2JDMhHXGVgPQXMoYFiM= +k8s.io/component-base v0.35.5 h1:1y1xxfpFNkNi4RMi6bvPNN4aDr9VhOijtEfrqnhPijs= +k8s.io/component-base v0.35.5/go.mod h1:n/+aL98XYINubqIu/Okh6mS/kZT2nMeN4IQkQR4VXRg= +k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= +k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b/go.mod h1:CgujABENc3KuTrcsdpGmrrASjtQsWCT7R99mEV4U/fM= k8s.io/gengo/v2 v2.0.0-20251215205346-5ee0d033ba5b h1:0YkdvW3rX2vaBWsqCGZAekxPRwaI5NuYNprOsMNVLns= k8s.io/gengo/v2 v2.0.0-20251215205346-5ee0d033ba5b/go.mod h1:yvyl3l9E+UxlqOMUULdKTAYB0rEhsmjr7+2Vb/1pCSo= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= k8s.io/kms v0.36.1 h1:XdvKpywoW4k7YUHDh5uYP4mahJXECswHGfCddBBYLZs= k8s.io/kms v0.36.1/go.mod h1:g91diTD9h0oJCCHkTb00krlF+Qm5HTnkWLi9Q/TpRoc= k8s.io/kube-aggregator v0.35.5 h1:oLflHAqh8tEoEcXtrzGhr4hctwhcRr5B1sM+T96N1rs= k8s.io/kube-aggregator v0.35.5/go.mod h1:L3GflyN8a8CDjej2UxgeGwRiXYuI+aTZ0GE7qssdN2w= -k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= +k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a h1:xCeOEAOoGYl2jnJoHkC3hkbPJgdATINPMAxaynU2Ovg= k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a/go.mod h1:uGBT7iTA6c6MvqUvSXIaYZo9ukscABYi2btjhvgKGZ0= k8s.io/kubelet v0.35.5 h1:asU07lJvTB9lK7XPEcQJdPrV96eu/zNGkJVSEWeZFFQ= @@ -870,28 +992,28 @@ k8s.io/metrics v0.35.5 h1:Xy5sIUvQFoWC2OZ7E4VEQgZlbQR+0PtfdIuieCYF2kU= k8s.io/metrics v0.35.5/go.mod h1:NMfFh5jgoyzOXr8rCXQjgj8RAclft68I93OIQvjSQoc= k8s.io/pod-security-admission v0.35.5 h1:R+FbF2OyANMBYkMFtavHyNVOE82VeewRtLXGdADqkjk= k8s.io/pod-security-admission v0.35.5/go.mod h1:36iCuuOBK1re5qU1/WGu3JsOytNRUWq/RhdqAG1gU+E= -k8s.io/streaming v0.36.1 h1:L+K68n4Gg940BGNNYtUBvL1WTLL0YnKT3s+P1MNAmR4= -k8s.io/streaming v0.36.1/go.mod h1:z6fV3D+NVkoeqRMtWwlUZK6U17SY/LqNzOxWL6GyR/s= -k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= k8s.io/utils v0.0.0-20260507154919-ff6756f316d2 h1:wU4tMEhLGgIbLvXQb1cfN+EcM0wf7zC6CPF+C79jroc= k8s.io/utils v0.0.0-20260507154919-ff6756f316d2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 h1:hSfpvjjTQXQY2Fol2CS0QHMNs/WI1MOSGzCm1KhM5ec= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= -sigs.k8s.io/controller-runtime v0.24.1 h1:miPEwrmirImAvgME1L9qebGHrOnGJoVmVdtOU9fRfo4= -sigs.k8s.io/controller-runtime v0.24.1/go.mod h1:vFkfY5fGt5xAC/sKb8IBFKgWPNKG9OUG29dR8Y2wImw= +sigs.k8s.io/controller-runtime v0.23.3 h1:VjB/vhoPoA9l1kEKZHBMnQF33tdCLQKJtydy4iqwZ80= +sigs.k8s.io/controller-runtime v0.23.3/go.mod h1:B6COOxKptp+YaUT5q4l6LqUJTRpizbgf9KSRNdQGns0= sigs.k8s.io/controller-tools v0.20.1 h1:gkfMt9YodI0K85oT8rVi80NTXO/kDmabKR5Ajn5GYxs= sigs.k8s.io/controller-tools v0.20.1/go.mod h1:b4qPmjGU3iZwqn34alUU5tILhNa9+VXK+J3QV0fT/uU= sigs.k8s.io/gateway-api v1.5.0 h1:duoo14Ky/fJXpjpmyMISE2RTBGnfCg8zICfTYLTnBJA= sigs.k8s.io/gateway-api v1.5.0/go.mod h1:GvCETiaMAlLym5CovLxGjS0NysqFk3+Yuq3/rh6QL2o= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= +sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= -sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v6 v6.2.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/structured-merge-diff/v6 v6.3.2 h1:kwVWMx5yS1CrnFWA/2QHyRVJ8jM6dBA80uLmm0wJkk8= sigs.k8s.io/structured-merge-diff/v6 v6.3.2/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= From b38c4ac229b9db1cc279e0d9ac81606aaeda9352 Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Fri, 29 May 2026 11:19:08 +0200 Subject: [PATCH 24/25] adapt tests to include proxy tests Signed-off-by: Lukas Hoehl --- pkg/controller/actuator_shoot_test.go | 95 ++++---------- pkg/controller/allowedcidrs/shoot_test.go | 148 ++++++++++++++++++++++ pkg/controller/suite_test.go | 5 +- 3 files changed, 173 insertions(+), 75 deletions(-) create mode 100644 pkg/controller/allowedcidrs/shoot_test.go diff --git a/pkg/controller/actuator_shoot_test.go b/pkg/controller/actuator_shoot_test.go index 7e85d92b..fbf00209 100644 --- a/pkg/controller/actuator_shoot_test.go +++ b/pkg/controller/actuator_shoot_test.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" + gardenercorev1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants" extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" "github.com/gardener/gardener/pkg/apis/resources/v1alpha1" . "github.com/gardener/gardener/pkg/utils/test/matchers" @@ -14,7 +15,6 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/utils/ptr" "github.com/stackitcloud/gardener-extension-acl/pkg/controller/config" "github.com/stackitcloud/gardener-extension-acl/pkg/envoyfilters" @@ -27,13 +27,11 @@ var _ = Describe("actuator shoot test", func() { shootNamespace1, shootNamespace2 string istioNamespace1, istioNamespace2 string istioNamespace1Selector, istioNamespace2Selector map[string]string - istioIngressGatewayServiceName string ) BeforeEach(func() { shootNamespace1 = createNewShootNamespace() istioNamespace1 = createNewIstioNamespace() - istioIngressGatewayServiceName = "istio-ingressgateway" istioNamespace1Selector = map[string]string{ "app": "istio-ingressgateway", "istio": istioNamespace1, @@ -44,24 +42,6 @@ var _ = Describe("actuator shoot test", func() { createNewIstioDeployment(istioNamespace1, istioNamespace1Selector) createNewCluster(shootNamespace1) createNewInfrastructure(shootNamespace1) - createNewService( - istioIngressGatewayServiceName, - istioNamespace1, - istioNamespace1Selector, - corev1.ServiceTypeLoadBalancer, - ) - updateServiceStatus( - istioIngressGatewayServiceName, - istioNamespace1, - corev1.ServiceStatus{ - LoadBalancer: corev1.LoadBalancerStatus{ - Ingress: []corev1.LoadBalancerIngress{{ - IP: "1.1.1.1", - IPMode: ptr.To(corev1.LoadBalancerIPModeProxy), - }}, - }, - }, - ) a = getNewActuator() }) @@ -239,65 +219,37 @@ var _ = Describe("actuator shoot test", func() { Expect(secret.Data["seed"]).To(ContainSubstring("1.2.3.4")) Expect(secret.Data["seed"]).To(ContainSubstring(istioNamespace1)) Expect(secret.Data["seed"]).To(ContainSubstring("acl-vpn-" + shootNamespace1)) - }) }) Describe("reconciliation of an extension object running on a managedSeed", func() { AfterEach(func() { deleteShootInfo() - }) - - It("should not get the egressIPs if the LoadBalancer IPMode is not set to Proxy", func() { - updateServiceStatus( - istioIngressGatewayServiceName, - istioNamespace1, - corev1.ServiceStatus{}, - ) - Expect(a.usesProxyTypeLBService(ctx, istioNamespace1)).To(BeFalse()) - - updateServiceStatus( - istioIngressGatewayServiceName, - istioNamespace1, - corev1.ServiceStatus{ - LoadBalancer: corev1.LoadBalancerStatus{ - Ingress: []corev1.LoadBalancerIngress{{ - IP: "1.1.1.1", - IPMode: ptr.To(corev1.LoadBalancerIPModeVIP), - }}, + Expect(func() error { + svc := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: gardenercorev1beta1constants.DefaultSNIIngressServiceName, + Namespace: istioNamespace1, }, - }, - ) - Expect(a.usesProxyTypeLBService(ctx, istioNamespace1)).To(BeFalse()) - }) - - It("should get the egressIPs if the LoadBalancer IPMode is set to Proxy", func() { - Expect(a.usesProxyTypeLBService(ctx, istioNamespace1)).To(BeTrue()) - }) - - It("should return an empty slice of egressIPs if no shoot-info ConfigMap exists", func() { - cidrs, err := a.getSeedEgressIPOnManagedSeeds(ctx) - Expect(err).ToNot(HaveOccurred()) - Expect(cidrs).To(BeEmpty()) - }) - - It("should fail to return egressIPs if the shoot-info ConfigMap contains invalid CIDRs", func() { - createShootInfo([]string{"1.1.1.1", "1.1.1.2/32"}) - - _, err := a.getSeedEgressIPOnManagedSeeds(ctx) - Expect(err).To(HaveOccurred()) - }) - - It("should return the egressIP CIDRs of the shoot-info ConfigMap", func() { - c := []string{"1.1.1.1/32", "1.1.1.2/32"} - createShootInfo(c) - - cidrs, err := a.getSeedEgressIPOnManagedSeeds(ctx) - Expect(err).ToNot(HaveOccurred()) - Expect(cidrs).To(BeEquivalentTo(c)) + } + err := k8sClient.Delete(ctx, svc) + if err != nil && !apierrors.IsNotFound(err) { + return err + } + return nil + }()).ShouldNot(HaveOccurred()) }) It("should create ACLs including egressIPs of managedSeed", func() { + createNewService(gardenercorev1beta1constants.DefaultSNIIngressServiceName, istioNamespace1, corev1.ServiceTypeLoadBalancer) + updateServiceStatus(gardenercorev1beta1constants.DefaultSNIIngressServiceName, istioNamespace1, corev1.ServiceStatus{ + LoadBalancer: corev1.LoadBalancerStatus{ + Ingress: []corev1.LoadBalancerIngress{{ + IP: "10.0.0.2", + IPMode: new(corev1.LoadBalancerIPModeProxy), + }}, + }, + }) createShootInfo([]string{"1.1.1.1/32", "1.1.1.2/32"}) extSpec := extensionspec.ExtensionSpec{ @@ -309,7 +261,7 @@ var _ = Describe("actuator shoot test", func() { } extSpecJSON, err := json.Marshal(extSpec) Expect(err).NotTo(HaveOccurred()) - ext := createNewExtension(shootNamespace1, extSpecJSON) + ext := createNewExtension(shootNamespace1, extSpecJSON, extensionsv1alpha1.ExtensionClassShoot) Expect(ext).To(Not(BeNil())) Expect(a.Reconcile(ctx, logger, ext)).To(Succeed()) @@ -431,7 +383,6 @@ var _ = Describe("actuator shoot test", func() { err = k8sClient.Get(ctx, types.NamespacedName{Name: ResourceNameSeed, Namespace: shootNamespace1}, mr) Expect(err).To(HaveOccurred()) Expect(apierrors.IsNotFound(err)).To(BeTrue()) - }) }) }) diff --git a/pkg/controller/allowedcidrs/shoot_test.go b/pkg/controller/allowedcidrs/shoot_test.go new file mode 100644 index 00000000..51876cf0 --- /dev/null +++ b/pkg/controller/allowedcidrs/shoot_test.go @@ -0,0 +1,148 @@ +package allowedcidrs + +import ( + "context" + "strings" + + gardenercorev1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" +) + +var _ = Describe("Shoot", func() { + var shoot *Shoot + istioNamespace := "istio-ingress" + istioIngressGatewayServiceName := "istio-ingressgateway" + var k8sClient client.Client + + BeforeEach(func() { + k8sClient = fake.NewFakeClient() + shoot = &Shoot{ + Client: k8sClient, + IstioNamespace: istioNamespace, + } + }) + + Describe("#usesProxyTypeLBService", func() { + BeforeEach(func(ctx context.Context) { + createNewService( + ctx, + k8sClient, + istioIngressGatewayServiceName, + istioNamespace, + corev1.ServiceTypeLoadBalancer, + ) + updateServiceStatus( + ctx, + k8sClient, + istioIngressGatewayServiceName, + istioNamespace, + corev1.ServiceStatus{ + LoadBalancer: corev1.LoadBalancerStatus{ + Ingress: []corev1.LoadBalancerIngress{{ + IP: "1.1.1.1", + IPMode: ptr.To(corev1.LoadBalancerIPModeProxy), + }}, + }, + }, + ) + }) + + It("should not get the egressIPs if the LoadBalancer IPMode is not set to Proxy", func(ctx context.Context) { + updateServiceStatus( + ctx, + k8sClient, + istioIngressGatewayServiceName, + istioNamespace, + corev1.ServiceStatus{}, + ) + Expect(shoot.usesProxyTypeLBService(ctx)).To(BeFalse()) + + updateServiceStatus( + ctx, + k8sClient, + istioIngressGatewayServiceName, + istioNamespace, + corev1.ServiceStatus{ + LoadBalancer: corev1.LoadBalancerStatus{ + Ingress: []corev1.LoadBalancerIngress{{ + IP: "1.1.1.1", + IPMode: ptr.To(corev1.LoadBalancerIPModeVIP), + }}, + }, + }, + ) + Expect(shoot.usesProxyTypeLBService(ctx)).To(BeFalse()) + }) + + It("should get the egressIPs if the LoadBalancer IPMode is set to Proxy", func(ctx context.Context) { + Expect(shoot.usesProxyTypeLBService(ctx)).To(BeTrue()) + }) + }) + Describe("#getSeedEgressIPOnManagedSeeds", func() { + It("should return an empty slice of egressIPs if no shoot-info ConfigMap exists", func(ctx context.Context) { + cidrs, err := shoot.getSeedEgressIPOnManagedSeeds(ctx) + Expect(err).ToNot(HaveOccurred()) + Expect(cidrs).To(BeEmpty()) + }) + + It("should fail to return egressIPs if the shoot-info ConfigMap contains invalid CIDRs", func(ctx context.Context) { + createShootInfo(ctx, k8sClient, []string{"1.1.1.1", "1.1.1.2/32"}) + + _, err := shoot.getSeedEgressIPOnManagedSeeds(ctx) + Expect(err).To(HaveOccurred()) + }) + + It("should return the egressIP CIDRs of the shoot-info ConfigMap", func(ctx context.Context) { + c := []string{"1.1.1.1/32", "1.1.1.2/32"} + createShootInfo(ctx, k8sClient, c) + + cidrs, err := shoot.getSeedEgressIPOnManagedSeeds(ctx) + Expect(err).ToNot(HaveOccurred()) + Expect(cidrs).To(BeEquivalentTo(c)) + }) + }) +}) + +func createNewService(ctx context.Context, k8sClient client.Client, name, namespace string, serviceType corev1.ServiceType) { + svc := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Spec: corev1.ServiceSpec{ + Type: serviceType, + Ports: []corev1.ServicePort{{ + Port: 80, + }}, + }, + } + GinkgoLogr.Info("creating service", "name", svc.Name, "namespace", svc.Namespace, "labels", svc.Labels) + Expect(k8sClient.Create(ctx, svc)).ShouldNot(HaveOccurred()) +} + +func updateServiceStatus(ctx context.Context, k8sClient client.Client, name, namespace string, status corev1.ServiceStatus) { + svc := &corev1.Service{} + Expect(k8sClient.Get(ctx, types.NamespacedName{Name: name, Namespace: namespace}, svc)).ShouldNot(HaveOccurred()) + svc.Status = status + Expect(k8sClient.Status().Update(ctx, svc)).ShouldNot(HaveOccurred()) +} + +func createShootInfo(ctx context.Context, k8sClient client.Client, cidrs []string) { + cm := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: gardenercorev1beta1constants.ConfigMapNameShootInfo, + Namespace: "kube-system", + }, + Data: map[string]string{ + "egressCIDRs": strings.Join(cidrs, ","), + }, + } + Expect(k8sClient.Create(ctx, cm)).ShouldNot(HaveOccurred()) +} diff --git a/pkg/controller/suite_test.go b/pkg/controller/suite_test.go index 479112f8..a75d0756 100644 --- a/pkg/controller/suite_test.go +++ b/pkg/controller/suite_test.go @@ -182,10 +182,9 @@ func createNewGateway(name, shootNamespace string, labels map[string]string) *is return gw } -func createNewService(name, namespace string, labels map[string]string, serviceType corev1.ServiceType) { +func createNewService(name, namespace string, serviceType corev1.ServiceType) { svc := &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ - Labels: labels, Name: name, Namespace: namespace, }, @@ -196,7 +195,7 @@ func createNewService(name, namespace string, labels map[string]string, serviceT }}, }, } - logr.Logger{}.Info("creating service", "name", svc.Name, "namespace", svc.Namespace, "labels", svc.Labels) + GinkgoLogr.Info("creating service", "name", svc.Name, "namespace", svc.Namespace, "labels", svc.Labels) Expect(k8sClient.Create(ctx, svc)).ShouldNot(HaveOccurred()) } From fe2b7edb5e0b78ab85fd4bc5e6bdcbd5788d05ca Mon Sep 17 00:00:00 2001 From: Lukas Hoehl Date: Tue, 2 Jun 2026 11:42:16 +0200 Subject: [PATCH 25/25] rebase Signed-off-by: Lukas Hoehl --- go.sum | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 9 deletions(-) diff --git a/go.sum b/go.sum index 59b945ca..6064ca92 100644 --- a/go.sum +++ b/go.sum @@ -637,13 +637,37 @@ go.yaml.in/yaml/v4 v4.0.0-rc.2/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfP 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.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= -golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= +golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= +golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= +golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= +golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= +golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc= +golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988= +golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc= +golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 h1:jiDhWWeC7jfWqR9c/uplMOqJ0sbNlNWv0UkzE0vX1MA= golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90/go.mod h1:xE1HEv6b+1SCZ5/uscMRjUBKtIxworgEcEi+/n9NQDQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -781,8 +805,40 @@ golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= -golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= +golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= +golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= +golang.org/x/telemetry v0.0.0-20250710130107-8d8967aff50b/go.mod h1:4ZwOYna0/zsOKwuR5X/m0QFOJpSZvAxFfkQT+Erd9D4= +golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488/go.mod h1:fGb/2+tgXXjhjHsTNdVEEMZNWA0quBnfrO+AfoDSAKw= +golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053/go.mod h1:+nZKN+XVh4LCiA9DV3ywrzN4gumyCnKjau3NGb9SGoE= +golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE= golang.org/x/telemetry v0.0.0-20260508192327-42602be52be6 h1:HjU6IWBiAgRIdAJ9/y1rwCn+UELEmwV+VsTLzj/W4sE= golang.org/x/telemetry v0.0.0-20260508192327-42602be52be6/go.mod h1:Eqhaxk/wZsWEH8CRxLwj6xzEJbz7k1EFGqx7nyCoabE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=