From 28c991a587094db2ea09e76660ba2afd4532da84 Mon Sep 17 00:00:00 2001 From: Stefan Bueringer Date: Fri, 27 Feb 2026 10:28:31 +0100 Subject: [PATCH] Bump to k8s.io/* v0.36.0-alpha.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stefan Büringer buringerst@vmware.com --- .gomodcheck.yaml | 4 - examples/scratch-env/go.mod | 12 +-- examples/scratch-env/go.sum | 24 +++--- go.mod | 36 ++++---- go.sum | 76 ++++++++--------- pkg/cache/cache.go | 4 + pkg/cache/cache_test.go | 87 +++++++++++++++++--- pkg/cache/informertest/fake_cache.go | 2 +- pkg/cache/multi_namespace_cache.go | 114 +++++++++++++++++++------- pkg/controller/controllertest/util.go | 88 +++++++++++++++++--- tools/setup-envtest/go.mod | 2 +- tools/setup-envtest/go.sum | 4 +- 12 files changed, 320 insertions(+), 133 deletions(-) diff --git a/.gomodcheck.yaml b/.gomodcheck.yaml index e24f346250..75c5261fde 100644 --- a/.gomodcheck.yaml +++ b/.gomodcheck.yaml @@ -9,10 +9,6 @@ upstreamRefs: # k8s.io/utils -> conflicts with k/k deps excludedModules: - # Needs a newer version to fix https://github.com/kubernetes-sigs/controller-runtime/issues/3418 - # This should not be needed by the time we update to 1.36 - - sigs.k8s.io/structured-merge-diff/v6 - # --- test dependencies: - github.com/onsi/ginkgo/v2 - github.com/onsi/gomega diff --git a/examples/scratch-env/go.mod b/examples/scratch-env/go.mod index 95f6abf229..fc9ad0486b 100644 --- a/examples/scratch-env/go.mod +++ b/examples/scratch-env/go.mod @@ -50,16 +50,16 @@ require ( gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.36.0-alpha.1 // indirect - k8s.io/apiextensions-apiserver v0.36.0-alpha.1 // indirect - k8s.io/apimachinery v0.36.0-alpha.1 // indirect - k8s.io/client-go v0.36.0-alpha.1 // indirect + k8s.io/api v0.36.0-alpha.2 // indirect + k8s.io/apiextensions-apiserver v0.36.0-alpha.2 // indirect + k8s.io/apimachinery v0.36.0-alpha.2 // indirect + k8s.io/client-go v0.36.0-alpha.2 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20260127142750-a19766b6e2d4 // indirect - k8s.io/utils v0.0.0-20260108192941-914a6e750570 // indirect + k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 // 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-0.20260122202528-d9cc6641c482 // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.3.2 // indirect sigs.k8s.io/yaml v1.6.0 // indirect ) diff --git a/examples/scratch-env/go.sum b/examples/scratch-env/go.sum index 3cedd21f0d..e5862b67fc 100644 --- a/examples/scratch-env/go.sum +++ b/examples/scratch-env/go.sum @@ -145,25 +145,25 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 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.0-alpha.1 h1:iuVKXufxgq4sTsIJRZ3Sz2M3qAqfcNjestKRxfkk6Qg= -k8s.io/api v0.36.0-alpha.1/go.mod h1:tmQdQJzGz7/vieQ6wWJlG9AqQPEyE/BjODuCPePopkk= -k8s.io/apiextensions-apiserver v0.36.0-alpha.1 h1:PJ2n77mS7WXzzLhWNeUcjesn9zsikjzOh8C8+CljMFQ= -k8s.io/apiextensions-apiserver v0.36.0-alpha.1/go.mod h1:81YX6qFkUNS8y/ttJ3p2W4nTRvt4fWbKBt4uF0pLfrg= -k8s.io/apimachinery v0.36.0-alpha.1 h1:MrQLU+TD3A2/ywQiTHEJ5BEKKk3XHpy0RkT98V0XdKI= -k8s.io/apimachinery v0.36.0-alpha.1/go.mod h1:hQkG060WLAG1TIkYsu5lj3tb6YdNpKe5Zrr2UPGg+/k= -k8s.io/client-go v0.36.0-alpha.1 h1:6LgGjlF/C1U7gVn43ugh9hDyR2ToGZk4zKMwIPocYh8= -k8s.io/client-go v0.36.0-alpha.1/go.mod h1:lQ0Wzo39wPLju4QEVKX3WeLCvElRinyiHZjkeWy2gZ4= +k8s.io/api v0.36.0-alpha.2 h1:5VQ17JO0v+9X/meq70nUzb6Ec7zuAfP+izKiJMeu9zM= +k8s.io/api v0.36.0-alpha.2/go.mod h1:VrBGsSGpBoBDkL0gV2hd11bLXcW3xX0/dg352BZthWs= +k8s.io/apiextensions-apiserver v0.36.0-alpha.2 h1:YkcqeHkx+cX/Qk9kH/IH88F0gkNIFLqVQeIG2FOyDKQ= +k8s.io/apiextensions-apiserver v0.36.0-alpha.2/go.mod h1:88Ee1E7oqcG1VwCpi0DPD8qIVX7sSz7MNLyVsZMQLl0= +k8s.io/apimachinery v0.36.0-alpha.2 h1:I3A/nvRsgV/j/AX7VXDn8XjuDz2gsfcdOTVCkKMRLsQ= +k8s.io/apimachinery v0.36.0-alpha.2/go.mod h1:7mgr/dli8ofwAbcIQXetFVX1fbOYsOYojq3AUbybVmQ= +k8s.io/client-go v0.36.0-alpha.2 h1:Tk1GnYEd9KjzRG9QN84DWghJ4I91Cy5pbxSyffEZlhw= +k8s.io/client-go v0.36.0-alpha.2/go.mod h1:exn5BZg49XPJN4xNe18t4O3LJah8seb2Fxl7IyUJ6jY= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20260127142750-a19766b6e2d4 h1:HhDfevmPS+OalTjQRKbTHppRIz01AWi8s45TMXStgYY= k8s.io/kube-openapi v0.0.0-20260127142750-a19766b6e2d4/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= -k8s.io/utils v0.0.0-20260108192941-914a6e750570 h1:JT4W8lsdrGENg9W+YwwdLJxklIuKWdRm+BC+xt33FOY= -k8s.io/utils v0.0.0-20260108192941-914a6e750570/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= +k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 h1:AZYQSJemyQB5eRxqcPky+/7EdBj0xi3g0ZcxxJ7vbWU= +k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/randfill 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-0.20260122202528-d9cc6641c482 h1:2WOzJpHUBVrrkDjU4KBT8n5LDcj824eX0I5UKcgeRUs= -sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/structured-merge-diff/v6 v6.3.2 h1:kwVWMx5yS1CrnFWA/2QHyRVJ8jM6dBA80uLmm0wJkk8= +sigs.k8s.io/structured-merge-diff/v6 v6.3.2/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/go.mod b/go.mod index d413300be4..bb993c0d04 100644 --- a/go.mod +++ b/go.mod @@ -20,14 +20,14 @@ require ( golang.org/x/sys v0.40.0 gomodules.xyz/jsonpatch/v2 v2.4.0 gopkg.in/evanphx/json-patch.v4 v4.13.0 // Using v4 to match upstream - k8s.io/api v0.36.0-alpha.1 - k8s.io/apiextensions-apiserver v0.36.0-alpha.1 - k8s.io/apimachinery v0.36.0-alpha.1 - k8s.io/apiserver v0.36.0-alpha.1 - k8s.io/client-go v0.36.0-alpha.1 + k8s.io/api v0.36.0-alpha.2 + k8s.io/apiextensions-apiserver v0.36.0-alpha.2 + k8s.io/apimachinery v0.36.0-alpha.2 + k8s.io/apiserver v0.36.0-alpha.2 + k8s.io/client-go v0.36.0-alpha.2 k8s.io/klog/v2 v2.130.1 - k8s.io/utils v0.0.0-20260108192941-914a6e750570 - sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482 + k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 + sigs.k8s.io/structured-merge-diff/v6 v6.3.2 sigs.k8s.io/yaml v1.6.0 ) @@ -52,7 +52,7 @@ require ( github.com/google/gnostic-models v0.7.0 // indirect github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.4 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -69,13 +69,13 @@ require ( github.com/stoewer/go-strcase v1.3.0 // indirect github.com/x448/float16 v0.8.4 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0 // indirect - go.opentelemetry.io/otel v1.39.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.39.0 // indirect - go.opentelemetry.io/otel/metric v1.39.0 // indirect - go.opentelemetry.io/otel/sdk v1.39.0 // indirect - go.opentelemetry.io/otel/trace v1.39.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 // indirect + go.opentelemetry.io/otel v1.40.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0 // indirect + go.opentelemetry.io/otel/metric v1.40.0 // indirect + go.opentelemetry.io/otel/sdk v1.40.0 // indirect + go.opentelemetry.io/otel/trace v1.40.0 // indirect go.opentelemetry.io/proto/otlp v1.9.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect @@ -87,13 +87,13 @@ require ( golang.org/x/text v0.33.0 // indirect golang.org/x/time v0.14.0 // indirect golang.org/x/tools v0.40.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20260112192933-99fd39fd28a9 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260112192933-99fd39fd28a9 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 // indirect google.golang.org/grpc v1.78.0 // indirect google.golang.org/protobuf v1.36.11 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/component-base v0.36.0-alpha.1 // indirect + k8s.io/component-base v0.36.0-alpha.2 // indirect k8s.io/kube-openapi v0.0.0-20260127142750-a19766b6e2d4 // indirect sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 // indirect sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect diff --git a/go.sum b/go.sum index af5ed4c286..287f943d58 100644 --- a/go.sum +++ b/go.sum @@ -70,8 +70,8 @@ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.4 h1:kEISI/Gx67NzH3nJxAmY/dGac80kKZgZt134u7Y/k1s= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.4/go.mod h1:6Nz966r3vQYCqIzWsuEl9d7cf7mRhtDmm++sOxlnfxI= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7 h1:X+2YciYSxvMQK0UZ7sg45ZVabVZBeBuvMkmuI2V3Fak= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7/go.mod h1:lW34nIZuQ8UDPdkon5fmfp2l3+ZkQ2me/+oecHYLOII= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -155,22 +155,22 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0 h1:ssfIgGNANqpVFCndZvcuyKbl0g+UAVcbBcqGkG28H0Y= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0/go.mod h1:GQ/474YrbE4Jx8gZ4q5I4hrhUzM6UPzyrqJYV2AqPoQ= -go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= -go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 h1:f0cb2XPmrqn4XMy9PNliTgRKJgS5WcL/u0/WRYGz4t0= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0/go.mod h1:vnakAaFckOMiMtOIhFI2MNH4FYrZzXCYxmb1LlhoGz8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.39.0 h1:in9O8ESIOlwJAEGTkkf34DesGRAc/Pn8qJ7k3r/42LM= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.39.0/go.mod h1:Rp0EXBm5tfnv0WL+ARyO/PHBEaEAT8UUHQ6AGJcSq6c= -go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= -go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs= -go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= -go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= -go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= -go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= -go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= -go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 h1:7iP2uCb7sGddAr30RRS6xjKy7AZ2JtTOPA3oolgVSw8= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0/go.mod h1:c7hN3ddxs/z6q9xwvfLPk+UHlWRQyaeR1LdgfL/66l0= +go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms= +go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 h1:QKdN8ly8zEMrByybbQgv8cWBcdAarwmIPZ6FThrWXJs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0/go.mod h1:bTdK1nhqF76qiPoCCdyFIV+N/sRHYXYCTQc+3VCi3MI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0 h1:DvJDOPmSWQHWywQS6lKL+pb8s3gBLOZUtw4N+mavW1I= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0/go.mod h1:EtekO9DEJb4/jRyN4v4Qjc2yA7AtfCBuz2FynRUWTXs= +go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g= +go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc= +go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8= +go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE= +go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw= +go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg= +go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw= +go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA= go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A= go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -207,10 +207,10 @@ gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/api v0.0.0-20260112192933-99fd39fd28a9 h1:4DKBrmaqeptdEzp21EfrOEh8LE7PJ5ywH6wydSbOfGY= -google.golang.org/genproto/googleapis/api v0.0.0-20260112192933-99fd39fd28a9/go.mod h1:dd646eSK+Dk9kxVBl1nChEOhJPtMXriCcVb4x3o6J+E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260112192933-99fd39fd28a9 h1:IY6/YYRrFUk0JPp0xOVctvFIVuRnjccihY5kxf5g0TE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260112192933-99fd39fd28a9/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 h1:merA0rdPeUV3YIIfHHcH4qBkiQAc1nfCKSI7lB4cV2M= +google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409/go.mod h1:fl8J1IvUjCilwZzQowmw2b7HQB2eAuYBabMXzWurF+I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 h1:H86B94AW+VfJWDqFeEbBPhEtHzJwJfTbgE2lZa54ZAQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= @@ -225,31 +225,31 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 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.0-alpha.1 h1:iuVKXufxgq4sTsIJRZ3Sz2M3qAqfcNjestKRxfkk6Qg= -k8s.io/api v0.36.0-alpha.1/go.mod h1:tmQdQJzGz7/vieQ6wWJlG9AqQPEyE/BjODuCPePopkk= -k8s.io/apiextensions-apiserver v0.36.0-alpha.1 h1:PJ2n77mS7WXzzLhWNeUcjesn9zsikjzOh8C8+CljMFQ= -k8s.io/apiextensions-apiserver v0.36.0-alpha.1/go.mod h1:81YX6qFkUNS8y/ttJ3p2W4nTRvt4fWbKBt4uF0pLfrg= -k8s.io/apimachinery v0.36.0-alpha.1 h1:MrQLU+TD3A2/ywQiTHEJ5BEKKk3XHpy0RkT98V0XdKI= -k8s.io/apimachinery v0.36.0-alpha.1/go.mod h1:hQkG060WLAG1TIkYsu5lj3tb6YdNpKe5Zrr2UPGg+/k= -k8s.io/apiserver v0.36.0-alpha.1 h1:1Asrp2FOU5idJ27gnEBfftNs2M0R8I/dgcGZBpbdTDo= -k8s.io/apiserver v0.36.0-alpha.1/go.mod h1:q94OHsYAc9PUhAV/WY1oR8+KLaoA/hqhCAuFPbCDg6g= -k8s.io/client-go v0.36.0-alpha.1 h1:6LgGjlF/C1U7gVn43ugh9hDyR2ToGZk4zKMwIPocYh8= -k8s.io/client-go v0.36.0-alpha.1/go.mod h1:lQ0Wzo39wPLju4QEVKX3WeLCvElRinyiHZjkeWy2gZ4= -k8s.io/component-base v0.36.0-alpha.1 h1:TqcWstwe/G+NMYJLce7qHpbkhBMDTX/ZN+YBt1PYD3o= -k8s.io/component-base v0.36.0-alpha.1/go.mod h1:Pmt1eBuT7cJoqFdJmWbWNf7zaEdA6y1tBeZjIj4EWMA= +k8s.io/api v0.36.0-alpha.2 h1:5VQ17JO0v+9X/meq70nUzb6Ec7zuAfP+izKiJMeu9zM= +k8s.io/api v0.36.0-alpha.2/go.mod h1:VrBGsSGpBoBDkL0gV2hd11bLXcW3xX0/dg352BZthWs= +k8s.io/apiextensions-apiserver v0.36.0-alpha.2 h1:YkcqeHkx+cX/Qk9kH/IH88F0gkNIFLqVQeIG2FOyDKQ= +k8s.io/apiextensions-apiserver v0.36.0-alpha.2/go.mod h1:88Ee1E7oqcG1VwCpi0DPD8qIVX7sSz7MNLyVsZMQLl0= +k8s.io/apimachinery v0.36.0-alpha.2 h1:I3A/nvRsgV/j/AX7VXDn8XjuDz2gsfcdOTVCkKMRLsQ= +k8s.io/apimachinery v0.36.0-alpha.2/go.mod h1:7mgr/dli8ofwAbcIQXetFVX1fbOYsOYojq3AUbybVmQ= +k8s.io/apiserver v0.36.0-alpha.2 h1:7IS97LYVQ9zk6Fhykrljpn7De4VAEamR2lL/t1eWzfI= +k8s.io/apiserver v0.36.0-alpha.2/go.mod h1:jVN5pyVw9YSo5ZpmerTTAQaX2RcluD5CI2Ezyb2z4cU= +k8s.io/client-go v0.36.0-alpha.2 h1:Tk1GnYEd9KjzRG9QN84DWghJ4I91Cy5pbxSyffEZlhw= +k8s.io/client-go v0.36.0-alpha.2/go.mod h1:exn5BZg49XPJN4xNe18t4O3LJah8seb2Fxl7IyUJ6jY= +k8s.io/component-base v0.36.0-alpha.2 h1:V2jcC1cWxdWfLvWZ1tRv+9C9844zfJtzKE2bsltaAuI= +k8s.io/component-base v0.36.0-alpha.2/go.mod h1:0BDaTMFJnMBD+wSUbfQ/2azaNn9gx+/PzE21NPrYKhM= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20260127142750-a19766b6e2d4 h1:HhDfevmPS+OalTjQRKbTHppRIz01AWi8s45TMXStgYY= k8s.io/kube-openapi v0.0.0-20260127142750-a19766b6e2d4/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= -k8s.io/utils v0.0.0-20260108192941-914a6e750570 h1:JT4W8lsdrGENg9W+YwwdLJxklIuKWdRm+BC+xt33FOY= -k8s.io/utils v0.0.0-20260108192941-914a6e750570/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= +k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 h1:AZYQSJemyQB5eRxqcPky+/7EdBj0xi3g0ZcxxJ7vbWU= +k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 h1:hSfpvjjTQXQY2Fol2CS0QHMNs/WI1MOSGzCm1KhM5ec= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/randfill 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-0.20260122202528-d9cc6641c482 h1:2WOzJpHUBVrrkDjU4KBT8n5LDcj824eX0I5UKcgeRUs= -sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/structured-merge-diff/v6 v6.3.2 h1:kwVWMx5yS1CrnFWA/2QHyRVJ8jM6dBA80uLmm0wJkk8= +sigs.k8s.io/structured-merge-diff/v6 v6.3.2/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/pkg/cache/cache.go b/pkg/cache/cache.go index b814170de1..2a6a6c6be0 100644 --- a/pkg/cache/cache.go +++ b/pkg/cache/cache.go @@ -127,6 +127,10 @@ type Informer interface { // HasSynced return true if the informers underlying store has synced. HasSynced() bool + + // HasSyncedChecker completes if the informers underlying store has synced. + HasSyncedChecker() toolscache.DoneChecker + // IsStopped returns true if the informer has been stopped. IsStopped() bool } diff --git a/pkg/cache/cache_test.go b/pkg/cache/cache_test.go index 08c36a9648..875f022a3e 100644 --- a/pkg/cache/cache_test.go +++ b/pkg/cache/cache_test.go @@ -554,7 +554,7 @@ func NonBlockingGetTest(createCacheFunc func(config *rest.Config, opts cache.Opt By("creating the informer cache") opts.NewInformer = func(_ kcache.ListerWatcher, _ runtime.Object, _ time.Duration, _ kcache.Indexers) kcache.SharedIndexInformer { - return &controllertest.FakeInformer{Synced: false} + return controllertest.NewFakeInformer() } informerCache, err = createCacheFunc(cfg, opts) Expect(err).NotTo(HaveOccurred()) @@ -1353,6 +1353,11 @@ func CacheTest(createCacheFunc func(config *rest.Config, opts cache.Options) (ca }() Expect(namespacedCache.WaitForCacheSync(ctx)).To(BeTrue()) + By("check informer has synced") + informer, err := namespacedCache.GetInformer(ctx, &corev1.Pod{}) + Expect(err).ToNot(HaveOccurred()) + Eventually(informer.HasSyncedChecker().Done(), 1*time.Second).Should(BeClosed()) + By("listing pods in all namespaces") out := &metav1.PartialObjectMetadataList{} out.SetGroupVersionKind(schema.GroupVersionKind{ @@ -1960,7 +1965,23 @@ func CacheTest(createCacheFunc func(config *rest.Config, opts cache.Options) (ca addFunc := func(obj any) { out <- obj } - _, _ = sii.AddEventHandler(kcache.ResourceEventHandlerFuncs{AddFunc: addFunc}) + handlerRegistration, err := sii.AddEventHandler(kcache.ResourceEventHandlerFuncs{AddFunc: addFunc}) + Expect(err).ToNot(HaveOccurred()) + + By("draining the channel until the handler is synced") + timeout := time.After(5 * time.Second) + drainLoop: + for { + select { + case <-out: + continue + case <-handlerRegistration.HasSyncedChecker().Done(): + break drainLoop + case <-timeout: + break drainLoop + } + } + Expect(handlerRegistration.HasSyncedChecker().Done()).Should(BeClosed()) By("adding an object") cl, err := client.New(cfg, client.Options{}) @@ -2020,7 +2041,23 @@ func CacheTest(createCacheFunc func(config *rest.Config, opts cache.Options) (ca addFunc := func(obj any) { out <- obj } - _, _ = sii.AddEventHandler(kcache.ResourceEventHandlerFuncs{AddFunc: addFunc}) + handlerRegistration, err := sii.AddEventHandler(kcache.ResourceEventHandlerFuncs{AddFunc: addFunc}) + Expect(err).ToNot(HaveOccurred()) + + By("draining the channel until the handler is synced") + timeout := time.After(5 * time.Second) + drainLoop: + for { + select { + case <-out: + continue + case <-handlerRegistration.HasSyncedChecker().Done(): + break drainLoop + case <-timeout: + break drainLoop + } + } + Expect(handlerRegistration.HasSyncedChecker().Done()).Should(BeClosed()) By("adding an object") cl, err := client.New(cfg, client.Options{}) @@ -2226,7 +2263,23 @@ func CacheTest(createCacheFunc func(config *rest.Config, opts cache.Options) (ca addFunc := func(obj any) { out <- obj } - _, _ = sii.AddEventHandler(kcache.ResourceEventHandlerFuncs{AddFunc: addFunc}) + handlerRegistration, err := sii.AddEventHandler(kcache.ResourceEventHandlerFuncs{AddFunc: addFunc}) + Expect(err).ToNot(HaveOccurred()) + + By("draining the channel until the handler is synced") + timeout := time.After(5 * time.Second) + drainLoop: + for { + select { + case <-out: + continue + case <-handlerRegistration.HasSyncedChecker().Done(): + break drainLoop + case <-timeout: + break drainLoop + } + } + Expect(handlerRegistration.HasSyncedChecker().Done()).Should(BeClosed()) By("adding an object") cl, err := client.New(cfg, client.Options{}) @@ -2385,7 +2438,23 @@ func CacheTest(createCacheFunc func(config *rest.Config, opts cache.Options) (ca addFunc := func(obj any) { out <- obj } - _, _ = sii.AddEventHandler(kcache.ResourceEventHandlerFuncs{AddFunc: addFunc}) + handlerRegistration, err := sii.AddEventHandler(kcache.ResourceEventHandlerFuncs{AddFunc: addFunc}) + Expect(err).ToNot(HaveOccurred()) + + By("draining the channel until the handler is synced") + timeout := time.After(5 * time.Second) + drainLoop: + for { + select { + case <-out: + continue + case <-handlerRegistration.HasSyncedChecker().Done(): + break drainLoop + case <-timeout: + break drainLoop + } + } + Expect(handlerRegistration.HasSyncedChecker().Done()).Should(BeClosed()) By("adding an object") cl, err := client.New(cfg, client.Options{}) @@ -2607,7 +2676,7 @@ func TestReaderWaitsForCacheSync(t *testing.T) { synctest.Test(t, func(t *testing.T) { g := NewWithT(t) - fakeInformer := &controllertest.FakeInformer{Synced: false} + fakeInformer := controllertest.NewFakeInformer() c, err := cache.New(&rest.Config{}, cache.Options{ ReaderFailOnMissingInformer: readerFailOnMissingInformer, Mapper: &fakeRESTMapper{}, @@ -2641,9 +2710,7 @@ func TestReaderWaitsForCacheSync(t *testing.T) { g.Expect(err).To(HaveOccurred()) g.Expect(apierrors.IsTimeout(err)).To(BeTrue()) - fakeInformer.SyncedLock.Lock() - fakeInformer.Synced = true - fakeInformer.SyncedLock.Unlock() + fakeInformer.Synced() g.Expect(c.List(ctx, services)).To(Succeed()) @@ -2663,7 +2730,7 @@ func TestIndexFieldDoesNotBlock(t *testing.T) { synctest.Test(t, func(t *testing.T) { g := NewWithT(t) - fakeInformer := &controllertest.FakeInformer{Synced: false} + fakeInformer := controllertest.NewFakeInformer() c, err := cache.New(&rest.Config{}, cache.Options{ Mapper: &fakeRESTMapper{}, NewInformer: func(kcache.ListerWatcher, runtime.Object, time.Duration, kcache.Indexers) kcache.SharedIndexInformer { diff --git a/pkg/cache/informertest/fake_cache.go b/pkg/cache/informertest/fake_cache.go index 5f907d774b..3ca4705e57 100644 --- a/pkg/cache/informertest/fake_cache.go +++ b/pkg/cache/informertest/fake_cache.go @@ -117,7 +117,7 @@ func (c *FakeInformers) informerFor(gvk schema.GroupVersionKind, _ runtime.Objec } // Set Synced to true by default so that WaitForCacheSync returns immediately - c.InformersByGVK[gvk] = &controllertest.FakeInformer{Synced: true} + c.InformersByGVK[gvk] = controllertest.NewFakeInformer(controllertest.Synced) return c.InformersByGVK[gvk], nil } diff --git a/pkg/cache/multi_namespace_cache.go b/pkg/cache/multi_namespace_cache.go index d7d7b0e7c2..592519c35d 100644 --- a/pkg/cache/multi_namespace_cache.go +++ b/pkg/cache/multi_namespace_cache.go @@ -19,6 +19,7 @@ package cache import ( "context" "fmt" + "strings" "time" corev1 "k8s.io/api/core/v1" @@ -90,11 +91,9 @@ func (c *multiNamespaceCache) GetInformer(ctx context.Context, obj client.Object return nil, err } - return &multiNamespaceInformer{ - namespaceToInformer: map[string]Informer{ - globalCache: clusterCacheInformer, - }, - }, nil + return newMultiNamespaceInformer(map[string]Informer{ + globalCache: clusterCacheInformer, + }), nil } namespaceToInformer := map[string]Informer{} @@ -106,7 +105,7 @@ func (c *multiNamespaceCache) GetInformer(ctx context.Context, obj client.Object namespaceToInformer[ns] = informer } - return &multiNamespaceInformer{namespaceToInformer: namespaceToInformer}, nil + return newMultiNamespaceInformer(namespaceToInformer), nil } func (c *multiNamespaceCache) RemoveInformer(ctx context.Context, obj client.Object) error { @@ -143,11 +142,9 @@ func (c *multiNamespaceCache) GetInformerForKind(ctx context.Context, gvk schema return nil, err } - return &multiNamespaceInformer{ - namespaceToInformer: map[string]Informer{ - globalCache: clusterCacheInformer, - }, - }, nil + return newMultiNamespaceInformer(map[string]Informer{ + globalCache: clusterCacheInformer, + }), nil } namespaceToInformer := map[string]Informer{} @@ -159,7 +156,7 @@ func (c *multiNamespaceCache) GetInformerForKind(ctx context.Context, gvk schema namespaceToInformer[ns] = informer } - return &multiNamespaceInformer{namespaceToInformer: namespaceToInformer}, nil + return newMultiNamespaceInformer(namespaceToInformer), nil } func (c *multiNamespaceCache) Start(ctx context.Context) error { @@ -325,17 +322,47 @@ func (c *multiNamespaceCache) List(ctx context.Context, list client.ObjectList, return nil } +func newMultiNamespaceInformer(namespaceToInformer map[string]Informer) Informer { + mni := &multiNamespaceInformer{ + synced: make(chan struct{}), + namespaceToInformer: namespaceToInformer, + } + go func() { + for _, informer := range mni.namespaceToInformer { + <-informer.HasSyncedChecker().Done() + } + close(mni.synced) + }() + return mni +} + // multiNamespaceInformer knows how to handle interacting with the underlying informer across multiple namespaces. type multiNamespaceInformer struct { + synced chan struct{} namespaceToInformer map[string]Informer } -type handlerRegistration struct { +func newMultiNamespaceInformerHandlerRegistration(handles map[string]toolscache.ResourceEventHandlerRegistration) toolscache.ResourceEventHandlerRegistration { + hr := &multiNamespaceInformerHandlerRegistration{ + synced: make(chan struct{}), + handles: handles, + } + go func() { + for _, handle := range hr.handles { + <-handle.HasSyncedChecker().Done() + } + close(hr.synced) + }() + return hr +} + +type multiNamespaceInformerHandlerRegistration struct { + synced chan struct{} handles map[string]toolscache.ResourceEventHandlerRegistration } // HasSynced asserts that the handler has been called for the full initial state of the informer. -func (h handlerRegistration) HasSynced() bool { +func (h *multiNamespaceInformerHandlerRegistration) HasSynced() bool { for _, h := range h.handles { if !h.HasSynced() { return false @@ -344,62 +371,72 @@ func (h handlerRegistration) HasSynced() bool { return true } +func (h *multiNamespaceInformerHandlerRegistration) HasSyncedChecker() toolscache.DoneChecker { + return h +} + +func (h *multiNamespaceInformerHandlerRegistration) Name() string { + names := make([]string, 0, len(h.handles)) + for ns, handle := range h.handles { + names = append(names, fmt.Sprintf("%s: %s", ns, handle.HasSyncedChecker().Name())) + } + return strings.Join(names, ", ") +} + +func (h *multiNamespaceInformerHandlerRegistration) Done() <-chan struct{} { + return h.synced +} + var _ Informer = &multiNamespaceInformer{} // AddEventHandler adds the handler to each informer. func (i *multiNamespaceInformer) AddEventHandler(handler toolscache.ResourceEventHandler) (toolscache.ResourceEventHandlerRegistration, error) { - handles := handlerRegistration{ - handles: make(map[string]toolscache.ResourceEventHandlerRegistration, len(i.namespaceToInformer)), - } + handles := make(map[string]toolscache.ResourceEventHandlerRegistration, len(i.namespaceToInformer)) for ns, informer := range i.namespaceToInformer { registration, err := informer.AddEventHandler(handler) if err != nil { return nil, err } - handles.handles[ns] = registration + handles[ns] = registration } - return handles, nil + return newMultiNamespaceInformerHandlerRegistration(handles), nil } // AddEventHandlerWithResyncPeriod adds the handler with a resync period to each namespaced informer. func (i *multiNamespaceInformer) AddEventHandlerWithResyncPeriod(handler toolscache.ResourceEventHandler, resyncPeriod time.Duration) (toolscache.ResourceEventHandlerRegistration, error) { - handles := handlerRegistration{ - handles: make(map[string]toolscache.ResourceEventHandlerRegistration, len(i.namespaceToInformer)), - } + handles := make(map[string]toolscache.ResourceEventHandlerRegistration, len(i.namespaceToInformer)) for ns, informer := range i.namespaceToInformer { registration, err := informer.AddEventHandlerWithResyncPeriod(handler, resyncPeriod) if err != nil { return nil, err } - handles.handles[ns] = registration + handles[ns] = registration } - return handles, nil + return newMultiNamespaceInformerHandlerRegistration(handles), nil } // AddEventHandlerWithOptions adds the handler with options to each namespaced informer. func (i *multiNamespaceInformer) AddEventHandlerWithOptions(handler toolscache.ResourceEventHandler, options toolscache.HandlerOptions) (toolscache.ResourceEventHandlerRegistration, error) { - handles := handlerRegistration{ - handles: make(map[string]toolscache.ResourceEventHandlerRegistration, len(i.namespaceToInformer)), - } + handles := make(map[string]toolscache.ResourceEventHandlerRegistration, len(i.namespaceToInformer)) for ns, informer := range i.namespaceToInformer { registration, err := informer.AddEventHandlerWithOptions(handler, options) if err != nil { return nil, err } - handles.handles[ns] = registration + handles[ns] = registration } - return handles, nil + return newMultiNamespaceInformerHandlerRegistration(handles), nil } // RemoveEventHandler removes a previously added event handler given by its registration handle. func (i *multiNamespaceInformer) RemoveEventHandler(h toolscache.ResourceEventHandlerRegistration) error { - handles, ok := h.(handlerRegistration) + handles, ok := h.(*multiNamespaceInformerHandlerRegistration) if !ok { return fmt.Errorf("registration is not a registration returned by multiNamespaceInformer") } @@ -436,6 +473,23 @@ func (i *multiNamespaceInformer) HasSynced() bool { return true } +// HasSyncedChecker completes if each informer has synced. +func (i *multiNamespaceInformer) HasSyncedChecker() toolscache.DoneChecker { + return i +} + +func (i *multiNamespaceInformer) Name() string { + names := make([]string, 0, len(i.namespaceToInformer)) + for ns, informer := range i.namespaceToInformer { + names = append(names, fmt.Sprintf("%s: %s", ns, informer.HasSyncedChecker().Name())) + } + return strings.Join(names, ", ") +} + +func (i *multiNamespaceInformer) Done() <-chan struct{} { + return i.synced +} + // IsStopped checks if each namespaced informer has stopped, returns false if any are still running. func (i *multiNamespaceInformer) IsStopped() bool { for _, informer := range i.namespaceToInformer { diff --git a/pkg/controller/controllertest/util.go b/pkg/controller/controllertest/util.go index f6e8b4904d..49a4dc2007 100644 --- a/pkg/controller/controllertest/util.go +++ b/pkg/controller/controllertest/util.go @@ -18,7 +18,6 @@ package controllertest import ( "context" - "sync" "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -27,11 +26,33 @@ import ( var _ cache.SharedIndexInformer = &FakeInformer{} +// InformerOptions contains options for NewFakeInformer. +type InformerOptions struct { + // Synced indicates the informer is immediately synced after NewFakeInformer. + Synced bool +} + +// InformerOption is some configuration that modifies options for NewFakeInformer. +type InformerOption interface { + // Apply applies this configuration to the given InformerOptions. + Apply(*InformerOptions) +} + +// Synced indicates the informer is immediately synced after NewFakeInformer. +var Synced = synced{} + +type synced struct{} + +func (synced) Apply(opts *InformerOptions) { + opts.Synced = true +} + // FakeInformer provides fake Informer functionality for testing. +// FakeInformer must be constructed via NewFakeInformer. type FakeInformer struct { - // Synced is returned by the HasSynced functions to implement the Informer interface - Synced bool - SyncedLock sync.Mutex + // synced is used to signal that the informer is synced. + // This field is used in various HasSynced and HasSyncedChecker methods. + synced chan struct{} // RunCount is incremented each time RunInformersAndControllers is called RunCount int @@ -39,6 +60,21 @@ type FakeInformer struct { handlers []cache.ResourceEventHandler } +func NewFakeInformer(opts ...InformerOption) *FakeInformer { + informerOptions := &InformerOptions{} + for _, opt := range opts { + opt.Apply(informerOptions) + } + + f := &FakeInformer{ + synced: make(chan struct{}), + } + if informerOptions.Synced { + f.Synced() + } + return f +} + // fakeHandlerRegistration implements cache.ResourceEventHandlerRegistration for testing. type fakeHandlerRegistration struct { informer *FakeInformer @@ -46,10 +82,20 @@ type fakeHandlerRegistration struct { // HasSynced implements cache.ResourceEventHandlerRegistration. func (f *fakeHandlerRegistration) HasSynced() bool { - f.informer.SyncedLock.Lock() - defer f.informer.SyncedLock.Unlock() + return f.informer.HasSynced() +} + +// HasSyncedChecker implements cache.ResourceEventHandlerRegistration. +func (f *fakeHandlerRegistration) HasSyncedChecker() cache.DoneChecker { + return f +} - return f.informer.Synced +func (f *fakeHandlerRegistration) Name() string { + return "FakeHandlerRegistration" +} + +func (f *fakeHandlerRegistration) Done() <-chan struct{} { + return f.informer.synced } // AddIndexers does nothing. TODO(community): Implement this. @@ -67,12 +113,32 @@ func (f *FakeInformer) Informer() cache.SharedIndexInformer { return f } -// HasSynced implements the Informer interface. Returns f.Synced. +// Synced sets the FakeInformer state to "synced". +func (f *FakeInformer) Synced() { + close(f.synced) +} + +// HasSynced implements the Informer interface. Returns f.Synced. func (f *FakeInformer) HasSynced() bool { - f.SyncedLock.Lock() - defer f.SyncedLock.Unlock() + select { + case <-f.synced: + return true + default: + return false + } +} + +// HasSyncedChecker implements the Informer interface. +func (f *FakeInformer) HasSyncedChecker() cache.DoneChecker { + return f +} + +func (f *FakeInformer) Name() string { + return "FakeInformer" +} - return f.Synced +func (f *FakeInformer) Done() <-chan struct{} { + return f.synced } // AddEventHandler implements the Informer interface. Adds an EventHandler to the fake Informers. TODO(community): Implement Registration. diff --git a/tools/setup-envtest/go.mod b/tools/setup-envtest/go.mod index f68627b463..a28d6e90ee 100644 --- a/tools/setup-envtest/go.mod +++ b/tools/setup-envtest/go.mod @@ -10,7 +10,7 @@ require ( github.com/spf13/afero v1.12.0 github.com/spf13/pflag v1.0.9 go.uber.org/zap v1.27.0 - k8s.io/apimachinery v0.36.0-alpha.1 + k8s.io/apimachinery v0.36.0-alpha.2 sigs.k8s.io/yaml v1.6.0 ) diff --git a/tools/setup-envtest/go.sum b/tools/setup-envtest/go.sum index 99235663f1..3537ee739f 100644 --- a/tools/setup-envtest/go.sum +++ b/tools/setup-envtest/go.sum @@ -81,7 +81,7 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 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/apimachinery v0.36.0-alpha.1 h1:MrQLU+TD3A2/ywQiTHEJ5BEKKk3XHpy0RkT98V0XdKI= -k8s.io/apimachinery v0.36.0-alpha.1/go.mod h1:hQkG060WLAG1TIkYsu5lj3tb6YdNpKe5Zrr2UPGg+/k= +k8s.io/apimachinery v0.36.0-alpha.2 h1:I3A/nvRsgV/j/AX7VXDn8XjuDz2gsfcdOTVCkKMRLsQ= +k8s.io/apimachinery v0.36.0-alpha.2/go.mod h1:7mgr/dli8ofwAbcIQXetFVX1fbOYsOYojq3AUbybVmQ= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=