From 00313c89b646033a730b730e43f3611ae2ba27a7 Mon Sep 17 00:00:00 2001 From: Anupama Bhat Date: Mon, 24 Aug 2026 10:57:02 +0200 Subject: [PATCH 1/4] chore(deps): update k8s.io/* to v0.36.3 --- docs/stack_crd.yaml | 106 ++++++------ docs/stackset_crd.yaml | 104 ++++++------ go.mod | 70 ++++---- go.sum | 156 +++++++++--------- hack/update-codegen.sh | 1 - .../versioned/fake/clientset_generated.go | 19 ++- .../informers/externalversions/factory.go | 113 ++++++++++--- .../internalinterfaces/factory_interfaces.go | 19 +++ .../zalando.org/v1/platformcredentialsset.go | 52 +++--- .../externalversions/zalando.org/v1/stack.go | 52 +++--- .../zalando.org/v1/stackset.go | 52 +++--- 11 files changed, 428 insertions(+), 316 deletions(-) diff --git a/docs/stack_crd.yaml b/docs/stack_crd.yaml index 1a5e7770..30cb9c12 100644 --- a/docs/stack_crd.yaml +++ b/docs/stack_crd.yaml @@ -1998,12 +1998,6 @@ spec: Must be set if and only if type is "Localhost". type: string type: - description: |- - type indicates which kind of AppArmor profile will be applied. - Valid options are: - Localhost - a profile pre-loaded on the node. - RuntimeDefault - the container runtime's default profile. - Unconfined - no AppArmor enforcement. type: string required: - type @@ -2039,7 +2033,6 @@ spec: procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. type: string readOnlyRootFilesystem: @@ -3345,12 +3338,6 @@ spec: Must be set if and only if type is "Localhost". type: string type: - description: |- - type indicates which kind of AppArmor profile will be applied. - Valid options are: - Localhost - a profile pre-loaded on the node. - RuntimeDefault - the container runtime's default profile. - Unconfined - no AppArmor enforcement. type: string required: - type @@ -3386,7 +3373,6 @@ spec: procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. type: string readOnlyRootFilesystem: @@ -3836,7 +3822,6 @@ spec: When set to false, a new userns is created for the pod. Setting false is useful for mitigating container breakout vulnerabilities even allowing users to run their containers as root without actually having root privileges on the host. - This field is alpha-level and is only honored by servers that enable the UserNamespacesSupport feature. type: boolean hostname: description: |- @@ -4768,11 +4753,6 @@ spec: Note that this field cannot be set when spec.os.name is windows. properties: localhostProfile: - description: |- - localhostProfile indicates a profile loaded on the node that should be used. - The profile must be preconfigured on the node to work. - Must match the loaded name of the profile. - Must be set if and only if type is "Localhost". type: string type: type: string @@ -4810,7 +4790,6 @@ spec: procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. type: string readOnlyRootFilesystem: @@ -5345,6 +5324,14 @@ spec: It adds a name to it that uniquely identifies the ResourceClaim inside the Pod. Containers that need access to the ResourceClaim reference it with this name. + + When the DRAWorkloadResourceClaims feature gate is enabled and this Pod + belongs to a PodGroup, a PodResourceClaim is matched to a + PodGroupResourceClaim if all of their fields are equal (Name, + ResourceClaimName, and ResourceClaimTemplateName). A matched claim references + a single ResourceClaim shared across all Pods in the PodGroup, reserved for + the PodGroup in ResourceClaimStatus.ReservedFor rather than for individual + Pods. properties: name: description: |- @@ -5370,6 +5357,16 @@ spec: generated component, will be used to form a unique name for the ResourceClaim, which will be recorded in pod.status.resourceClaimStatuses. + When the DRAWorkloadResourceClaims feature gate is enabled and the pod + belongs to a PodGroup that defines a PodGroupResourceClaim with the same + Name and ResourceClaimTemplateName, this PodResourceClaim resolves to the + ResourceClaim generated for the PodGroup. All pods in the group that + define an equivalent PodResourceClaim matching the + PodGroupResourceClaim's Name and ResourceClaimTemplateName share the same + generated ResourceClaim. ResourceClaims generated for a PodGroup are + owned by the PodGroup and their lifecycles are tied to the PodGroup + instead of any individual pod. + This field is immutable and no changes will be made to the corresponding ResourceClaim by the control plane after creating the ResourceClaim. @@ -5495,6 +5492,28 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map + schedulingGroup: + description: |- + SchedulingGroup provides a reference to the immediate scheduling runtime + grouping object that this Pod belongs to. + This field is used by the scheduler to identify the group and apply the + correct group scheduling policies. The association with a group also + impacts other lifecycle aspects of a Pod that are relevant in a wider context + of scheduling like preemption, resource attachment, etc. If not specified, + the Pod is treated as a single unit in all of these aspects. + The group object referenced by this field may not exist at the time the + Pod is created. + This field is immutable, but a group object with the same name may be + recreated with different policies. Doing this during pod scheduling + may result in the placement not conforming to the expected policies. + properties: + podGroupName: + description: |- + PodGroupName specifies the name of the standalone PodGroup object + that represents the runtime instance of this group. + Must be a DNS subdomain. + type: string + type: object securityContext: description: |- SecurityContext holds pod-level security attributes and common container settings. @@ -6752,7 +6771,7 @@ spec: A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. - The volume will be mounted read-only (ro) and non-executable files (noexec). + The volume will be mounted read-only (ro). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type. properties: @@ -6918,8 +6937,7 @@ spec: description: |- portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type - are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate - is on. + are redirected to the pxd.portworx.com CSI driver. properties: fsType: description: |- @@ -7431,42 +7449,6 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map - workloadRef: - description: |- - WorkloadRef provides a reference to the Workload object that this Pod belongs to. - This field is used by the scheduler to identify the PodGroup and apply the - correct group scheduling policies. The Workload object referenced - by this field may not exist at the time the Pod is created. - This field is immutable, but a Workload object with the same name - may be recreated with different policies. Doing this during pod scheduling - may result in the placement not conforming to the expected policies. - properties: - name: - description: |- - Name defines the name of the Workload object this Pod belongs to. - Workload must be in the same namespace as the Pod. - If it doesn't match any existing Workload, the Pod will remain unschedulable - until a Workload object is created and observed by the kube-scheduler. - It must be a DNS subdomain. - type: string - podGroup: - description: |- - PodGroup is the name of the PodGroup within the Workload that this Pod - belongs to. If it doesn't match any existing PodGroup within the Workload, - the Pod will remain unschedulable until the Workload object is recreated - and observed by the kube-scheduler. It must be a DNS label. - type: string - podGroupReplicaKey: - description: |- - PodGroupReplicaKey specifies the replica key of the PodGroup to which this - Pod belongs. It is used to distinguish pods belonging to different replicas - of the same pod group. The pod group policy is applied separately to each replica. - When set, it must be a DNS label. - type: string - required: - - name - - podGroup - type: object required: - containers type: object @@ -7497,11 +7479,15 @@ spec: `random` - backend is chosen at random. `consistentHash` - backend is chosen by [consistent hashing](https://en.wikipedia.org/wiki/Consistent_hashing) algorithm based on the request key. The request key is derived from `X-Forwarded-For` header or request remote IP address as the fallback. Use [`consistentHashKey`](filters.md#consistenthashkey) filter to set the request key. Use [`consistentHashBalanceFactor`](filters.md#consistenthashbalancefactor) to prevent popular keys from overloading a single backend endpoint. `powerOfRandomNChoices` - backend is chosen by selecting N random endpoints and picking the one with least outstanding requests from them (see http://www.eecs.harvard.edu/~michaelm/postscripts/handbook2001.pdf). + `weightedRoundRobin` - backend is chosen by smooth weighted round robin with dynamic weights based on the ratio of successful round trips per endpoint, weights are updated by the passive health check when enabled. + `leastRequests` - backend is chosen as the endpoint with the lowest load factor, defined as inflight requests divided by endpoint weight. Ties are broken by smooth weighted round-robin over the tied set proportional to endpoint weights. With equal weights and no inflight requests it behaves like roundRobin. enum: - roundRobin - random - consistentHash - powerOfRandomNChoices + - weightedRoundRobin + - leastRequests type: string endpoints: description: Endpoints is required for type `lb` diff --git a/docs/stackset_crd.yaml b/docs/stackset_crd.yaml index c8b3bd32..994788b3 100644 --- a/docs/stackset_crd.yaml +++ b/docs/stackset_crd.yaml @@ -139,11 +139,15 @@ spec: `random` - backend is chosen at random. `consistentHash` - backend is chosen by [consistent hashing](https://en.wikipedia.org/wiki/Consistent_hashing) algorithm based on the request key. The request key is derived from `X-Forwarded-For` header or request remote IP address as the fallback. Use [`consistentHashKey`](filters.md#consistenthashkey) filter to set the request key. Use [`consistentHashBalanceFactor`](filters.md#consistenthashbalancefactor) to prevent popular keys from overloading a single backend endpoint. `powerOfRandomNChoices` - backend is chosen by selecting N random endpoints and picking the one with least outstanding requests from them (see http://www.eecs.harvard.edu/~michaelm/postscripts/handbook2001.pdf). + `weightedRoundRobin` - backend is chosen by smooth weighted round robin with dynamic weights based on the ratio of successful round trips per endpoint, weights are updated by the passive health check when enabled. + `leastRequests` - backend is chosen as the endpoint with the lowest load factor, defined as inflight requests divided by endpoint weight. Ties are broken by smooth weighted round-robin over the tied set proportional to endpoint weights. With equal weights and no inflight requests it behaves like roundRobin. enum: - roundRobin - random - consistentHash - powerOfRandomNChoices + - weightedRoundRobin + - leastRequests type: string endpoints: description: Endpoints is required for type `lb` @@ -1729,11 +1733,6 @@ spec: type: integer service: default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. type: string required: - port @@ -2250,7 +2249,6 @@ spec: procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. type: string readOnlyRootFilesystem: @@ -3597,7 +3595,6 @@ spec: procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. type: string readOnlyRootFilesystem: @@ -3727,11 +3724,6 @@ spec: type: integer service: default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. type: string required: - port @@ -4053,7 +4045,6 @@ spec: When set to false, a new userns is created for the pod. Setting false is useful for mitigating container breakout vulnerabilities even allowing users to run their containers as root without actually having root privileges on the host. - This field is alpha-level and is only honored by servers that enable the UserNamespacesSupport feature. type: boolean hostname: description: |- @@ -4508,11 +4499,6 @@ spec: type: integer service: default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. type: string required: - port @@ -5029,7 +5015,6 @@ spec: procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. type: string readOnlyRootFilesystem: @@ -5570,6 +5555,14 @@ spec: It adds a name to it that uniquely identifies the ResourceClaim inside the Pod. Containers that need access to the ResourceClaim reference it with this name. + + When the DRAWorkloadResourceClaims feature gate is enabled and this Pod + belongs to a PodGroup, a PodResourceClaim is matched to a + PodGroupResourceClaim if all of their fields are equal (Name, + ResourceClaimName, and ResourceClaimTemplateName). A matched claim references + a single ResourceClaim shared across all Pods in the PodGroup, reserved for + the PodGroup in ResourceClaimStatus.ReservedFor rather than for individual + Pods. properties: name: description: |- @@ -5595,6 +5588,16 @@ spec: generated component, will be used to form a unique name for the ResourceClaim, which will be recorded in pod.status.resourceClaimStatuses. + When the DRAWorkloadResourceClaims feature gate is enabled and the pod + belongs to a PodGroup that defines a PodGroupResourceClaim with the same + Name and ResourceClaimTemplateName, this PodResourceClaim resolves to the + ResourceClaim generated for the PodGroup. All pods in the group that + define an equivalent PodResourceClaim matching the + PodGroupResourceClaim's Name and ResourceClaimTemplateName share the same + generated ResourceClaim. ResourceClaims generated for a PodGroup are + owned by the PodGroup and their lifecycles are tied to the PodGroup + instead of any individual pod. + This field is immutable and no changes will be made to the corresponding ResourceClaim by the control plane after creating the ResourceClaim. @@ -5721,6 +5724,28 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map + schedulingGroup: + description: |- + SchedulingGroup provides a reference to the immediate scheduling runtime + grouping object that this Pod belongs to. + This field is used by the scheduler to identify the group and apply the + correct group scheduling policies. The association with a group also + impacts other lifecycle aspects of a Pod that are relevant in a wider context + of scheduling like preemption, resource attachment, etc. If not specified, + the Pod is treated as a single unit in all of these aspects. + The group object referenced by this field may not exist at the time the + Pod is created. + This field is immutable, but a group object with the same name may be + recreated with different policies. Doing this during pod scheduling + may result in the placement not conforming to the expected policies. + properties: + podGroupName: + description: |- + PodGroupName specifies the name of the standalone PodGroup object + that represents the runtime instance of this group. + Must be a DNS subdomain. + type: string + type: object securityContext: description: |- SecurityContext holds pod-level security attributes and common container settings. @@ -6985,7 +7010,7 @@ spec: A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. - The volume will be mounted read-only (ro) and non-executable files (noexec). + The volume will be mounted read-only (ro). Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath) before 1.33. The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type. properties: @@ -7153,8 +7178,7 @@ spec: description: |- portworxVolume represents a portworx volume attached and mounted on kubelets host machine. Deprecated: PortworxVolume is deprecated. All operations for the in-tree portworxVolume type - are redirected to the pxd.portworx.com CSI driver when the CSIMigrationPortworx feature-gate - is on. + are redirected to the pxd.portworx.com CSI driver. properties: fsType: description: |- @@ -7671,42 +7695,6 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map - workloadRef: - description: |- - WorkloadRef provides a reference to the Workload object that this Pod belongs to. - This field is used by the scheduler to identify the PodGroup and apply the - correct group scheduling policies. The Workload object referenced - by this field may not exist at the time the Pod is created. - This field is immutable, but a Workload object with the same name - may be recreated with different policies. Doing this during pod scheduling - may result in the placement not conforming to the expected policies. - properties: - name: - description: |- - Name defines the name of the Workload object this Pod belongs to. - Workload must be in the same namespace as the Pod. - If it doesn't match any existing Workload, the Pod will remain unschedulable - until a Workload object is created and observed by the kube-scheduler. - It must be a DNS subdomain. - type: string - podGroup: - description: |- - PodGroup is the name of the PodGroup within the Workload that this Pod - belongs to. If it doesn't match any existing PodGroup within the Workload, - the Pod will remain unschedulable until the Workload object is recreated - and observed by the kube-scheduler. It must be a DNS label. - type: string - podGroupReplicaKey: - description: |- - PodGroupReplicaKey specifies the replica key of the PodGroup to which this - Pod belongs. It is used to distinguish pods belonging to different replicas - of the same pod group. The pod group policy is applied separately to each replica. - When set, it must be a DNS label. - type: string - required: - - name - - podGroup - type: object required: - containers type: object diff --git a/go.mod b/go.mod index c7872389..72f41c5a 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/zalando-incubator/stackset-controller -go 1.26.1 +go 1.26.5 require ( github.com/alecthomas/kingpin v2.2.6+incompatible @@ -8,13 +8,13 @@ require ( github.com/google/go-cmp v0.7.0 github.com/heptiolabs/healthcheck v0.0.0-20211123025425-613501dd5deb github.com/prometheus/client_golang v1.24.1 - github.com/sirupsen/logrus v1.10.0 - github.com/stretchr/testify v1.12.0 - github.com/szuecs/routegroup-client v0.34.1 + github.com/sirupsen/logrus v1.10.1 + github.com/stretchr/testify v1.12.1 + github.com/szuecs/routegroup-client v0.36.3 golang.org/x/sync v0.22.0 - k8s.io/api v0.35.7 - k8s.io/apimachinery v0.35.7 - k8s.io/client-go v0.35.7 + k8s.io/api v0.36.4 + k8s.io/apimachinery v0.36.4 + k8s.io/client-go v0.36.4 sigs.k8s.io/yaml v1.6.0 ) @@ -26,22 +26,22 @@ require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.13.0 // indirect github.com/fatih/color v1.18.0 // indirect - github.com/fxamacker/cbor/v2 v2.9.0 // indirect - github.com/go-logr/logr v1.4.3 // indirect - github.com/go-openapi/jsonpointer v0.22.5 // indirect - github.com/go-openapi/jsonreference v0.21.5 // indirect - github.com/go-openapi/swag v0.25.5 // indirect - github.com/go-openapi/swag/cmdutils v0.25.5 // indirect - github.com/go-openapi/swag/conv v0.25.5 // indirect - github.com/go-openapi/swag/fileutils v0.25.5 // indirect - github.com/go-openapi/swag/jsonname v0.25.5 // indirect - github.com/go-openapi/swag/jsonutils v0.25.5 // indirect - github.com/go-openapi/swag/loading v0.25.5 // indirect - github.com/go-openapi/swag/mangling v0.25.5 // indirect - github.com/go-openapi/swag/netutils v0.25.5 // indirect - github.com/go-openapi/swag/stringutils v0.25.5 // indirect - github.com/go-openapi/swag/typeutils v0.25.5 // indirect - github.com/go-openapi/swag/yamlutils v0.25.5 // indirect + github.com/fxamacker/cbor/v2 v2.9.3 // indirect + github.com/go-logr/logr v1.4.4 // indirect + github.com/go-openapi/jsonpointer v1.0.0 // indirect + github.com/go-openapi/jsonreference v1.0.0 // indirect + github.com/go-openapi/swag v0.29.1 // indirect + github.com/go-openapi/swag/cmdutils v0.29.1 // indirect + github.com/go-openapi/swag/conv v0.29.1 // indirect + github.com/go-openapi/swag/fileutils v0.29.1 // indirect + github.com/go-openapi/swag/jsonutils v0.29.1 // indirect + github.com/go-openapi/swag/loading v0.29.1 // indirect + github.com/go-openapi/swag/mangling v0.29.1 // indirect + github.com/go-openapi/swag/netutils v0.29.1 // indirect + github.com/go-openapi/swag/pools v0.29.1 // indirect + github.com/go-openapi/swag/stringutils v0.29.1 // indirect + github.com/go-openapi/swag/typeutils v0.29.1 // indirect + github.com/go-openapi/swag/yamlutils v0.29.1 // indirect github.com/gobuffalo/flect v1.0.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/gnostic-models v0.7.1 // indirect @@ -59,35 +59,35 @@ require ( github.com/prometheus/common v0.70.1 // indirect github.com/prometheus/procfs v0.21.1 // indirect github.com/spf13/cobra v1.9.1 // indirect - github.com/spf13/pflag v1.0.9 // indirect + github.com/spf13/pflag v1.0.10 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xhit/go-str2duration/v2 v2.1.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect - go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/mod v0.37.0 // indirect - golang.org/x/net v0.57.0 // indirect + go.yaml.in/yaml/v3 v3.0.5 // indirect + golang.org/x/mod v0.40.0 // indirect + golang.org/x/net v0.58.0 // indirect golang.org/x/oauth2 v0.36.0 // indirect golang.org/x/sys v0.47.0 // indirect golang.org/x/term v0.45.0 // indirect - golang.org/x/text v0.40.0 // indirect + golang.org/x/text v0.41.0 // indirect golang.org/x/time v0.15.0 // indirect - golang.org/x/tools v0.47.0 // indirect - google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // indirect + golang.org/x/tools v0.49.0 // indirect + google.golang.org/protobuf v1.36.12 // indirect gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0 // indirect gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiextensions-apiserver v0.34.0 // indirect - k8s.io/code-generator v0.34.1 // indirect - k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f // indirect + k8s.io/code-generator v0.36.3 // indirect + k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b // indirect k8s.io/klog/v2 v2.140.0 // indirect - k8s.io/kube-openapi v0.0.0-20260319004828-5883c5ee87b9 // indirect - k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 // indirect + k8s.io/kube-openapi v0.0.0-20260821135717-be32def86098 // indirect + k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3 // indirect sigs.k8s.io/controller-tools v0.19.0 // indirect sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect sigs.k8s.io/randfill v1.0.0 // indirect - sigs.k8s.io/structured-merge-diff/v6 v6.3.2 // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.4.2 // indirect ) tool ( diff --git a/go.sum b/go.sum index 1a4fd65a..092367c7 100644 --- a/go.sum +++ b/go.sum @@ -32,46 +32,46 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= -github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= -github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= -github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/fxamacker/cbor/v2 v2.9.3 h1:oQBnFATpNdY8gJHTndDDv5Xl4QqNaz51G5LLEPhng3Q= +github.com/fxamacker/cbor/v2 v2.9.3/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= +github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8= +github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-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.21.5 h1:6uCGVXU/aNF13AQNggxfysJ+5ZcU4nEAe+pJyVWRdiE= -github.com/go-openapi/jsonreference v0.21.5/go.mod h1:u25Bw85sX4E2jzFodh1FOKMTZLcfifd1Q+iKKOUxExw= -github.com/go-openapi/swag v0.25.5 h1:pNkwbUEeGwMtcgxDr+2GBPAk4kT+kJ+AaB+TMKAg+TU= -github.com/go-openapi/swag v0.25.5/go.mod h1:B3RT6l8q7X803JRxa2e59tHOiZlX1t8viplOcs9CwTA= -github.com/go-openapi/swag/cmdutils v0.25.5 h1:yh5hHrpgsw4NwM9KAEtaDTXILYzdXh/I8Whhx9hKj7c= -github.com/go-openapi/swag/cmdutils v0.25.5/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0= -github.com/go-openapi/swag/conv v0.25.5 h1:wAXBYEXJjoKwE5+vc9YHhpQOFj2JYBMF2DUi+tGu97g= -github.com/go-openapi/swag/conv v0.25.5/go.mod h1:CuJ1eWvh1c4ORKx7unQnFGyvBbNlRKbnRyAvDvzWA4k= -github.com/go-openapi/swag/fileutils v0.25.5 h1:B6JTdOcs2c0dBIs9HnkyTW+5gC+8NIhVBUwERkFhMWk= -github.com/go-openapi/swag/fileutils v0.25.5/go.mod h1:V3cT9UdMQIaH4WiTrUc9EPtVA4txS0TOmRURmhGF4kc= -github.com/go-openapi/swag/jsonname v0.25.5 h1:8p150i44rv/Drip4vWI3kGi9+4W9TdI3US3uUYSFhSo= -github.com/go-openapi/swag/jsonname v0.25.5/go.mod h1:jNqqikyiAK56uS7n8sLkdaNY/uq6+D2m2LANat09pKU= -github.com/go-openapi/swag/jsonutils v0.25.5 h1:XUZF8awQr75MXeC+/iaw5usY/iM7nXPDwdG3Jbl9vYo= -github.com/go-openapi/swag/jsonutils v0.25.5/go.mod h1:48FXUaz8YsDAA9s5AnaUvAmry1UcLcNVWUjY42XkrN4= -github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.5 h1:SX6sE4FrGb4sEnnxbFL/25yZBb5Hcg1inLeErd86Y1U= -github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.5/go.mod h1:/2KvOTrKWjVA5Xli3DZWdMCZDzz3uV/T7bXwrKWPquo= -github.com/go-openapi/swag/loading v0.25.5 h1:odQ/umlIZ1ZVRteI6ckSrvP6e2w9UTF5qgNdemJHjuU= -github.com/go-openapi/swag/loading v0.25.5/go.mod h1:I8A8RaaQ4DApxhPSWLNYWh9NvmX2YKMoB9nwvv6oW6g= -github.com/go-openapi/swag/mangling v0.25.5 h1:hyrnvbQRS7vKePQPHHDso+k6CGn5ZBs5232UqWZmJZw= -github.com/go-openapi/swag/mangling v0.25.5/go.mod h1:6hadXM/o312N/h98RwByLg088U61TPGiltQn71Iw0NY= -github.com/go-openapi/swag/netutils v0.25.5 h1:LZq2Xc2QI8+7838elRAaPCeqJnHODfSyOa7ZGfxDKlU= -github.com/go-openapi/swag/netutils v0.25.5/go.mod h1:lHbtmj4m57APG/8H7ZcMMSWzNqIQcu0RFiXrPUara14= -github.com/go-openapi/swag/stringutils v0.25.5 h1:NVkoDOA8YBgtAR/zvCx5rhJKtZF3IzXcDdwOsYzrB6M= -github.com/go-openapi/swag/stringutils v0.25.5/go.mod h1:PKK8EZdu4QJq8iezt17HM8RXnLAzY7gW0O1KKarrZII= -github.com/go-openapi/swag/typeutils v0.25.5 h1:EFJ+PCga2HfHGdo8s8VJXEVbeXRCYwzzr9u4rJk7L7E= -github.com/go-openapi/swag/typeutils v0.25.5/go.mod h1:itmFmScAYE1bSD8C4rS0W+0InZUBrB2xSPbWt6DLGuc= -github.com/go-openapi/swag/yamlutils v0.25.5 h1:kASCIS+oIeoc55j28T4o8KwlV2S4ZLPT6G0iq2SSbVQ= -github.com/go-openapi/swag/yamlutils v0.25.5/go.mod h1:Gek1/SjjfbYvM+Iq4QGwa/2lEXde9n2j4a3wI3pNuOQ= -github.com/go-openapi/testify/enable/yaml/v2 v2.4.0 h1:7SgOMTvJkM8yWrQlU8Jm18VeDPuAvB/xWrdxFJkoFag= -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-openapi/jsonpointer v1.0.0 h1:kR9tHqY0CtZaOPVFm622dPVNhrvYpwr4uCxgL3h1H8s= +github.com/go-openapi/jsonpointer v1.0.0/go.mod h1:Z3rw7dWu1p9IgitXCFamSlA5lmDiklEB6vkaxcNZW5Y= +github.com/go-openapi/jsonreference v1.0.0 h1:jlmTr6torcd1YgDQvSfNmRtKzYDO4FGBkrAdlAVWnpY= +github.com/go-openapi/jsonreference v1.0.0/go.mod h1:jtwdyGbJk0Xhe5Y+rwtglQP6Sb1WZST4rT32LWB+sv0= +github.com/go-openapi/swag v0.29.1 h1:C6EeWzUwQtcWEhE9eqBdUubGXxhWY4PlzHMLD7kLaiQ= +github.com/go-openapi/swag v0.29.1/go.mod h1:BzxEXKiPlSXRsRTv1KSBF/BpGKHxA/YciCnr4tv9bvA= +github.com/go-openapi/swag/cmdutils v0.29.1 h1:3DorPGfUdE80BogKY22EzoHBcHMrkVomZMoV7kS4ANY= +github.com/go-openapi/swag/cmdutils v0.29.1/go.mod h1:Sm1MVFMkF6guJJ+pQqHnQA3N0j9qALV3NxzDSv6bETM= +github.com/go-openapi/swag/conv v0.29.1 h1:AC4Eh/5c/eUDOUCzzsRC9ghmFgOSBHeRMGIngY0ZUGA= +github.com/go-openapi/swag/conv v0.29.1/go.mod h1:S1X7/ZrBEZOC0Wc8AGxjbcGS92l3WEjA7aPtpl+RaqM= +github.com/go-openapi/swag/fileutils v0.29.1 h1:ZcPzMceVhU1WPbK6N1G6sNQKdd1CWJlf3cA08UHuoM0= +github.com/go-openapi/swag/fileutils v0.29.1/go.mod h1:/wofKYckbtRl2p3+EwQsosie5CT1B38+dQ+PS579BzI= +github.com/go-openapi/swag/jsonutils v0.29.1 h1:AFCxs0eQZ24/QyfhVHM2t49rMz7Vv3XCsZQI6yrNy+c= +github.com/go-openapi/swag/jsonutils v0.29.1/go.mod h1:u3+sCfJpttDpcmS5kpm0yxL6GK0eWgODsx8Yw8fcqNM= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.29.1 h1:BiiXE31Bx9SfpsMmOQj5KYpUhTZBpLVriVhJDuLuY2o= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.29.1/go.mod h1:julgTUKZ9/D0j6O7GKajmRs+812FWxQg/mMpGunWSjg= +github.com/go-openapi/swag/loading v0.29.1 h1:FCv5fG8UhTdDJa2R7w+5O9Ekpcbw7tt0nFWvmDKGBjc= +github.com/go-openapi/swag/loading v0.29.1/go.mod h1:N0ESuem4p2oedKal8EJhciqnJ9Q9Wmt83L1CRB3Fouw= +github.com/go-openapi/swag/mangling v0.29.1 h1:lHALtvYCdxVnRl4GrHmFPwfBTZYIObqdGNSKyu/8D6I= +github.com/go-openapi/swag/mangling v0.29.1/go.mod h1:SAop9pB7PUjQ/CGCNf/JmCKTRK+GDO+RqE9UHqC/N6s= +github.com/go-openapi/swag/netutils v0.29.1 h1:IjIvdEP5duKcghFqJEPSUraRnkKYHoM65kTluTu+Jb4= +github.com/go-openapi/swag/netutils v0.29.1/go.mod h1:DUde7x4Bx00k5jYl2AdRpNAO0m7atUvD2x6X+bWkbno= +github.com/go-openapi/swag/pools v0.29.1 h1:NRogYxdEW9SjRM4mkAOji9iefO4MRXq3p/ZJcoQbUKg= +github.com/go-openapi/swag/pools v0.29.1/go.mod h1:leDcaghjkRAhCuCRv9NfJU5f0mjoU3cT/XZObhMk3pc= +github.com/go-openapi/swag/stringutils v0.29.1 h1:1ykunK7iJQk1uOO7+oUH1ukbsK85fFCOiCFMOVSY+F0= +github.com/go-openapi/swag/stringutils v0.29.1/go.mod h1:7fSqZ+z8Qc0tOfAAK0jVa5qFGrnIlRi6n7NeGGrr1vc= +github.com/go-openapi/swag/typeutils v0.29.1 h1:Nzv9nhnlLCRBPQqfOX+7lB6Guju370or8StT+lIOf6M= +github.com/go-openapi/swag/typeutils v0.29.1/go.mod h1:hxpgDZJVBkBsi/d3MIUosafoFdE5exaQRmVp0zwu3YE= +github.com/go-openapi/swag/yamlutils v0.29.1 h1:69w3tsBajm7MR/fejLy7HD/3J68Ys1SeeZMEzZ3w2sk= +github.com/go-openapi/swag/yamlutils v0.29.1/go.mod h1:rgsp3vT/QdWzKwn43CigDwjOGIenPyTZMKnxEM8jZOA= +github.com/go-openapi/testify/enable/yaml/v2 v2.6.1 h1:Jm+/ze2rMtbD98yen92AhATGLGREDYXG56Xr4gMjEtE= +github.com/go-openapi/testify/enable/yaml/v2 v2.6.1/go.mod h1:YDPnwCRDu38/oJBVMBVXOUDiJ9cIeBHWvfImHaXqnv4= +github.com/go-openapi/testify/v2 v2.6.1 h1:6CNJhTjMzgaeaH8WhshcsZNPIvRemiOcFpU7seO/y7Q= +github.com/go-openapi/testify/v2 v2.6.1/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw= github.com/gobuffalo/flect v1.0.3 h1:xeWBM2nui+qnVvNM4S3foBhCAL2XgPU+a7FdpelbTq4= github.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -120,8 +120,8 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= 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/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= -github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= +github.com/onsi/gomega v1.38.1 h1:FaLA8GlcpXDwsb7m0h2A9ew2aTk3vnZMlzFgg5tz/pk= +github.com/onsi/gomega v1.38.1/go.mod h1:LfcV8wZLvwcYRwPiJysphKAEsmcFnLMK/9c+PjvlX8g= 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= @@ -136,13 +136,13 @@ github.com/prometheus/procfs v0.21.1/go.mod h1:aB55Cww9pdSJVHk0hUf0inxWyyjPogFIj 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= -github.com/sirupsen/logrus v1.10.0 h1:T8MxJJXVZkfcC5zSRMRAg2F8+lxjmUCGGWPzFxO+Msc= -github.com/sirupsen/logrus v1.10.0/go.mod h1:FXZFonkDAnFozmO+5hGAFvB0Yg9/j2SIhA/QuIkP180= +github.com/sirupsen/logrus v1.10.1 h1:xi4336Zh11WpU14fXR6I67V3yaTPQYwRx2WEtHbRg4Q= +github.com/sirupsen/logrus v1.10.1/go.mod h1:vsQHnG7xzNsxk3NrwboUiWPnIC3dmbjcGPykD7+tiHk= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= -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/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -157,10 +157,10 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO 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.12.0 h1:K6Mr6jO9JICuend/5xzTM03ydSV3vdNRYAdPSukj8uI= -github.com/stretchr/testify v1.12.0/go.mod h1:bOYBZb5qJ00vPzWfIqBUZPaxK8jWiXc6d3ErP4Ca9Gw= -github.com/szuecs/routegroup-client v0.34.1 h1:8+Nqx/ti6c6rHEOs5U/8rocaNZ6gaJMkMxMQgLcVsek= -github.com/szuecs/routegroup-client v0.34.1/go.mod h1:eG9zOJaLqNdswNJ8R6jSSL2WrFIxIBtAp3FBsvYF60A= +github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE= +github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg= +github.com/szuecs/routegroup-client v0.36.3 h1:pmONEAAEMjSbm2TbyLbG112xxxs1fXEogllVdtYSXr8= +github.com/szuecs/routegroup-client v0.36.3/go.mod h1:md0pEJwoAHPynVlvqORzaINjI22CBymIVipqWVK0h/M= 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/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= @@ -189,8 +189,8 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 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.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= -go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= +go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= 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= @@ -198,14 +198,14 @@ golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= 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.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ= -golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0= +golang.org/x/mod v0.40.0 h1:hUv+3cXcdRHz08UmSiOob7sadHig73uo5bkXxQ/tvUs= +golang.org/x/mod v0.40.0/go.mod h1:0/weTWkPWGBikyTWAX3dkjVztMmBA5hM0DH6BElSupE= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE= -golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU= +golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To= +golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU= 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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -224,18 +224,18 @@ golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0= golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs= -golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY= +golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8= +golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M= 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-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q= -golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA= -golang.org/x/tools/go/expect v0.1.0-deprecated h1:jY2C5HGYR5lqex3gEniOQL0r7Dq5+VGVgY1nudX5lXY= -golang.org/x/tools/go/expect v0.1.0-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= +golang.org/x/tools v0.49.0 h1:3NI7VXzL9+1WZD52Dx2ttoPwD5DWrFGpl9mFZDlmisI= +golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo= +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= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -248,8 +248,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= -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= +google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc= +google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0 h1:FVCohIoYO7IJoDDVpV2pdq7SgrMH6wHnuTyrdrxJNoY= gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0/go.mod h1:OdE7CF6DbADk7lN8LIKRzRJTTZXIjtWgA5THM5lhBAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -266,28 +266,28 @@ 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= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.35.7 h1:qzjBIl6HRlZ4TXvVELrWC50d30RZu/uLJFE9efpLgxk= -k8s.io/api v0.35.7/go.mod h1:rXqZY94EWBj+9wVgdVOVS46MtnAEF09khzjCR4EOqiE= +k8s.io/api v0.36.4 h1:RxrvqCL6vgH5/+UnTeu1IIFqYmGfy0hnyrod1rn35Oo= +k8s.io/api v0.36.4/go.mod h1:S2B3orCFBDhrgyWbLeuKcT2QdHIpQesBkCYSlWtwUOw= k8s.io/apiextensions-apiserver v0.34.0 h1:B3hiB32jV7BcyKcMU5fDaDxk882YrJ1KU+ZSkA9Qxoc= k8s.io/apiextensions-apiserver v0.34.0/go.mod h1:hLI4GxE1BDBy9adJKxUxCEHBGZtGfIg98Q+JmTD7+g0= -k8s.io/apimachinery v0.35.7 h1:dIMi/gFnUDiASbeBqx1wqLAB8jlNo4kysncMZceV0OM= -k8s.io/apimachinery v0.35.7/go.mod h1:1I6w9iM6v//hXKgxe1g3ybZgcOaJrcYg9sQGtndFrmc= +k8s.io/apimachinery v0.36.4 h1:PT2UzkupGuAx/+xT5XjiMJ1WGpY3fn9/hdAvjweRet4= +k8s.io/apimachinery v0.36.4/go.mod h1:p2I2dipt7JHG+quVwQ1d02d28O4GdDi77RByQ13MTpk= k8s.io/apiserver v0.34.0 h1:Z51fw1iGMqN7uJ1kEaynf2Aec1Y774PqU+FVWCFV3Jg= k8s.io/apiserver v0.34.0/go.mod h1:52ti5YhxAvewmmpVRqlASvaqxt0gKJxvCeW7ZrwgazQ= -k8s.io/client-go v0.35.7 h1:UWxdVZcqqCdeip50BKoIcoGryX7WfTE1oQQVolP8HJs= -k8s.io/client-go v0.35.7/go.mod h1:uksk4ZVg/i4PrgsMsludkEe7Cp6v8hJ9wvje+2Ekn+c= -k8s.io/code-generator v0.34.1 h1:WpphT26E+j7tEgIUfFr5WfbJrktCGzB3JoJH9149xYc= -k8s.io/code-generator v0.34.1/go.mod h1:DeWjekbDnJWRwpw3s0Jat87c+e0TgkxoR4ar608yqvg= +k8s.io/client-go v0.36.4 h1:MDvfDNvMSt0Br94SK8neviVlwL9qifw9B26hJCpD1K0= +k8s.io/client-go v0.36.4/go.mod h1:pNK4WKELbwlEDvtbE8l22lEZL5THYF61H5EealokZmA= +k8s.io/code-generator v0.36.3 h1:tsiHI6NepXQncnexlTAf52w5VxZ4HYDU4ZqCNLFb9tA= +k8s.io/code-generator v0.36.3/go.mod h1:Unn13Mp8X+H803jgZi4f4ExxK11aj0llXcSsl++UTkE= k8s.io/component-base v0.34.0 h1:bS8Ua3zlJzapklsB1dZgjEJuJEeHjj8yTu1gxE2zQX8= k8s.io/component-base v0.34.0/go.mod h1:RSCqUdvIjjrEm81epPcjQ/DS+49fADvGSCkIP3IC6vg= -k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f h1:SLb+kxmzfA87x4E4brQzB33VBbT2+x7Zq9ROIHmGn9Q= -k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= +k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b h1:gMplByicHV/TJBizHd9aVEsTYoJBnnUAT5MHlTkbjhQ= +k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b/go.mod h1:CgujABENc3KuTrcsdpGmrrASjtQsWCT7R99mEV4U/fM= k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= -k8s.io/kube-openapi v0.0.0-20260319004828-5883c5ee87b9 h1:Sztf7ESG9tAXRW/ACJZjrj5jhdOUqS2KFRQT+CTvu78= -k8s.io/kube-openapi v0.0.0-20260319004828-5883c5ee87b9/go.mod h1:uGBT7iTA6c6MvqUvSXIaYZo9ukscABYi2btjhvgKGZ0= -k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 h1:kBawHLSnx/mYHmRnNUf9d4CpjREbeZuxoSGOX/J+aYM= -k8s.io/utils v0.0.0-20260319190234-28399d86e0b5/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= +k8s.io/kube-openapi v0.0.0-20260821135717-be32def86098 h1:z5+pcu1jTyKK5mNTe2/+x+U6Uuv9jRVOJQLaBJJMpeI= +k8s.io/kube-openapi v0.0.0-20260821135717-be32def86098/go.mod h1:0/mqHCVhlumdJ3BhCfnjSZQE037nAhNodh1/hK0T8/I= +k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3 h1:jVkFFVfXdXP74B/zbO3hM3hpSFD0xvhQ5U686DPurkE= +k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3/go.mod h1:M2s5JB1lIYP3jzZdorPLHXIPJzt9vv2muW5a6L9DtNM= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= sigs.k8s.io/controller-tools v0.19.0 h1:OU7jrPPiZusryu6YK0jYSjPqg8Vhf8cAzluP9XGI5uk= @@ -296,7 +296,7 @@ sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5E sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= 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/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/structured-merge-diff/v6 v6.4.2 h1:qdOxHwrl2Kaag1aQEarlYcOA9vSyGCp3CIki3aW8c4Q= +sigs.k8s.io/structured-merge-diff/v6 v6.4.2/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/hack/update-codegen.sh b/hack/update-codegen.sh index f534c28e..b4cabf9b 100755 --- a/hack/update-codegen.sh +++ b/hack/update-codegen.sh @@ -33,7 +33,6 @@ GROUPS_WITH_VERSIONS="${CUSTOM_RESOURCE_NAME}:${CUSTOM_RESOURCE_VERSION}" echo "Generating deepcopy funcs" go tool deepcopy-gen \ --output-file zz_generated.deepcopy.go \ - --bounding-dirs "${APIS_PKG}" \ --go-header-file "${SCRIPT_ROOT}/hack/boilerplate.go.txt" \ "${APIS_PKG}/${CUSTOM_RESOURCE_NAME}/${CUSTOM_RESOURCE_VERSION}" diff --git a/pkg/client/clientset/versioned/fake/clientset_generated.go b/pkg/client/clientset/versioned/fake/clientset_generated.go index f32a64df..e167e7c7 100644 --- a/pkg/client/clientset/versioned/fake/clientset_generated.go +++ b/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -34,10 +34,6 @@ import ( // It's backed by a very simple object tracker that processes creates, updates and deletions as-is, // without applying any field management, validations and/or defaults. It shouldn't be considered a replacement // for a real clientset and is mostly useful in simple unit tests. -// -// DEPRECATED: NewClientset replaces this with support for field management, which significantly improves -// server side apply testing. NewClientset is only available when apply configurations are generated (e.g. -// via --with-applyconfig). func NewSimpleClientset(objects ...runtime.Object) *Clientset { o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) for _, obj := range objects { @@ -51,8 +47,8 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { cs.AddReactor("*", "*", testing.ObjectReaction(o)) cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { var opts metav1.ListOptions - if watchActcion, ok := action.(testing.WatchActionImpl); ok { - opts = watchActcion.ListOptions + if watchAction, ok := action.(testing.WatchActionImpl); ok { + opts = watchAction.ListOptions } gvr := action.GetResource() ns := action.GetNamespace() @@ -83,6 +79,17 @@ func (c *Clientset) Tracker() testing.ObjectTracker { return c.tracker } +// IsWatchListSemanticsUnSupported informs the reflector that this client +// doesn't support WatchList semantics. +// +// This is a synthetic method whose sole purpose is to satisfy the optional +// interface check performed by the reflector. +// Returning true signals that WatchList can NOT be used. +// No additional logic is implemented here. +func (c *Clientset) IsWatchListSemanticsUnSupported() bool { + return true +} + var ( _ clientset.Interface = &Clientset{} _ testing.FakeClient = &Clientset{} diff --git a/pkg/client/informers/externalversions/factory.go b/pkg/client/informers/externalversions/factory.go index 5254aede..b14655f2 100644 --- a/pkg/client/informers/externalversions/factory.go +++ b/pkg/client/informers/externalversions/factory.go @@ -19,6 +19,7 @@ limitations under the License. package externalversions import ( + context "context" reflect "reflect" sync "sync" time "time" @@ -29,6 +30,7 @@ import ( v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" + wait "k8s.io/apimachinery/pkg/util/wait" cache "k8s.io/client-go/tools/cache" ) @@ -43,6 +45,7 @@ type sharedInformerFactory struct { defaultResync time.Duration customResync map[reflect.Type]time.Duration transform cache.TransformFunc + informerName *cache.InformerName informers map[reflect.Type]cache.SharedIndexInformer // startedInformers is used for tracking which informers have been started. @@ -89,6 +92,21 @@ func WithTransform(transform cache.TransformFunc) SharedInformerOption { } } +// WithInformerName sets the InformerName for informer identity used in metrics. +// The InformerName must be created via cache.NewInformerName() at startup, +// which validates global uniqueness. Each informer type will register its +// GVR under this name. +func WithInformerName(informerName *cache.InformerName) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.informerName = informerName + return factory + } +} + +func (f *sharedInformerFactory) InformerName() *cache.InformerName { + return f.informerName +} + // NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { return NewSharedInformerFactoryWithOptions(client, defaultResync) @@ -97,6 +115,7 @@ func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Dur // NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. // Listers obtained via this SharedInformerFactory will be subject to the same filters // as specified here. +// // Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) @@ -122,6 +141,10 @@ func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResy } func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { + f.StartWithContext(wait.ContextForChannel(stopCh)) +} + +func (f *sharedInformerFactory) StartWithContext(ctx context.Context) { f.lock.Lock() defer f.lock.Unlock() @@ -131,15 +154,9 @@ func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { for informerType, informer := range f.informers { if !f.startedInformers[informerType] { - f.wg.Add(1) - // We need a new variable in each loop iteration, - // otherwise the goroutine would use the loop variable - // and that keeps changing. - informer := informer - go func() { - defer f.wg.Done() - informer.Run(stopCh) - }() + f.wg.Go(func() { + informer.RunWithContext(ctx) + }) f.startedInformers[informerType] = true } } @@ -152,9 +169,15 @@ func (f *sharedInformerFactory) Shutdown() { // Will return immediately if there is nothing to wait for. f.wg.Wait() + f.informerName.Release() } func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { + result := f.WaitForCacheSyncWithContext(wait.ContextForChannel(stopCh)) + return result.Synced +} + +func (f *sharedInformerFactory) WaitForCacheSyncWithContext(ctx context.Context) cache.SyncResult { informers := func() map[reflect.Type]cache.SharedIndexInformer { f.lock.Lock() defer f.lock.Unlock() @@ -168,10 +191,31 @@ func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[ref return informers }() - res := map[reflect.Type]bool{} + // Wait for informers to sync, without polling. + cacheSyncs := make([]cache.DoneChecker, 0, len(informers)) + for _, informer := range informers { + cacheSyncs = append(cacheSyncs, informer.HasSyncedChecker()) + } + cache.WaitFor(ctx, "" /* no logging */, cacheSyncs...) + + res := cache.SyncResult{ + Synced: make(map[reflect.Type]bool, len(informers)), + } + failed := false for informType, informer := range informers { - res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced) + hasSynced := informer.HasSynced() + if !hasSynced { + failed = true + } + res.Synced[informType] = hasSynced } + if failed { + // context.Cause is more informative than ctx.Err(). + // This must be non-nil, otherwise WaitFor wouldn't have stopped + // prematurely. + res.Err = context.Cause(ctx) + } + return res } @@ -193,7 +237,9 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal } informer = newFunc(f.client, resyncPeriod) - informer.SetTransform(f.transform) + if f.transform != nil { + informer.SetTransform(f.transform) + } f.informers[informerType] = informer return informer @@ -204,33 +250,52 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal // // It is typically used like this: // -// ctx, cancel := context.Background() +// ctx, cancel := context.WithCancel(context.Background()) // defer cancel() // factory := NewSharedInformerFactory(client, resyncPeriod) // defer factory.WaitForStop() // Returns immediately if nothing was started. // genericInformer := factory.ForResource(resource) // typedInformer := factory.SomeAPIGroup().V1().SomeType() -// factory.Start(ctx.Done()) // Start processing these informers. -// synced := factory.WaitForCacheSync(ctx.Done()) -// for v, ok := range synced { -// if !ok { -// fmt.Fprintf(os.Stderr, "caches failed to sync: %v", v) -// return -// } +// handle, err := typeInformer.Informer().AddEventHandler(...) +// if err != nil { +// return fmt.Errorf("register event handler: %v", err) +// } +// defer typeInformer.Informer().RemoveEventHandler(handle) // Avoids leaking goroutines. +// factory.StartWithContext(ctx) // Start processing these informers. +// synced := factory.WaitForCacheSyncWithContext(ctx) +// if err := synced.AsError(); err != nil { +// return err +// } +// for v := range synced { +// // Only if desired log some information similar to this. +// fmt.Fprintf(os.Stdout, "cache synced: %s", v) +// } +// +// // Also make sure that all of the initial cache events have been delivered. +// if !WaitFor(ctx, "event handler sync", handle.HasSyncedChecker()) { +// // Must have failed because of context. +// return fmt.Errorf("sync event handler: %w", context.Cause(ctx)) // } // // // Creating informers can also be created after Start, but then // // Start must be called again: // anotherGenericInformer := factory.ForResource(resource) -// factory.Start(ctx.Done()) +// factory.StartWithContext(ctx) type SharedInformerFactory interface { internalinterfaces.SharedInformerFactory // Start initializes all requested informers. They are handled in goroutines // which run until the stop channel gets closed. // Warning: Start does not block. When run in a go-routine, it will race with a later WaitForCacheSync. + // + // Contextual logging: StartWithContext should be used instead of Start in code which supports contextual logging. Start(stopCh <-chan struct{}) + // StartWithContext initializes all requested informers. They are handled in goroutines + // which run until the context gets canceled. + // Warning: StartWithContext does not block. When run in a go-routine, it will race with a later WaitForCacheSync. + StartWithContext(ctx context.Context) + // Shutdown marks a factory as shutting down. At that point no new // informers can be started anymore and Start will return without // doing anything. @@ -245,8 +310,14 @@ type SharedInformerFactory interface { // WaitForCacheSync blocks until all started informers' caches were synced // or the stop channel gets closed. + // + // Contextual logging: WaitForCacheSync should be used instead of WaitForCacheSync in code which supports contextual logging. It also returns a more useful result. WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + // WaitForCacheSyncWithContext blocks until all started informers' caches were synced + // or the context gets canceled. + WaitForCacheSyncWithContext(ctx context.Context) cache.SyncResult + // ForResource gives generic access to a shared informer of the matching type. ForResource(resource schema.GroupVersionResource) (GenericInformer, error) diff --git a/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go b/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go index e0135a1f..9ffcfef6 100644 --- a/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go +++ b/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -34,7 +34,26 @@ type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexI type SharedInformerFactory interface { Start(stopCh <-chan struct{}) InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer + InformerName() *cache.InformerName } // TweakListOptionsFunc is a function that transforms a v1.ListOptions. type TweakListOptionsFunc func(*v1.ListOptions) + +// InformerOptions holds the options for creating an informer. +type InformerOptions struct { + // ResyncPeriod is the resync period for this informer. + // If not set, defaults to 0 (no resync). + ResyncPeriod time.Duration + + // Indexers are the indexers for this informer. + Indexers cache.Indexers + + // InformerName is used to uniquely identify this informer for metrics. + // If not set, metrics will not be published for this informer. + // Use cache.NewInformerName() to create an InformerName at startup. + InformerName *cache.InformerName + + // TweakListOptions is an optional function to modify the list options. + TweakListOptions TweakListOptionsFunc +} diff --git a/pkg/client/informers/externalversions/zalando.org/v1/platformcredentialsset.go b/pkg/client/informers/externalversions/zalando.org/v1/platformcredentialsset.go index 1e28fcd6..130a103f 100644 --- a/pkg/client/informers/externalversions/zalando.org/v1/platformcredentialsset.go +++ b/pkg/client/informers/externalversions/zalando.org/v1/platformcredentialsset.go @@ -28,6 +28,7 @@ import ( zalandoorgv1 "github.com/zalando-incubator/stackset-controller/pkg/client/listers/zalando.org/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" watch "k8s.io/apimachinery/pkg/watch" cache "k8s.io/client-go/tools/cache" ) @@ -49,48 +50,61 @@ type platformCredentialsSetInformer struct { // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. func NewPlatformCredentialsSetInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredPlatformCredentialsSetInformer(client, namespace, resyncPeriod, indexers, nil) + return NewPlatformCredentialsSetInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers}) } // NewFilteredPlatformCredentialsSetInformer constructs a new informer for PlatformCredentialsSet type. // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. func NewFilteredPlatformCredentialsSetInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { - return cache.NewSharedIndexInformer( - &cache.ListWatch{ - ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + return NewPlatformCredentialsSetInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers, TweakListOptions: tweakListOptions}) +} + +// NewPlatformCredentialsSetInformerWithOptions constructs a new informer for PlatformCredentialsSet type with additional options. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewPlatformCredentialsSetInformerWithOptions(client versioned.Interface, namespace string, options internalinterfaces.InformerOptions) cache.SharedIndexInformer { + gvr := schema.GroupVersionResource{Group: "zalando.org", Version: "v1", Resource: "platformcredentialssets"} + identifier := options.InformerName.WithResource(gvr) + tweakListOptions := options.TweakListOptions + return cache.NewSharedIndexInformerWithOptions( + cache.ToListWatcherWithWatchListSemantics(&cache.ListWatch{ + ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.ZalandoV1().PlatformCredentialsSets(namespace).List(context.Background(), options) + return client.ZalandoV1().PlatformCredentialsSets(namespace).List(context.Background(), opts) }, - WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.ZalandoV1().PlatformCredentialsSets(namespace).Watch(context.Background(), options) + return client.ZalandoV1().PlatformCredentialsSets(namespace).Watch(context.Background(), opts) }, - ListWithContextFunc: func(ctx context.Context, options metav1.ListOptions) (runtime.Object, error) { + ListWithContextFunc: func(ctx context.Context, opts metav1.ListOptions) (runtime.Object, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.ZalandoV1().PlatformCredentialsSets(namespace).List(ctx, options) + return client.ZalandoV1().PlatformCredentialsSets(namespace).List(ctx, opts) }, - WatchFuncWithContext: func(ctx context.Context, options metav1.ListOptions) (watch.Interface, error) { + WatchFuncWithContext: func(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.ZalandoV1().PlatformCredentialsSets(namespace).Watch(ctx, options) + return client.ZalandoV1().PlatformCredentialsSets(namespace).Watch(ctx, opts) }, - }, + }, client), &apiszalandoorgv1.PlatformCredentialsSet{}, - resyncPeriod, - indexers, + cache.SharedIndexInformerOptions{ + ResyncPeriod: options.ResyncPeriod, + Indexers: options.Indexers, + Identifier: identifier, + }, ) } func (f *platformCredentialsSetInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredPlatformCredentialsSetInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) + return NewPlatformCredentialsSetInformerWithOptions(client, f.namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, InformerName: f.factory.InformerName(), TweakListOptions: f.tweakListOptions}) } func (f *platformCredentialsSetInformer) Informer() cache.SharedIndexInformer { diff --git a/pkg/client/informers/externalversions/zalando.org/v1/stack.go b/pkg/client/informers/externalversions/zalando.org/v1/stack.go index 20532249..2b7cd633 100644 --- a/pkg/client/informers/externalversions/zalando.org/v1/stack.go +++ b/pkg/client/informers/externalversions/zalando.org/v1/stack.go @@ -28,6 +28,7 @@ import ( zalandoorgv1 "github.com/zalando-incubator/stackset-controller/pkg/client/listers/zalando.org/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" watch "k8s.io/apimachinery/pkg/watch" cache "k8s.io/client-go/tools/cache" ) @@ -49,48 +50,61 @@ type stackInformer struct { // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. func NewStackInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredStackInformer(client, namespace, resyncPeriod, indexers, nil) + return NewStackInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers}) } // NewFilteredStackInformer constructs a new informer for Stack type. // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. func NewFilteredStackInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { - return cache.NewSharedIndexInformer( - &cache.ListWatch{ - ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + return NewStackInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers, TweakListOptions: tweakListOptions}) +} + +// NewStackInformerWithOptions constructs a new informer for Stack type with additional options. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewStackInformerWithOptions(client versioned.Interface, namespace string, options internalinterfaces.InformerOptions) cache.SharedIndexInformer { + gvr := schema.GroupVersionResource{Group: "zalando.org", Version: "v1", Resource: "stacks"} + identifier := options.InformerName.WithResource(gvr) + tweakListOptions := options.TweakListOptions + return cache.NewSharedIndexInformerWithOptions( + cache.ToListWatcherWithWatchListSemantics(&cache.ListWatch{ + ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.ZalandoV1().Stacks(namespace).List(context.Background(), options) + return client.ZalandoV1().Stacks(namespace).List(context.Background(), opts) }, - WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.ZalandoV1().Stacks(namespace).Watch(context.Background(), options) + return client.ZalandoV1().Stacks(namespace).Watch(context.Background(), opts) }, - ListWithContextFunc: func(ctx context.Context, options metav1.ListOptions) (runtime.Object, error) { + ListWithContextFunc: func(ctx context.Context, opts metav1.ListOptions) (runtime.Object, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.ZalandoV1().Stacks(namespace).List(ctx, options) + return client.ZalandoV1().Stacks(namespace).List(ctx, opts) }, - WatchFuncWithContext: func(ctx context.Context, options metav1.ListOptions) (watch.Interface, error) { + WatchFuncWithContext: func(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.ZalandoV1().Stacks(namespace).Watch(ctx, options) + return client.ZalandoV1().Stacks(namespace).Watch(ctx, opts) }, - }, + }, client), &apiszalandoorgv1.Stack{}, - resyncPeriod, - indexers, + cache.SharedIndexInformerOptions{ + ResyncPeriod: options.ResyncPeriod, + Indexers: options.Indexers, + Identifier: identifier, + }, ) } func (f *stackInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredStackInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) + return NewStackInformerWithOptions(client, f.namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, InformerName: f.factory.InformerName(), TweakListOptions: f.tweakListOptions}) } func (f *stackInformer) Informer() cache.SharedIndexInformer { diff --git a/pkg/client/informers/externalversions/zalando.org/v1/stackset.go b/pkg/client/informers/externalversions/zalando.org/v1/stackset.go index ff75519a..adfddb94 100644 --- a/pkg/client/informers/externalversions/zalando.org/v1/stackset.go +++ b/pkg/client/informers/externalversions/zalando.org/v1/stackset.go @@ -28,6 +28,7 @@ import ( zalandoorgv1 "github.com/zalando-incubator/stackset-controller/pkg/client/listers/zalando.org/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" watch "k8s.io/apimachinery/pkg/watch" cache "k8s.io/client-go/tools/cache" ) @@ -49,48 +50,61 @@ type stackSetInformer struct { // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. func NewStackSetInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredStackSetInformer(client, namespace, resyncPeriod, indexers, nil) + return NewStackSetInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers}) } // NewFilteredStackSetInformer constructs a new informer for StackSet type. // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. func NewFilteredStackSetInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { - return cache.NewSharedIndexInformer( - &cache.ListWatch{ - ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + return NewStackSetInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers, TweakListOptions: tweakListOptions}) +} + +// NewStackSetInformerWithOptions constructs a new informer for StackSet type with additional options. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewStackSetInformerWithOptions(client versioned.Interface, namespace string, options internalinterfaces.InformerOptions) cache.SharedIndexInformer { + gvr := schema.GroupVersionResource{Group: "zalando.org", Version: "v1", Resource: "stacksets"} + identifier := options.InformerName.WithResource(gvr) + tweakListOptions := options.TweakListOptions + return cache.NewSharedIndexInformerWithOptions( + cache.ToListWatcherWithWatchListSemantics(&cache.ListWatch{ + ListFunc: func(opts metav1.ListOptions) (runtime.Object, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.ZalandoV1().StackSets(namespace).List(context.Background(), options) + return client.ZalandoV1().StackSets(namespace).List(context.Background(), opts) }, - WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.ZalandoV1().StackSets(namespace).Watch(context.Background(), options) + return client.ZalandoV1().StackSets(namespace).Watch(context.Background(), opts) }, - ListWithContextFunc: func(ctx context.Context, options metav1.ListOptions) (runtime.Object, error) { + ListWithContextFunc: func(ctx context.Context, opts metav1.ListOptions) (runtime.Object, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.ZalandoV1().StackSets(namespace).List(ctx, options) + return client.ZalandoV1().StackSets(namespace).List(ctx, opts) }, - WatchFuncWithContext: func(ctx context.Context, options metav1.ListOptions) (watch.Interface, error) { + WatchFuncWithContext: func(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { - tweakListOptions(&options) + tweakListOptions(&opts) } - return client.ZalandoV1().StackSets(namespace).Watch(ctx, options) + return client.ZalandoV1().StackSets(namespace).Watch(ctx, opts) }, - }, + }, client), &apiszalandoorgv1.StackSet{}, - resyncPeriod, - indexers, + cache.SharedIndexInformerOptions{ + ResyncPeriod: options.ResyncPeriod, + Indexers: options.Indexers, + Identifier: identifier, + }, ) } func (f *stackSetInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredStackSetInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) + return NewStackSetInformerWithOptions(client, f.namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, InformerName: f.factory.InformerName(), TweakListOptions: f.tweakListOptions}) } func (f *stackSetInformer) Informer() cache.SharedIndexInformer { From d41ab55ce8bb90badf516d4f21b1952c35948e9f Mon Sep 17 00:00:00 2001 From: Anupama Bhat Date: Mon, 24 Aug 2026 13:29:57 +0200 Subject: [PATCH 2/4] chore: update lint configuration for Go 1.26 Signed-off-by: Anupama-P --- .golangci.yml | 9 +++++++-- cmd/e2e/basic_test.go | 2 +- cmd/stackset-controller/main.go | 1 - cmd/traffic/main.go | 22 +++++++++++++++------- controller/stackset.go | 8 +++++--- docs/stack_crd.yaml | 10 +++++----- docs/stackset_crd.yaml | 20 ++++++++++---------- pkg/core/autoscaler_test.go | 10 +++++----- pkg/core/stack_resources.go | 24 ++++++++++++------------ pkg/core/stackset.go | 10 +++++----- pkg/core/test_helpers.go | 2 +- pkg/core/traffic_prescaling.go | 2 +- pkg/core/types.go | 2 +- 13 files changed, 68 insertions(+), 54 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 888a65d5..6cc5f64f 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,3 +1,5 @@ +version: "2" + run: concurrency: 4 @@ -5,9 +7,12 @@ linters: disable-all: true enable: - errcheck - - gosimple - govet - ineffassign - staticcheck - - typecheck - unused + exclusions: + rules: + - linters: + - staticcheck + text: "QF1008" diff --git a/cmd/e2e/basic_test.go b/cmd/e2e/basic_test.go index 659a24b7..499e719a 100644 --- a/cmd/e2e/basic_test.go +++ b/cmd/e2e/basic_test.go @@ -330,7 +330,7 @@ func verifyStack(t *testing.T, stacksetName, currentVersion string, stacksetSpec require.EqualValues(t, stackResourceLabels, deployment.Labels) require.EqualValues( t, replicas(deployment.Spec.Replicas), - replicas(stack.Spec.StackSpec.Replicas), + replicas(stack.Spec.Replicas), ) require.EqualValues(t, stackResourceLabels, deployment.Spec.Template.Labels) if stacksetSpec.StackTemplate.Spec.Strategy != nil { diff --git a/cmd/stackset-controller/main.go b/cmd/stackset-controller/main.go index a4b7bb17..0d3d084d 100644 --- a/cmd/stackset-controller/main.go +++ b/cmd/stackset-controller/main.go @@ -141,7 +141,6 @@ func configureKubeConfig(apiServerURL *url.URL, timeout time.Duration, stopCh <- DialContext: (&net.Dialer{ Timeout: timeout, KeepAlive: 30 * time.Second, - DualStack: false, // K8s do not work well with IPv6 }).DialContext, TLSHandshakeTimeout: timeout, ResponseHeaderTimeout: 10 * time.Second, diff --git a/cmd/traffic/main.go b/cmd/traffic/main.go index 2e65873a..d0207e25 100644 --- a/cmd/traffic/main.go +++ b/cmd/traffic/main.go @@ -60,7 +60,9 @@ func main() { if err != nil { log.Fatal(err) } - printTrafficTable(stacks) + if err := printTrafficTable(stacks); err != nil { + log.Fatal(err) + } return } @@ -68,23 +70,29 @@ func main() { if err != nil { log.Fatal(err) } - printTrafficTable(stacks) + if err := printTrafficTable(stacks); err != nil { + log.Fatal(err) + } } -func printTrafficTable(stacks []traffic.StackTrafficWeight) { +func printTrafficTable(stacks []traffic.StackTrafficWeight) error { w := tabwriter.NewWriter(os.Stdout, 8, 8, 4, ' ', 0) - fmt.Fprintf(w, "%s\t%s\t%s\n", "STACK", "DESIRED TRAFFIC", "ACTUAL TRAFFIC") + if _, err := fmt.Fprintf(w, "%s\t%s\t%s\n", "STACK", "DESIRED TRAFFIC", "ACTUAL TRAFFIC"); err != nil { + return err + } for _, stack := range stacks { - fmt.Fprintf(w, + if _, err := fmt.Fprintf(w, "%s\t%s\t%s\n", stack.Name, fmt.Sprintf("%.1f%%", stack.Weight), fmt.Sprintf("%.1f%%", stack.ActualWeight), - ) + ); err != nil { + return err + } } - w.Flush() + return w.Flush() } func newKubeConfig() (*rest.Config, error) { diff --git a/controller/stackset.go b/controller/stackset.go index 76d41ae8..5a6bcb9d 100644 --- a/controller/stackset.go +++ b/controller/stackset.go @@ -340,7 +340,7 @@ func (c *StackSetController) collectIngresses(ctx context.Context, stacksets map for _, stackset := range stacksets { if s, ok := stackset.StackContainers[uid]; ok { if strings.HasSuffix( - ingress.ObjectMeta.Name, + ingress.Name, core.SegmentSuffix, ) { // Traffic Segment @@ -378,7 +378,7 @@ func (c *StackSetController) collectRouteGroups(ctx context.Context, stacksets m for _, stackset := range stacksets { if s, ok := stackset.StackContainers[uid]; ok { if strings.HasSuffix( - routegroup.ObjectMeta.Name, + routegroup.Name, core.SegmentSuffix, ) { // Traffic Segment @@ -584,6 +584,7 @@ func (c *StackSetController) errorEventf(object runtime.Object, reason string, e object, v1.EventTypeWarning, reason, + "%s", err.Error()) return &eventedError{err: err} } @@ -1113,7 +1114,8 @@ func (c *StackSetController) ReconcileStackSet(ctx context.Context, container *c container.StackSet, v1.EventTypeWarning, "TrafficNotSwitched", - "Failed to switch traffic: "+err.Error()) + "Failed to switch traffic: %s", + err.Error()) } // Mark stacks that should be removed diff --git a/docs/stack_crd.yaml b/docs/stack_crd.yaml index 30cb9c12..03893e56 100644 --- a/docs/stack_crd.yaml +++ b/docs/stack_crd.yaml @@ -3331,11 +3331,6 @@ spec: Note that this field cannot be set when spec.os.name is windows. properties: localhostProfile: - description: |- - localhostProfile indicates a profile loaded on the node that should be used. - The profile must be preconfigured on the node to work. - Must match the loaded name of the profile. - Must be set if and only if type is "Localhost". type: string type: type: string @@ -4753,6 +4748,11 @@ spec: Note that this field cannot be set when spec.os.name is windows. properties: localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". type: string type: type: string diff --git a/docs/stackset_crd.yaml b/docs/stackset_crd.yaml index 994788b3..3e48ce43 100644 --- a/docs/stackset_crd.yaml +++ b/docs/stackset_crd.yaml @@ -3112,11 +3112,6 @@ spec: type: integer service: default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. type: string required: - port @@ -3308,6 +3303,11 @@ spec: type: integer service: default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. type: string required: - port @@ -4499,6 +4499,11 @@ spec: type: integer service: default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. type: string required: - port @@ -5150,11 +5155,6 @@ spec: type: integer service: default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. type: string required: - port diff --git a/pkg/core/autoscaler_test.go b/pkg/core/autoscaler_test.go index 42759344..2e1d4ee8 100644 --- a/pkg/core/autoscaler_test.go +++ b/pkg/core/autoscaler_test.go @@ -797,7 +797,7 @@ func TestSortingDuplicatedMetrics(t *testing.T) { }, } - metricsHash, _ := metricHash(container.Stack.ObjectMeta.Namespace, container.Stack.ObjectMeta.Name) + metricsHash, _ := metricHash(container.Stack.Namespace, container.Stack.Name) expectedMetrics := []autoscaling.MetricSpec{ { @@ -935,7 +935,7 @@ func TestSortingDuplicatedMetrics(t *testing.T) { Type: autoscaling.ObjectMetricSourceType, Object: &autoscaling.ObjectMetricSource{ Metric: autoscaling.MetricIdentifier{ - Name: fmt.Sprintf("%s,%s", requestsPerSecondName, container.Stack.ObjectMeta.Name), + Name: fmt.Sprintf("%s,%s", requestsPerSecondName, container.Stack.Name), }, DescribedObject: autoscaling.CrossVersionObjectReference{ APIVersion: "networking.k8s.io/v1", @@ -952,7 +952,7 @@ func TestSortingDuplicatedMetrics(t *testing.T) { Type: autoscaling.ObjectMetricSourceType, Object: &autoscaling.ObjectMetricSource{ Metric: autoscaling.MetricIdentifier{ - Name: fmt.Sprintf("%s,%s", requestsPerSecondName, container.Stack.ObjectMeta.Name), + Name: fmt.Sprintf("%s,%s", requestsPerSecondName, container.Stack.Name), }, DescribedObject: autoscaling.CrossVersionObjectReference{ APIVersion: "networking.k8s.io/v1", @@ -1050,7 +1050,7 @@ func TestSortingDuplicatedMetrics(t *testing.T) { Name: requestsPerSecondName, Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{ - "backend": container.Stack.ObjectMeta.Name, + "backend": container.Stack.Name, }, }, }, @@ -1072,7 +1072,7 @@ func TestSortingDuplicatedMetrics(t *testing.T) { Name: requestsPerSecondName, Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{ - "backend": container.Stack.ObjectMeta.Name, + "backend": container.Stack.Name, }, }, }, diff --git a/pkg/core/stack_resources.go b/pkg/core/stack_resources.go index 5c8550a0..f193ba0e 100644 --- a/pkg/core/stack_resources.go +++ b/pkg/core/stack_resources.go @@ -131,14 +131,14 @@ func (sc *StackContainer) resourceMeta() metav1.ObjectMeta { // getServicePorts gets the service ports to be used for the stack service. func getServicePorts(stackSpec zv1.StackSpecInternal, backendPort *intstr.IntOrString) ([]v1.ServicePort, error) { var servicePorts []v1.ServicePort - if stackSpec.StackSpec.Service == nil || - len(stackSpec.StackSpec.Service.Ports) == 0 { + if stackSpec.Service == nil || + len(stackSpec.Service.Ports) == 0 { servicePorts = servicePortsFromContainers( - stackSpec.StackSpec.PodTemplate.Spec.Containers, + stackSpec.PodTemplate.Spec.Containers, ) } else { - servicePorts = stackSpec.StackSpec.Service.Ports + servicePorts = stackSpec.Service.Ports } // validate that one port in the list maps to the backendPort. @@ -227,11 +227,11 @@ func (sc *StackContainer) GenerateDeployment() *appsv1.Deployment { } var strategy *appsv1.DeploymentStrategy - if stack.Spec.StackSpec.Strategy != nil { - strategy = stack.Spec.StackSpec.Strategy.DeepCopy() + if stack.Spec.Strategy != nil { + strategy = stack.Spec.Strategy.DeepCopy() } - embeddedCopy := stack.Spec.StackSpec.PodTemplate.ObjectMeta.DeepCopy() + embeddedCopy := stack.Spec.PodTemplate.ObjectMeta.DeepCopy() templateObjectMeta := metav1.ObjectMeta{ Annotations: embeddedCopy.Annotations, @@ -242,13 +242,13 @@ func (sc *StackContainer) GenerateDeployment() *appsv1.Deployment { ObjectMeta: sc.resourceMeta(), Spec: appsv1.DeploymentSpec{ Replicas: updatedReplicas, - MinReadySeconds: sc.Stack.Spec.StackSpec.MinReadySeconds, + MinReadySeconds: sc.Stack.Spec.MinReadySeconds, Selector: &metav1.LabelSelector{ MatchLabels: sc.selector(), }, Template: v1.PodTemplateSpec{ ObjectMeta: objectMetaInjectLabels(templateObjectMeta, stack.Labels), - Spec: *stack.Spec.StackSpec.PodTemplate.Spec.DeepCopy(), + Spec: *stack.Spec.PodTemplate.Spec.DeepCopy(), }, }, } @@ -272,7 +272,7 @@ func (sc *StackContainer) GenerateHPA() ( return nil, nil } - autoscalerSpec := sc.Stack.Spec.StackSpec.Autoscaler + autoscalerSpec := sc.Stack.Spec.Autoscaler trafficWeight := sc.actualTrafficWeight if autoscalerSpec == nil { @@ -340,10 +340,10 @@ func (sc *StackContainer) GenerateService() (*v1.Service, error) { metaObj := sc.resourceMeta() stackSpec := sc.Stack.Spec - if stackSpec.StackSpec.Service != nil { + if stackSpec.Service != nil { metaObj.Annotations = mergeLabels( metaObj.Annotations, - stackSpec.StackSpec.Service.Annotations, + stackSpec.Service.Annotations, ) } return &v1.Service{ diff --git a/pkg/core/stackset.go b/pkg/core/stackset.go index 15e67c73..25aeb41f 100644 --- a/pkg/core/stackset.go +++ b/pkg/core/stackset.go @@ -54,7 +54,7 @@ func sanitizeServicePorts(service *zv1.StackServiceSpec) *zv1.StackServiceSpec { // NewStack returns an (optional) stack that should be created func (ssc *StackSetContainer) NewStack(forwardSupportEnabled bool) (*StackContainer, string) { - _, forwardMigration := ssc.StackSet.ObjectMeta.Annotations[forwardBackendAnnotation] + _, forwardMigration := ssc.StackSet.Annotations[forwardBackendAnnotation] if !forwardSupportEnabled { forwardMigration = false } @@ -290,7 +290,7 @@ func (ssc *StackSetContainer) GenerateIngress() (*networking.Ingress, error) { if sc.actualTrafficWeight > 0 { actualWeights[sc.Name()] = sc.actualTrafficWeight - rule.IngressRuleValue.HTTP.Paths = append(rule.IngressRuleValue.HTTP.Paths, networking.HTTPIngressPath{ + rule.HTTP.Paths = append(rule.HTTP.Paths, networking.HTTPIngressPath{ Path: stackset.Spec.Ingress.Path, PathType: &PathTypeImplementationSpecific, Backend: networking.IngressBackend{ @@ -306,13 +306,13 @@ func (ssc *StackSetContainer) GenerateIngress() (*networking.Ingress, error) { } } - if len(rule.IngressRuleValue.HTTP.Paths) == 0 { + if len(rule.HTTP.Paths) == 0 { return nil, errNoPaths } // sort backends by name to have a consistent generated ingress resource. - sort.Slice(rule.IngressRuleValue.HTTP.Paths, func(i, j int) bool { - return rule.IngressRuleValue.HTTP.Paths[i].Backend.Service.Name < rule.IngressRuleValue.HTTP.Paths[j].Backend.Service.Name + sort.Slice(rule.HTTP.Paths, func(i, j int) bool { + return rule.HTTP.Paths[i].Backend.Service.Name < rule.HTTP.Paths[j].Backend.Service.Name }) // create rule per hostname diff --git a/pkg/core/test_helpers.go b/pkg/core/test_helpers.go index 99e569a2..be1c1754 100644 --- a/pkg/core/test_helpers.go +++ b/pkg/core/test_helpers.go @@ -78,7 +78,7 @@ func (f *testStackFactory) currentActualTrafficWeight(weight float64) *testStack } func (f *testStackFactory) maxReplicas(replicas int32) *testStackFactory { - f.container.Stack.Spec.StackSpec.Autoscaler = &zv1.Autoscaler{ + f.container.Stack.Spec.Autoscaler = &zv1.Autoscaler{ MaxReplicas: replicas, } return f diff --git a/pkg/core/traffic_prescaling.go b/pkg/core/traffic_prescaling.go index 1f431e8d..d4a37e24 100644 --- a/pkg/core/traffic_prescaling.go +++ b/pkg/core/traffic_prescaling.go @@ -54,7 +54,7 @@ func (r PrescalingTrafficReconciler) Reconcile(stacks map[string]*StackContainer // Unable to determine target scale, fallback to stack replicas if stack.prescalingReplicas == 0 { - stack.prescalingReplicas = effectiveReplicas(stack.Stack.Spec.StackSpec.Replicas) + stack.prescalingReplicas = effectiveReplicas(stack.Stack.Spec.Replicas) } // Limit to MaxReplicas diff --git a/pkg/core/types.go b/pkg/core/types.go index 4cef8de0..f489abdd 100644 --- a/pkg/core/types.go +++ b/pkg/core/types.go @@ -176,7 +176,7 @@ func (sc *StackContainer) IsReady() bool { } func (sc *StackContainer) MaxReplicas() int32 { - if sc.Stack.Spec.StackSpec.Autoscaler != nil { + if sc.Stack.Spec.Autoscaler != nil { return sc.Stack.Spec.StackSpec.Autoscaler.MaxReplicas } return math.MaxInt32 From e2add5536a9335650794ddef2ad000b7084e42f2 Mon Sep 17 00:00:00 2001 From: Anupama Bhat Date: Mon, 24 Aug 2026 13:36:18 +0200 Subject: [PATCH 3/4] chore(deps): pin k8s.io modules to v0.36.3 Signed-off-by: Anupama-P --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 72f41c5a..482bdf07 100644 --- a/go.mod +++ b/go.mod @@ -12,9 +12,9 @@ require ( github.com/stretchr/testify v1.12.1 github.com/szuecs/routegroup-client v0.36.3 golang.org/x/sync v0.22.0 - k8s.io/api v0.36.4 - k8s.io/apimachinery v0.36.4 - k8s.io/client-go v0.36.4 + k8s.io/api v0.36.3 + k8s.io/apimachinery v0.36.3 + k8s.io/client-go v0.36.3 sigs.k8s.io/yaml v1.6.0 ) diff --git a/go.sum b/go.sum index 092367c7..3c74d1e6 100644 --- a/go.sum +++ b/go.sum @@ -266,16 +266,16 @@ 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= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.36.4 h1:RxrvqCL6vgH5/+UnTeu1IIFqYmGfy0hnyrod1rn35Oo= -k8s.io/api v0.36.4/go.mod h1:S2B3orCFBDhrgyWbLeuKcT2QdHIpQesBkCYSlWtwUOw= +k8s.io/api v0.36.3 h1:NxB+05W2UGqXWFXcLO0RB5cnqnUPP5v5sVlaOH0Iz4w= +k8s.io/api v0.36.3/go.mod h1:JzLQKqRHC5+I8RVj/lS3lCg0mg6nWI9Fo/Sk3ElxHzg= k8s.io/apiextensions-apiserver v0.34.0 h1:B3hiB32jV7BcyKcMU5fDaDxk882YrJ1KU+ZSkA9Qxoc= k8s.io/apiextensions-apiserver v0.34.0/go.mod h1:hLI4GxE1BDBy9adJKxUxCEHBGZtGfIg98Q+JmTD7+g0= -k8s.io/apimachinery v0.36.4 h1:PT2UzkupGuAx/+xT5XjiMJ1WGpY3fn9/hdAvjweRet4= -k8s.io/apimachinery v0.36.4/go.mod h1:p2I2dipt7JHG+quVwQ1d02d28O4GdDi77RByQ13MTpk= +k8s.io/apimachinery v0.36.3 h1:PkzMRBRG8joFD8EhCuQAtNPvJlxb82FwplP26HIzvAM= +k8s.io/apimachinery v0.36.3/go.mod h1:cTSjBWgPe/6CQyBKzY/hDIRWCQQQeK0mfLbml0UYFHE= k8s.io/apiserver v0.34.0 h1:Z51fw1iGMqN7uJ1kEaynf2Aec1Y774PqU+FVWCFV3Jg= k8s.io/apiserver v0.34.0/go.mod h1:52ti5YhxAvewmmpVRqlASvaqxt0gKJxvCeW7ZrwgazQ= -k8s.io/client-go v0.36.4 h1:MDvfDNvMSt0Br94SK8neviVlwL9qifw9B26hJCpD1K0= -k8s.io/client-go v0.36.4/go.mod h1:pNK4WKELbwlEDvtbE8l22lEZL5THYF61H5EealokZmA= +k8s.io/client-go v0.36.3 h1:M4JdVzXxYcZk4fGpfDdYnxSwhLKWCFoQsHW6t+z8Hfg= +k8s.io/client-go v0.36.3/go.mod h1:gcPwr0c87vjjG6HB6pWEqOeuYVoXSsREjzux2j6GF30= k8s.io/code-generator v0.36.3 h1:tsiHI6NepXQncnexlTAf52w5VxZ4HYDU4ZqCNLFb9tA= k8s.io/code-generator v0.36.3/go.mod h1:Unn13Mp8X+H803jgZi4f4ExxK11aj0llXcSsl++UTkE= k8s.io/component-base v0.34.0 h1:bS8Ua3zlJzapklsB1dZgjEJuJEeHjj8yTu1gxE2zQX8= From eed3606f990c768e2cfc35c07b7d8e4cb6441eaf Mon Sep 17 00:00:00 2001 From: Anupama-P Date: Mon, 24 Aug 2026 13:39:30 +0200 Subject: [PATCH 4/4] fix(ci): run golangci-lint v2 Signed-off-by: Anupama-P --- .github/workflows/ci.yaml | 3 ++- Makefile | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 28ebff84..ea772d44 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -10,7 +10,8 @@ jobs: go-version: '^1.26' - run: go version - run: go install github.com/mattn/goveralls@latest - - run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest + - run: go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest + - run: mv "$(go env GOPATH)/bin/golangci-lint" "$(go env GOPATH)/bin/golangci-lint-v2" - run: make check - run: make test - run: make build.docker diff --git a/Makefile b/Makefile index fc23e910..a3b390c7 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,7 @@ GENERATED = pkg/apis/zalando.org/v1/zz_generated.deepcopy.go GOPKGS = $(shell go list ./... | grep -v /e2e) BUILD_FLAGS ?= -v LDFLAGS ?= -X main.version=$(VERSION) -w -s +GOLANGCI_LINT ?= golangci-lint-v2 default: build.local @@ -29,7 +30,7 @@ test: $(GENERATED) check: $(GENERATED) go mod download - golangci-lint run --timeout=2m ./... + $(GOLANGCI_LINT) run --timeout=2m ./... $(GENERATED): go.mod $(CRD_TYPE_SOURCE) ./hack/update-codegen.sh