From 3ffe842399aa446ee91b2389058020eb2a8084bf Mon Sep 17 00:00:00 2001 From: Fabio Bertinatto Date: Mon, 2 Mar 2026 18:21:49 -0300 Subject: [PATCH 1/2] Bump to latest openshift/kubernetes (release-4.16 branch) --- go.mod | 60 ++--- go.sum | 96 ++++---- .../pkg/apiserver/customresource_handler.go | 24 +- .../k8s.io/apimachinery/pkg/api/meta/help.go | 3 + .../pkg/runtime/serializer/codec_factory.go | 24 +- .../runtime/serializer/json/collections.go | 231 ++++++++++++++++++ .../pkg/runtime/serializer/json/json.go | 16 +- .../serializer/protobuf/collections.go | 174 +++++++++++++ .../runtime/serializer/protobuf/protobuf.go | 87 +++++-- .../apimachinery/pkg/runtime/types_proto.go | 127 +++++++++- .../handlers/responsewriters/writers.go | 60 ++++- .../apiserver/pkg/features/kube_features.go | 12 + .../apiserver/pkg/server/genericapiserver.go | 11 + .../etcd3/etcd3retry/retry_etcdclient.go | 82 +++++-- .../generated/zz_generated.annotations.go | 2 +- .../openshift-hack/e2e/annotate/rules.go | 3 + .../kubernetes/pkg/features/kube_features.go | 21 +- .../kubelet/apis/podresources/server_v1.go | 44 ++-- .../pkg/kubelet/apis/podresources/types.go | 1 + .../k8s.io/kubernetes/pkg/kubelet/kubelet.go | 18 +- .../core/rest/storage_core_generic.go | 13 + .../framework/plugins/nodevolumelimits/csi.go | 60 ++++- .../k8s.io/kubernetes/pkg/volume/plugins.go | 13 +- .../authorizer/rbac/bootstrappolicy/policy.go | 1 + vendor/modules.txt | 108 ++++---- 25 files changed, 1072 insertions(+), 219 deletions(-) create mode 100644 vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/collections.go create mode 100644 vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf/collections.go diff --git a/go.mod b/go.mod index 599161edba86..47e70f1cabed 100644 --- a/go.mod +++ b/go.mod @@ -291,34 +291,34 @@ require ( replace ( github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20231031162821-c5e24be53ea7 - k8s.io/api => github.com/openshift/kubernetes/staging/src/k8s.io/api v0.0.0-20250808221949-c68a6637efae - k8s.io/apiextensions-apiserver => github.com/openshift/kubernetes/staging/src/k8s.io/apiextensions-apiserver v0.0.0-20250808221949-c68a6637efae - k8s.io/apimachinery => github.com/openshift/kubernetes/staging/src/k8s.io/apimachinery v0.0.0-20250808221949-c68a6637efae - k8s.io/apiserver => github.com/openshift/kubernetes/staging/src/k8s.io/apiserver v0.0.0-20250808221949-c68a6637efae - k8s.io/cli-runtime => github.com/openshift/kubernetes/staging/src/k8s.io/cli-runtime v0.0.0-20250808221949-c68a6637efae - k8s.io/client-go => github.com/openshift/kubernetes/staging/src/k8s.io/client-go v0.0.0-20250808221949-c68a6637efae - k8s.io/cloud-provider => github.com/openshift/kubernetes/staging/src/k8s.io/cloud-provider v0.0.0-20250808221949-c68a6637efae - k8s.io/cluster-bootstrap => github.com/openshift/kubernetes/staging/src/k8s.io/cluster-bootstrap v0.0.0-20250808221949-c68a6637efae - k8s.io/code-generator => github.com/openshift/kubernetes/staging/src/k8s.io/code-generator v0.0.0-20250808221949-c68a6637efae - k8s.io/component-base => github.com/openshift/kubernetes/staging/src/k8s.io/component-base v0.0.0-20250808221949-c68a6637efae - k8s.io/component-helpers => github.com/openshift/kubernetes/staging/src/k8s.io/component-helpers v0.0.0-20250808221949-c68a6637efae - k8s.io/controller-manager => github.com/openshift/kubernetes/staging/src/k8s.io/controller-manager v0.0.0-20250808221949-c68a6637efae - k8s.io/cri-api => github.com/openshift/kubernetes/staging/src/k8s.io/cri-api v0.0.0-20250808221949-c68a6637efae - k8s.io/csi-translation-lib => github.com/openshift/kubernetes/staging/src/k8s.io/csi-translation-lib v0.0.0-20250808221949-c68a6637efae - k8s.io/dynamic-resource-allocation => github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation v0.0.0-20250808221949-c68a6637efae - k8s.io/endpointslice => github.com/openshift/kubernetes/staging/src/k8s.io/endpointslice v0.0.0-20250808221949-c68a6637efae - k8s.io/kube-aggregator => github.com/openshift/kubernetes/staging/src/k8s.io/kube-aggregator v0.0.0-20250808221949-c68a6637efae - k8s.io/kube-controller-manager => github.com/openshift/kubernetes/staging/src/k8s.io/kube-controller-manager v0.0.0-20250808221949-c68a6637efae - k8s.io/kube-proxy => github.com/openshift/kubernetes/staging/src/k8s.io/kube-proxy v0.0.0-20250808221949-c68a6637efae - k8s.io/kube-scheduler => github.com/openshift/kubernetes/staging/src/k8s.io/kube-scheduler v0.0.0-20250808221949-c68a6637efae - k8s.io/kubectl => github.com/openshift/kubernetes/staging/src/k8s.io/kubectl v0.0.0-20250808221949-c68a6637efae - k8s.io/kubelet => github.com/openshift/kubernetes/staging/src/k8s.io/kubelet v0.0.0-20250808221949-c68a6637efae - k8s.io/kubernetes => github.com/openshift/kubernetes v1.29.0-rc.1.0.20250808221949-c68a6637efae - k8s.io/legacy-cloud-providers => github.com/openshift/kubernetes/staging/src/k8s.io/legacy-cloud-providers v0.0.0-20250808221949-c68a6637efae - k8s.io/metrics => github.com/openshift/kubernetes/staging/src/k8s.io/metrics v0.0.0-20250808221949-c68a6637efae - k8s.io/mount-utils => github.com/openshift/kubernetes/staging/src/k8s.io/mount-utils v0.0.0-20250808221949-c68a6637efae - k8s.io/pod-security-admission => github.com/openshift/kubernetes/staging/src/k8s.io/pod-security-admission v0.0.0-20250808221949-c68a6637efae - k8s.io/sample-apiserver => github.com/openshift/kubernetes/staging/src/k8s.io/sample-apiserver v0.0.0-20250808221949-c68a6637efae - k8s.io/sample-cli-plugin => github.com/openshift/kubernetes/staging/src/k8s.io/sample-cli-plugin v0.0.0-20250808221949-c68a6637efae - k8s.io/sample-controller => github.com/openshift/kubernetes/staging/src/k8s.io/sample-controller v0.0.0-20250808221949-c68a6637efae + k8s.io/api => github.com/openshift/kubernetes/staging/src/k8s.io/api v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/apiextensions-apiserver => github.com/openshift/kubernetes/staging/src/k8s.io/apiextensions-apiserver v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/apimachinery => github.com/openshift/kubernetes/staging/src/k8s.io/apimachinery v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/apiserver => github.com/openshift/kubernetes/staging/src/k8s.io/apiserver v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/cli-runtime => github.com/openshift/kubernetes/staging/src/k8s.io/cli-runtime v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/client-go => github.com/openshift/kubernetes/staging/src/k8s.io/client-go v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/cloud-provider => github.com/openshift/kubernetes/staging/src/k8s.io/cloud-provider v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/cluster-bootstrap => github.com/openshift/kubernetes/staging/src/k8s.io/cluster-bootstrap v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/code-generator => github.com/openshift/kubernetes/staging/src/k8s.io/code-generator v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/component-base => github.com/openshift/kubernetes/staging/src/k8s.io/component-base v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/component-helpers => github.com/openshift/kubernetes/staging/src/k8s.io/component-helpers v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/controller-manager => github.com/openshift/kubernetes/staging/src/k8s.io/controller-manager v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/cri-api => github.com/openshift/kubernetes/staging/src/k8s.io/cri-api v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/csi-translation-lib => github.com/openshift/kubernetes/staging/src/k8s.io/csi-translation-lib v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/dynamic-resource-allocation => github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/endpointslice => github.com/openshift/kubernetes/staging/src/k8s.io/endpointslice v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/kube-aggregator => github.com/openshift/kubernetes/staging/src/k8s.io/kube-aggregator v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/kube-controller-manager => github.com/openshift/kubernetes/staging/src/k8s.io/kube-controller-manager v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/kube-proxy => github.com/openshift/kubernetes/staging/src/k8s.io/kube-proxy v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/kube-scheduler => github.com/openshift/kubernetes/staging/src/k8s.io/kube-scheduler v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/kubectl => github.com/openshift/kubernetes/staging/src/k8s.io/kubectl v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/kubelet => github.com/openshift/kubernetes/staging/src/k8s.io/kubelet v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/kubernetes => github.com/openshift/kubernetes v1.29.0-rc.1.0.20260209193319-41c4e9ba94f4 + k8s.io/legacy-cloud-providers => github.com/openshift/kubernetes/staging/src/k8s.io/legacy-cloud-providers v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/metrics => github.com/openshift/kubernetes/staging/src/k8s.io/metrics v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/mount-utils => github.com/openshift/kubernetes/staging/src/k8s.io/mount-utils v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/pod-security-admission => github.com/openshift/kubernetes/staging/src/k8s.io/pod-security-admission v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/sample-apiserver => github.com/openshift/kubernetes/staging/src/k8s.io/sample-apiserver v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/sample-cli-plugin => github.com/openshift/kubernetes/staging/src/k8s.io/sample-cli-plugin v0.0.0-20260209193319-41c4e9ba94f4 + k8s.io/sample-controller => github.com/openshift/kubernetes/staging/src/k8s.io/sample-controller v0.0.0-20260209193319-41c4e9ba94f4 ) diff --git a/go.sum b/go.sum index d389dd7662a8..58f98da7413e 100644 --- a/go.sum +++ b/go.sum @@ -644,54 +644,54 @@ github.com/openshift/client-go v0.0.0-20240510131258-f646d5f29250 h1:WQ0e89xebsN github.com/openshift/client-go v0.0.0-20240510131258-f646d5f29250/go.mod h1:tjGjTE59N1+5W0YE4Wqf0zJpFLIY4d+EpMihDKOn1oA= github.com/openshift/cluster-network-operator v0.0.0-20240111190956-90754aa19843 h1:gnesIcAzYdKHsUuKlHT9U36bWJ/8xBDkyjY/mRkdCBU= github.com/openshift/cluster-network-operator v0.0.0-20240111190956-90754aa19843/go.mod h1:chX1Hl5mlarhOVgqSrG8lbYoxUjO8x9+eALxBhGOLxM= -github.com/openshift/kubernetes v1.29.0-rc.1.0.20250808221949-c68a6637efae h1:zYvtRSXy44c7BAWMA5eQrJJ9DROk4dLYblXIvprJsas= -github.com/openshift/kubernetes v1.29.0-rc.1.0.20250808221949-c68a6637efae/go.mod h1:qfHpJmKw/Xj8ANJOegNbbwD2lh5+1nN9e4uXkA5fGTI= -github.com/openshift/kubernetes/staging/src/k8s.io/api v0.0.0-20250808221949-c68a6637efae h1:rw8H/3jFZsI7fkn7faAPlj1uk4gBwiSANmdE7/EwAhM= -github.com/openshift/kubernetes/staging/src/k8s.io/api v0.0.0-20250808221949-c68a6637efae/go.mod h1:qMfTVH/yQM4Gc2f5VQJbV1AMWQi8YFwu6fKRuT1Csx4= -github.com/openshift/kubernetes/staging/src/k8s.io/apiextensions-apiserver v0.0.0-20250808221949-c68a6637efae h1:ZI8M4498onk64q4PBPlZWS1wvC/76Yat7RSUjTRp5xg= -github.com/openshift/kubernetes/staging/src/k8s.io/apiextensions-apiserver v0.0.0-20250808221949-c68a6637efae/go.mod h1:jhDtaY6FHLbdNB1nonFhYsFlUvaJdPGPVx36znayM9I= -github.com/openshift/kubernetes/staging/src/k8s.io/apimachinery v0.0.0-20250808221949-c68a6637efae h1:stOVWOwGgzvFr1DJp3qUnonkwr67hANTSEbDTC1Ql/E= -github.com/openshift/kubernetes/staging/src/k8s.io/apimachinery v0.0.0-20250808221949-c68a6637efae/go.mod h1:IhHRRF080N9VU1QEEJ5zTYAQkPElZ84OH08nPyo0Lw0= -github.com/openshift/kubernetes/staging/src/k8s.io/apiserver v0.0.0-20250808221949-c68a6637efae h1:Nkxgs9tBVAtU0IKCEIivjIR445rvRnKN0CakDKhQ4hY= -github.com/openshift/kubernetes/staging/src/k8s.io/apiserver v0.0.0-20250808221949-c68a6637efae/go.mod h1:4wOG/HF+iyD0gEisqn5Ep09bAqOHw8Vl0mkB9ZEbF2A= -github.com/openshift/kubernetes/staging/src/k8s.io/cli-runtime v0.0.0-20250808221949-c68a6637efae h1:MF0bKyH/aVwVuac1OZrcuaYYCtZ2ytPLlaKax63qUdQ= -github.com/openshift/kubernetes/staging/src/k8s.io/cli-runtime v0.0.0-20250808221949-c68a6637efae/go.mod h1:eq1ArtMJ3o/VUDn7NTP/eryQG8pTGjtattESXd5g42U= -github.com/openshift/kubernetes/staging/src/k8s.io/client-go v0.0.0-20250808221949-c68a6637efae h1:n7hg/mCkmwzpKgFRtE8eQePkBX15foHA5YKLFvPmgow= -github.com/openshift/kubernetes/staging/src/k8s.io/client-go v0.0.0-20250808221949-c68a6637efae/go.mod h1:68E0AiovGRxyJ30s/QzLPLardQJCx/gm2GhdaAzJ10M= -github.com/openshift/kubernetes/staging/src/k8s.io/cloud-provider v0.0.0-20250808221949-c68a6637efae h1:OcBBH7KmocDF+ztukFKDwxu4aVyn+cAyBhY0omH+0G8= -github.com/openshift/kubernetes/staging/src/k8s.io/cloud-provider v0.0.0-20250808221949-c68a6637efae/go.mod h1:BMxEHFgDwf6lIiU/WFf9JaKhPjqKY2C3KPRaEF981TE= -github.com/openshift/kubernetes/staging/src/k8s.io/cluster-bootstrap v0.0.0-20250808221949-c68a6637efae h1:E2iak98SzBWZzzXJFPtRWa0ji4Tf0BqmBqp27ET2uoM= -github.com/openshift/kubernetes/staging/src/k8s.io/cluster-bootstrap v0.0.0-20250808221949-c68a6637efae/go.mod h1:NMIqLZ1bjJKn/OxQs/urOq9Mo7o4Z9SgaEkDi8r0iDQ= -github.com/openshift/kubernetes/staging/src/k8s.io/component-base v0.0.0-20250808221949-c68a6637efae h1:0s47q6FvnCaRryHXqHAyJKOd3ZIj1ZF2kDXj6pd/e2o= -github.com/openshift/kubernetes/staging/src/k8s.io/component-base v0.0.0-20250808221949-c68a6637efae/go.mod h1:3b4Iqz886KuvrA4U8pXcWoOPZh+fHh04LF28btXScbw= -github.com/openshift/kubernetes/staging/src/k8s.io/component-helpers v0.0.0-20250808221949-c68a6637efae h1:xNC+Tj+S/u/0PgeCl/NiXsHJLRFRfml26eayJnwmZn4= -github.com/openshift/kubernetes/staging/src/k8s.io/component-helpers v0.0.0-20250808221949-c68a6637efae/go.mod h1:Ogwj8/aLf37gUsRvZD1mAbSYWGxDAvc5RlO1c0PtjJY= -github.com/openshift/kubernetes/staging/src/k8s.io/controller-manager v0.0.0-20250808221949-c68a6637efae h1:HL1LCWZ1TDthnRup6taAjwnGUboE7hN7lffLlCo1HFw= -github.com/openshift/kubernetes/staging/src/k8s.io/controller-manager v0.0.0-20250808221949-c68a6637efae/go.mod h1:lP4RyYBciOkhbVCTb5MbSN0/GOauZTwGgpbTkwb7kEw= -github.com/openshift/kubernetes/staging/src/k8s.io/cri-api v0.0.0-20250808221949-c68a6637efae h1:+tXsjWTks+U1RGeDLxu2EbFsu4icOYdOMnS50ArFtF8= -github.com/openshift/kubernetes/staging/src/k8s.io/cri-api v0.0.0-20250808221949-c68a6637efae/go.mod h1:9Tgle7RkZOzgRM2VCSvvXZZjsQqOC6dxLtYy6BF+5PE= -github.com/openshift/kubernetes/staging/src/k8s.io/csi-translation-lib v0.0.0-20250808221949-c68a6637efae h1:KXHigt+FA7THdsT86Fg7rZRVnFpExggiK24y4z137ZE= -github.com/openshift/kubernetes/staging/src/k8s.io/csi-translation-lib v0.0.0-20250808221949-c68a6637efae/go.mod h1:bKXDOUmiy/juOoPYsnxt3RbUKZKx+LFKsfCZw8nxsos= -github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation v0.0.0-20250808221949-c68a6637efae h1:xbR8qOA4mYODHF71oDVUTJQZ+QSCnsU/T/HQqOUu2fc= -github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation v0.0.0-20250808221949-c68a6637efae/go.mod h1:ia6wL8kICRq0a6Zj2idep1RncpGA/8/qdTbL5rYqxz0= -github.com/openshift/kubernetes/staging/src/k8s.io/kube-aggregator v0.0.0-20250808221949-c68a6637efae h1:SBYkiGevI9uC3xLKCSQp4kHLD1O7QcN8DXKs9gqVEkk= -github.com/openshift/kubernetes/staging/src/k8s.io/kube-aggregator v0.0.0-20250808221949-c68a6637efae/go.mod h1:qU9xk9626BLArUnM067MnuYDKCp5yy1PZypQg5VFN1U= -github.com/openshift/kubernetes/staging/src/k8s.io/kube-scheduler v0.0.0-20250808221949-c68a6637efae h1:FqCdEPNg3K6MiWhyRyHdpSEJCDyFhCUKHxTx1I9RmzY= -github.com/openshift/kubernetes/staging/src/k8s.io/kube-scheduler v0.0.0-20250808221949-c68a6637efae/go.mod h1:iCnLhShFPbA6+0cBJHMIC8osA4ukveEZbQweXjn+oXo= -github.com/openshift/kubernetes/staging/src/k8s.io/kubectl v0.0.0-20250808221949-c68a6637efae h1:fucFo6g2HUwtaVmaemuSrRMxfbIV6uoyaR6A4ZtISZs= -github.com/openshift/kubernetes/staging/src/k8s.io/kubectl v0.0.0-20250808221949-c68a6637efae/go.mod h1:L0N5ONv4vn8oIGy8gjX0ZzkLT7GLQxP2G9R2+K/osEM= -github.com/openshift/kubernetes/staging/src/k8s.io/kubelet v0.0.0-20250808221949-c68a6637efae h1:N3xSYuEBwWLeYT/lB8ExOOBWE82CuPA+bQw9GZFBykY= -github.com/openshift/kubernetes/staging/src/k8s.io/kubelet v0.0.0-20250808221949-c68a6637efae/go.mod h1:KvraWPlwZlgVhDnR3yjrAQTIPAk2Qia7iA6f7MWmZ6k= -github.com/openshift/kubernetes/staging/src/k8s.io/legacy-cloud-providers v0.0.0-20250808221949-c68a6637efae h1:0r1IiS+gr00o9L30T/NzYaA9x3ramTtgfZv/vqbho3E= -github.com/openshift/kubernetes/staging/src/k8s.io/legacy-cloud-providers v0.0.0-20250808221949-c68a6637efae/go.mod h1:W4g9/bUJ1/X01jOJGx395Ob4wKV2R58OrGvDhVdZSjw= -github.com/openshift/kubernetes/staging/src/k8s.io/metrics v0.0.0-20250808221949-c68a6637efae h1:gJsVC6xLHIimP6aI7wEhP8bKAH4cpMYc7n42RrpOPmI= -github.com/openshift/kubernetes/staging/src/k8s.io/metrics v0.0.0-20250808221949-c68a6637efae/go.mod h1:wcQC0ObNu0HtMRBaJJL6OJgg+DzcrdgW9ek5i7AncbE= -github.com/openshift/kubernetes/staging/src/k8s.io/mount-utils v0.0.0-20250808221949-c68a6637efae h1:Q8WXAprNZ4sBSyPVXfxZUTQ+8wmo1nQvWHpLb9MTJ6A= -github.com/openshift/kubernetes/staging/src/k8s.io/mount-utils v0.0.0-20250808221949-c68a6637efae/go.mod h1:4KmkE88Y4LDYrotr6iqMrolXDcWWY7UqmroXTO/sxFw= -github.com/openshift/kubernetes/staging/src/k8s.io/pod-security-admission v0.0.0-20250808221949-c68a6637efae h1:7M0OoRTTSDVKBy2sn/t2LQDT1AsPLU7Ewe2Nlcv1cqo= -github.com/openshift/kubernetes/staging/src/k8s.io/pod-security-admission v0.0.0-20250808221949-c68a6637efae/go.mod h1:nEqWuQNrBxCIeYnc9zWoV3/SW5Lhtrn7vvugEFVk88o= -github.com/openshift/kubernetes/staging/src/k8s.io/sample-apiserver v0.0.0-20250808221949-c68a6637efae h1:DBTWC6fxo64I1iZyGO1zcRxBCcEulKdizTdTXlkskQI= -github.com/openshift/kubernetes/staging/src/k8s.io/sample-apiserver v0.0.0-20250808221949-c68a6637efae/go.mod h1:DRthJqxCPFs1oAAJEF0tyou7kJ+LlNASc7P8YqKSBC8= +github.com/openshift/kubernetes v1.29.0-rc.1.0.20260209193319-41c4e9ba94f4 h1:qOVRuW6bjf7Jxlv14fveQr9K5rDB1DAMOXQ8d0BcZdY= +github.com/openshift/kubernetes v1.29.0-rc.1.0.20260209193319-41c4e9ba94f4/go.mod h1:o/2Y2qmbcgLLzlwoN3iMFiR03X9Mjj+cBgA8oc2rklQ= +github.com/openshift/kubernetes/staging/src/k8s.io/api v0.0.0-20260209193319-41c4e9ba94f4 h1:HU6RPZpIUc42q1OzXrIxHamM/ukSL+WvW/tM+QXdPB4= +github.com/openshift/kubernetes/staging/src/k8s.io/api v0.0.0-20260209193319-41c4e9ba94f4/go.mod h1:qMfTVH/yQM4Gc2f5VQJbV1AMWQi8YFwu6fKRuT1Csx4= +github.com/openshift/kubernetes/staging/src/k8s.io/apiextensions-apiserver v0.0.0-20260209193319-41c4e9ba94f4 h1:U+Gi8v/CsVHhzrB7UZoZeqEHHQDaQVtmCnYCtQQI7+c= +github.com/openshift/kubernetes/staging/src/k8s.io/apiextensions-apiserver v0.0.0-20260209193319-41c4e9ba94f4/go.mod h1:09piPsqxFgJOBxSNW94g9yW5l1/rcUSbshP5fESwueU= +github.com/openshift/kubernetes/staging/src/k8s.io/apimachinery v0.0.0-20260209193319-41c4e9ba94f4 h1:YUbCh9pa96tgm8mooP4XjVYVfScSKAZ2enPJKKJIXGE= +github.com/openshift/kubernetes/staging/src/k8s.io/apimachinery v0.0.0-20260209193319-41c4e9ba94f4/go.mod h1:IhHRRF080N9VU1QEEJ5zTYAQkPElZ84OH08nPyo0Lw0= +github.com/openshift/kubernetes/staging/src/k8s.io/apiserver v0.0.0-20260209193319-41c4e9ba94f4 h1:D4eru3FuvnSnfaJlBimYAKn2W6Pfh6wT8o+4kr51a8k= +github.com/openshift/kubernetes/staging/src/k8s.io/apiserver v0.0.0-20260209193319-41c4e9ba94f4/go.mod h1:ZYWA2/evHEuXvUnJH5hOqr+GtEVJ/nx9RSp79j5UoOM= +github.com/openshift/kubernetes/staging/src/k8s.io/cli-runtime v0.0.0-20260209193319-41c4e9ba94f4 h1:Rh/5eiP6hKC+8HlaBhSNVGevEPWeUSSMKDSNWWdqssg= +github.com/openshift/kubernetes/staging/src/k8s.io/cli-runtime v0.0.0-20260209193319-41c4e9ba94f4/go.mod h1:eq1ArtMJ3o/VUDn7NTP/eryQG8pTGjtattESXd5g42U= +github.com/openshift/kubernetes/staging/src/k8s.io/client-go v0.0.0-20260209193319-41c4e9ba94f4 h1:CV2ZCkaS6FCMVAMeMxpKFmalKtsMsSn/0WlFKU1Xa9M= +github.com/openshift/kubernetes/staging/src/k8s.io/client-go v0.0.0-20260209193319-41c4e9ba94f4/go.mod h1:68E0AiovGRxyJ30s/QzLPLardQJCx/gm2GhdaAzJ10M= +github.com/openshift/kubernetes/staging/src/k8s.io/cloud-provider v0.0.0-20260209193319-41c4e9ba94f4 h1:qnnHj3Oa967dgcYQm/m+OjJ7fx6xZiqFIDWJj1MKDuM= +github.com/openshift/kubernetes/staging/src/k8s.io/cloud-provider v0.0.0-20260209193319-41c4e9ba94f4/go.mod h1:BMxEHFgDwf6lIiU/WFf9JaKhPjqKY2C3KPRaEF981TE= +github.com/openshift/kubernetes/staging/src/k8s.io/cluster-bootstrap v0.0.0-20260209193319-41c4e9ba94f4 h1:Owu6WkFsO9dWEBpDe3uRNgb6EtlAZp2qtAgfrcroW5A= +github.com/openshift/kubernetes/staging/src/k8s.io/cluster-bootstrap v0.0.0-20260209193319-41c4e9ba94f4/go.mod h1:NMIqLZ1bjJKn/OxQs/urOq9Mo7o4Z9SgaEkDi8r0iDQ= +github.com/openshift/kubernetes/staging/src/k8s.io/component-base v0.0.0-20260209193319-41c4e9ba94f4 h1:XgnZkxZ5bDinlaRkuqKokAOYOhuGFVK6wtrowPoK8VA= +github.com/openshift/kubernetes/staging/src/k8s.io/component-base v0.0.0-20260209193319-41c4e9ba94f4/go.mod h1:3b4Iqz886KuvrA4U8pXcWoOPZh+fHh04LF28btXScbw= +github.com/openshift/kubernetes/staging/src/k8s.io/component-helpers v0.0.0-20260209193319-41c4e9ba94f4 h1:391p2cmQT56Cx6IIrzNGrESDWCXhwIky2Sjm3yV84Lg= +github.com/openshift/kubernetes/staging/src/k8s.io/component-helpers v0.0.0-20260209193319-41c4e9ba94f4/go.mod h1:Ogwj8/aLf37gUsRvZD1mAbSYWGxDAvc5RlO1c0PtjJY= +github.com/openshift/kubernetes/staging/src/k8s.io/controller-manager v0.0.0-20260209193319-41c4e9ba94f4 h1:9jU8yMEWRRSGOGJhGOg+bTrAlSgWdZS8uyTvwOG564w= +github.com/openshift/kubernetes/staging/src/k8s.io/controller-manager v0.0.0-20260209193319-41c4e9ba94f4/go.mod h1:lP4RyYBciOkhbVCTb5MbSN0/GOauZTwGgpbTkwb7kEw= +github.com/openshift/kubernetes/staging/src/k8s.io/cri-api v0.0.0-20260209193319-41c4e9ba94f4 h1:xNMBGiSxhaHb0mosk7SeolOkwe52ciN+PWefiy2zvTc= +github.com/openshift/kubernetes/staging/src/k8s.io/cri-api v0.0.0-20260209193319-41c4e9ba94f4/go.mod h1:9Tgle7RkZOzgRM2VCSvvXZZjsQqOC6dxLtYy6BF+5PE= +github.com/openshift/kubernetes/staging/src/k8s.io/csi-translation-lib v0.0.0-20260209193319-41c4e9ba94f4 h1:WTXrX21x7OTEEgieK+SQ5/aiFOGYDkyDmJDkGh3fas8= +github.com/openshift/kubernetes/staging/src/k8s.io/csi-translation-lib v0.0.0-20260209193319-41c4e9ba94f4/go.mod h1:bKXDOUmiy/juOoPYsnxt3RbUKZKx+LFKsfCZw8nxsos= +github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation v0.0.0-20260209193319-41c4e9ba94f4 h1:CPwP7fUcNCS6nHXJYIvtoLI4iX/Y/3ySmVi+iJqfg14= +github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation v0.0.0-20260209193319-41c4e9ba94f4/go.mod h1:ia6wL8kICRq0a6Zj2idep1RncpGA/8/qdTbL5rYqxz0= +github.com/openshift/kubernetes/staging/src/k8s.io/kube-aggregator v0.0.0-20260209193319-41c4e9ba94f4 h1:azwR73vCftL5Af/pNsEMBgT4D58RQpwkjuKtJK+B/JU= +github.com/openshift/kubernetes/staging/src/k8s.io/kube-aggregator v0.0.0-20260209193319-41c4e9ba94f4/go.mod h1:qU9xk9626BLArUnM067MnuYDKCp5yy1PZypQg5VFN1U= +github.com/openshift/kubernetes/staging/src/k8s.io/kube-scheduler v0.0.0-20260209193319-41c4e9ba94f4 h1:pS8lP2jGiDuTwPbKOOmwaVtomn8IwWXDJWNZCVRrKN0= +github.com/openshift/kubernetes/staging/src/k8s.io/kube-scheduler v0.0.0-20260209193319-41c4e9ba94f4/go.mod h1:iCnLhShFPbA6+0cBJHMIC8osA4ukveEZbQweXjn+oXo= +github.com/openshift/kubernetes/staging/src/k8s.io/kubectl v0.0.0-20260209193319-41c4e9ba94f4 h1:9pJfomCLxJGVzWvwZerupO5t0BL6J2XBNO9aQlCeYQo= +github.com/openshift/kubernetes/staging/src/k8s.io/kubectl v0.0.0-20260209193319-41c4e9ba94f4/go.mod h1:L0N5ONv4vn8oIGy8gjX0ZzkLT7GLQxP2G9R2+K/osEM= +github.com/openshift/kubernetes/staging/src/k8s.io/kubelet v0.0.0-20260209193319-41c4e9ba94f4 h1:YPOBo+Juzmy18uXtCcHXq3XlaJG0HiaS09Y0ROjX5wc= +github.com/openshift/kubernetes/staging/src/k8s.io/kubelet v0.0.0-20260209193319-41c4e9ba94f4/go.mod h1:KvraWPlwZlgVhDnR3yjrAQTIPAk2Qia7iA6f7MWmZ6k= +github.com/openshift/kubernetes/staging/src/k8s.io/legacy-cloud-providers v0.0.0-20260209193319-41c4e9ba94f4 h1:32P5WN9bbVPfwVJBdK7izaDfKGukN6QqVCOm9YP1N9g= +github.com/openshift/kubernetes/staging/src/k8s.io/legacy-cloud-providers v0.0.0-20260209193319-41c4e9ba94f4/go.mod h1:W4g9/bUJ1/X01jOJGx395Ob4wKV2R58OrGvDhVdZSjw= +github.com/openshift/kubernetes/staging/src/k8s.io/metrics v0.0.0-20260209193319-41c4e9ba94f4 h1:dU6OAanZMgQ+O6kGLzZiSs7yRr48vldu1TvAuxS/Nvs= +github.com/openshift/kubernetes/staging/src/k8s.io/metrics v0.0.0-20260209193319-41c4e9ba94f4/go.mod h1:wcQC0ObNu0HtMRBaJJL6OJgg+DzcrdgW9ek5i7AncbE= +github.com/openshift/kubernetes/staging/src/k8s.io/mount-utils v0.0.0-20260209193319-41c4e9ba94f4 h1:7XRXlcggwNbs0oTz/hlXePAeYx/00c34JkoTnrItRsI= +github.com/openshift/kubernetes/staging/src/k8s.io/mount-utils v0.0.0-20260209193319-41c4e9ba94f4/go.mod h1:4KmkE88Y4LDYrotr6iqMrolXDcWWY7UqmroXTO/sxFw= +github.com/openshift/kubernetes/staging/src/k8s.io/pod-security-admission v0.0.0-20260209193319-41c4e9ba94f4 h1:HEH9pIrRnXbi7pl/He9wRTWFU7vy92rP+gVm1sDwCeY= +github.com/openshift/kubernetes/staging/src/k8s.io/pod-security-admission v0.0.0-20260209193319-41c4e9ba94f4/go.mod h1:nEqWuQNrBxCIeYnc9zWoV3/SW5Lhtrn7vvugEFVk88o= +github.com/openshift/kubernetes/staging/src/k8s.io/sample-apiserver v0.0.0-20260209193319-41c4e9ba94f4 h1:ndQnqwzjvfWf1x0uVRy9tsvLzlJ1TjmEwZeR3SgRaAU= +github.com/openshift/kubernetes/staging/src/k8s.io/sample-apiserver v0.0.0-20260209193319-41c4e9ba94f4/go.mod h1:DRthJqxCPFs1oAAJEF0tyou7kJ+LlNASc7P8YqKSBC8= github.com/openshift/library-go v0.0.0-20240513090140-e22d25af5587 h1:eZ79/F6bhtqoY78KRRxp5G5yITTgVatMnj5J/cYDumI= github.com/openshift/library-go v0.0.0-20240513090140-e22d25af5587/go.mod h1:lFwyRj0XjUf25Da3Q00y+KuaxCWTJ6YzYPDX1+96nco= github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20231031162821-c5e24be53ea7 h1:ACi574W+KszWNNkWT+8xNY7NpvpoHA+EPOKLlHB4MiQ= diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go b/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go index 7a586b979a7d..30895012be2d 100644 --- a/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go +++ b/vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go @@ -69,8 +69,10 @@ import ( "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters" "k8s.io/apiserver/pkg/endpoints/metrics" apirequest "k8s.io/apiserver/pkg/endpoints/request" + "k8s.io/apiserver/pkg/features" "k8s.io/apiserver/pkg/registry/generic" genericfilters "k8s.io/apiserver/pkg/server/filters" + utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/apiserver/pkg/util/webhook" "k8s.io/apiserver/pkg/warning" "k8s.io/client-go/scale" @@ -826,6 +828,7 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd clusterScoped := crd.Spec.Scope == apiextensionsv1.ClusterScoped // CRDs explicitly do not support protobuf, but some objects returned by the API server do + streamingCollections := utilfeature.DefaultFeatureGate.Enabled(features.StreamingCollectionEncodingToJSON) negotiatedSerializer := unstructuredNegotiatedSerializer{ typer: typer, creator: creator, @@ -839,10 +842,11 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd MediaTypeType: "application", MediaTypeSubType: "json", EncodesAsText: true, - Serializer: json.NewSerializer(json.DefaultMetaFactory, creator, typer, false), - PrettySerializer: json.NewSerializer(json.DefaultMetaFactory, creator, typer, true), + Serializer: json.NewSerializerWithOptions(json.DefaultMetaFactory, creator, typer, json.SerializerOptions{StreamingCollectionsEncoding: streamingCollections}), + PrettySerializer: json.NewSerializerWithOptions(json.DefaultMetaFactory, creator, typer, json.SerializerOptions{Pretty: true}), StrictSerializer: json.NewSerializerWithOptions(json.DefaultMetaFactory, creator, typer, json.SerializerOptions{ - Strict: true, + Strict: true, + StreamingCollectionsEncoding: streamingCollections, }), StreamSerializer: &runtime.StreamSerializerInfo{ EncodesAsText: true, @@ -865,7 +869,9 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd MediaType: "application/vnd.kubernetes.protobuf", MediaTypeType: "application", MediaTypeSubType: "vnd.kubernetes.protobuf", - Serializer: protobuf.NewSerializer(creator, typer), + Serializer: protobuf.NewSerializerWithOptions(creator, typer, protobuf.SerializerOptions{ + StreamingCollectionsEncoding: utilfeature.DefaultFeatureGate.Enabled(features.StreamingCollectionEncodingToProtobuf), + }), StreamSerializer: &runtime.StreamSerializerInfo{ Serializer: protobuf.NewRawSerializer(creator, typer), Framer: protobuf.LengthDelimitedFramer, @@ -936,7 +942,15 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd scaleScope := *requestScopes[v.Name] scaleConverter := scale.NewScaleConverter() scaleScope.Subresource = "scale" - scaleScope.Serializer = serializer.NewCodecFactory(scaleConverter.Scheme()) + var opts []serializer.CodecFactoryOptionsMutator + if utilfeature.DefaultFeatureGate.Enabled(features.StreamingCollectionEncodingToJSON) { + opts = append(opts, serializer.WithStreamingCollectionEncodingToJSON()) + } + if utilfeature.DefaultFeatureGate.Enabled(features.StreamingCollectionEncodingToProtobuf) { + opts = append(opts, serializer.WithStreamingCollectionEncodingToProtobuf()) + } + scaleScope.Serializer = serializer.NewCodecFactory(scaleConverter.Scheme(), opts...) + scaleScope.Kind = autoscalingv1.SchemeGroupVersion.WithKind("Scale") scaleScope.Namer = handlers.ContextBasedNaming{ Namer: meta.NewAccessor(), diff --git a/vendor/k8s.io/apimachinery/pkg/api/meta/help.go b/vendor/k8s.io/apimachinery/pkg/api/meta/help.go index 1fdd32c4ba3e..468afd0e9ee0 100644 --- a/vendor/k8s.io/apimachinery/pkg/api/meta/help.go +++ b/vendor/k8s.io/apimachinery/pkg/api/meta/help.go @@ -221,6 +221,9 @@ func extractList(obj runtime.Object, allocNew bool) ([]runtime.Object, error) { if err != nil { return nil, err } + if items.IsNil() { + return nil, nil + } list := make([]runtime.Object, items.Len()) if len(list) == 0 { return list, nil diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/codec_factory.go b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/codec_factory.go index ff9820842046..e2fe9207042d 100644 --- a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/codec_factory.go +++ b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/codec_factory.go @@ -52,7 +52,7 @@ type serializerType struct { func newSerializersForScheme(scheme *runtime.Scheme, mf json.MetaFactory, options CodecFactoryOptions) []serializerType { jsonSerializer := json.NewSerializerWithOptions( mf, scheme, scheme, - json.SerializerOptions{Yaml: false, Pretty: false, Strict: options.Strict}, + json.SerializerOptions{Yaml: false, Pretty: false, Strict: options.Strict, StreamingCollectionsEncoding: options.StreamingCollectionsEncodingToJSON}, ) jsonSerializerType := serializerType{ AcceptContentTypes: []string{runtime.ContentTypeJSON}, @@ -73,7 +73,7 @@ func newSerializersForScheme(scheme *runtime.Scheme, mf json.MetaFactory, option strictJSONSerializer := json.NewSerializerWithOptions( mf, scheme, scheme, - json.SerializerOptions{Yaml: false, Pretty: false, Strict: true}, + json.SerializerOptions{Yaml: false, Pretty: false, Strict: true, StreamingCollectionsEncoding: options.StreamingCollectionsEncodingToJSON}, ) jsonSerializerType.StrictSerializer = strictJSONSerializer @@ -85,7 +85,10 @@ func newSerializersForScheme(scheme *runtime.Scheme, mf json.MetaFactory, option mf, scheme, scheme, json.SerializerOptions{Yaml: true, Pretty: false, Strict: true}, ) - protoSerializer := protobuf.NewSerializer(scheme, scheme) + protoSerializer := protobuf.NewSerializerWithOptions(scheme, scheme, protobuf.SerializerOptions{ + StreamingCollectionsEncoding: options.StreamingCollectionsEncodingToProtobuf, + }) + protoRawSerializer := protobuf.NewRawSerializer(scheme, scheme) serializers := []serializerType{ @@ -136,6 +139,9 @@ type CodecFactoryOptions struct { Strict bool // Pretty includes a pretty serializer along with the non-pretty one Pretty bool + + StreamingCollectionsEncodingToJSON bool + StreamingCollectionsEncodingToProtobuf bool } // CodecFactoryOptionsMutator takes a pointer to an options struct and then modifies it. @@ -162,6 +168,18 @@ func DisableStrict(options *CodecFactoryOptions) { options.Strict = false } +func WithStreamingCollectionEncodingToJSON() CodecFactoryOptionsMutator { + return func(options *CodecFactoryOptions) { + options.StreamingCollectionsEncodingToJSON = true + } +} + +func WithStreamingCollectionEncodingToProtobuf() CodecFactoryOptionsMutator { + return func(options *CodecFactoryOptions) { + options.StreamingCollectionsEncodingToProtobuf = true + } +} + // NewCodecFactory provides methods for retrieving serializers for the supported wire formats // and conversion wrappers to define preferred internal and external versions. In the future, // as the internal version is used less, callers may instead use a defaulting serializer and diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/collections.go b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/collections.go new file mode 100644 index 000000000000..63b4e5ccb5f5 --- /dev/null +++ b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/collections.go @@ -0,0 +1,231 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package json + +import ( + "encoding/json" + "fmt" + "io" + "sort" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/conversion" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" +) + +func streamEncodeCollections(obj runtime.Object, w io.Writer) (bool, error) { + list, ok := obj.(*unstructured.UnstructuredList) + if ok { + return true, streamingEncodeUnstructuredList(w, list) + } + if _, ok := obj.(json.Marshaler); ok { + return false, nil + } + typeMeta, listMeta, items, err := getListMeta(obj) + if err == nil { + return true, streamingEncodeList(w, typeMeta, listMeta, items) + } + return false, nil +} + +// getListMeta implements list extraction logic for json stream serialization. +// +// Reason for a custom logic instead of reusing accessors from meta package: +// * Validate json tags to prevent incompatibility with json standard package. +// * ListMetaAccessor doesn't distinguish empty from nil value. +// * TypeAccessort reparsing "apiVersion" and serializing it with "{group}/{version}" +func getListMeta(list runtime.Object) (metav1.TypeMeta, metav1.ListMeta, []runtime.Object, error) { + listValue, err := conversion.EnforcePtr(list) + if err != nil { + return metav1.TypeMeta{}, metav1.ListMeta{}, nil, err + } + listType := listValue.Type() + if listType.NumField() != 3 { + return metav1.TypeMeta{}, metav1.ListMeta{}, nil, fmt.Errorf("expected ListType to have 3 fields") + } + // TypeMeta + typeMeta, ok := listValue.Field(0).Interface().(metav1.TypeMeta) + if !ok { + return metav1.TypeMeta{}, metav1.ListMeta{}, nil, fmt.Errorf("expected TypeMeta field to have TypeMeta type") + } + if listType.Field(0).Tag.Get("json") != ",inline" { + return metav1.TypeMeta{}, metav1.ListMeta{}, nil, fmt.Errorf(`expected TypeMeta json field tag to be ",inline"`) + } + // ListMeta + listMeta, ok := listValue.Field(1).Interface().(metav1.ListMeta) + if !ok { + return metav1.TypeMeta{}, metav1.ListMeta{}, nil, fmt.Errorf("expected ListMeta field to have ListMeta type") + } + if listType.Field(1).Tag.Get("json") != "metadata,omitempty" { + return metav1.TypeMeta{}, metav1.ListMeta{}, nil, fmt.Errorf(`expected ListMeta json field tag to be "metadata,omitempty"`) + } + // Items + items, err := meta.ExtractList(list) + if err != nil { + return metav1.TypeMeta{}, metav1.ListMeta{}, nil, err + } + if listType.Field(2).Tag.Get("json") != "items" { + return metav1.TypeMeta{}, metav1.ListMeta{}, nil, fmt.Errorf(`expected Items json field tag to be "items"`) + } + return typeMeta, listMeta, items, nil +} + +func streamingEncodeList(w io.Writer, typeMeta metav1.TypeMeta, listMeta metav1.ListMeta, items []runtime.Object) error { + // Start + if _, err := w.Write([]byte(`{`)); err != nil { + return err + } + + // TypeMeta + if typeMeta.Kind != "" { + if err := encodeKeyValuePair(w, "kind", typeMeta.Kind, []byte(",")); err != nil { + return err + } + } + if typeMeta.APIVersion != "" { + if err := encodeKeyValuePair(w, "apiVersion", typeMeta.APIVersion, []byte(",")); err != nil { + return err + } + } + + // ListMeta + if err := encodeKeyValuePair(w, "metadata", listMeta, []byte(",")); err != nil { + return err + } + + // Items + if err := encodeItemsObjectSlice(w, items); err != nil { + return err + } + + // End + _, err := w.Write([]byte("}\n")) + return err +} + +func encodeItemsObjectSlice(w io.Writer, items []runtime.Object) (err error) { + if items == nil { + err := encodeKeyValuePair(w, "items", nil, nil) + return err + } + _, err = w.Write([]byte(`"items":[`)) + if err != nil { + return err + } + suffix := []byte(",") + for i, item := range items { + if i == len(items)-1 { + suffix = nil + } + err := encodeValue(w, item, suffix) + if err != nil { + return err + } + } + _, err = w.Write([]byte("]")) + if err != nil { + return err + } + return err +} + +func streamingEncodeUnstructuredList(w io.Writer, list *unstructured.UnstructuredList) error { + _, err := w.Write([]byte(`{`)) + if err != nil { + return err + } + keys := make([]string, 0, len(list.Object)) + for k := range list.Object { + keys = append(keys, k) + } + if _, exists := list.Object["items"]; !exists { + keys = append(keys, "items") + } + sort.Strings(keys) + + suffix := []byte(",") + for i, key := range keys { + if i == len(keys)-1 { + suffix = nil + } + if key == "items" { + err = encodeItemsUnstructuredSlice(w, list.Items, suffix) + } else { + err = encodeKeyValuePair(w, key, list.Object[key], suffix) + } + if err != nil { + return err + } + } + _, err = w.Write([]byte("}\n")) + return err +} + +func encodeItemsUnstructuredSlice(w io.Writer, items []unstructured.Unstructured, suffix []byte) (err error) { + _, err = w.Write([]byte(`"items":[`)) + if err != nil { + return err + } + comma := []byte(",") + for i, item := range items { + if i == len(items)-1 { + comma = nil + } + err := encodeValue(w, item.Object, comma) + if err != nil { + return err + } + } + _, err = w.Write([]byte("]")) + if err != nil { + return err + } + if len(suffix) > 0 { + _, err = w.Write(suffix) + } + return err +} + +func encodeKeyValuePair(w io.Writer, key string, value any, suffix []byte) (err error) { + err = encodeValue(w, key, []byte(":")) + if err != nil { + return err + } + err = encodeValue(w, value, suffix) + if err != nil { + return err + } + return err +} + +func encodeValue(w io.Writer, value any, suffix []byte) error { + data, err := json.Marshal(value) + if err != nil { + return err + } + _, err = w.Write(data) + if err != nil { + return err + } + if len(suffix) > 0 { + _, err = w.Write(suffix) + } + return err +} diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go index 1ae4a32eb720..24f66a10174b 100644 --- a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go +++ b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go @@ -36,7 +36,7 @@ import ( // is not nil, the object has the group, version, and kind fields set. // Deprecated: use NewSerializerWithOptions instead. func NewSerializer(meta MetaFactory, creater runtime.ObjectCreater, typer runtime.ObjectTyper, pretty bool) *Serializer { - return NewSerializerWithOptions(meta, creater, typer, SerializerOptions{false, pretty, false}) + return NewSerializerWithOptions(meta, creater, typer, SerializerOptions{false, pretty, false, false}) } // NewYAMLSerializer creates a YAML serializer that handles encoding versioned objects into the proper YAML form. If typer @@ -44,7 +44,7 @@ func NewSerializer(meta MetaFactory, creater runtime.ObjectCreater, typer runtim // matches JSON, and will error if constructs are used that do not serialize to JSON. // Deprecated: use NewSerializerWithOptions instead. func NewYAMLSerializer(meta MetaFactory, creater runtime.ObjectCreater, typer runtime.ObjectTyper) *Serializer { - return NewSerializerWithOptions(meta, creater, typer, SerializerOptions{true, false, false}) + return NewSerializerWithOptions(meta, creater, typer, SerializerOptions{true, false, false, false}) } // NewSerializerWithOptions creates a JSON/YAML serializer that handles encoding versioned objects into the proper JSON/YAML @@ -93,6 +93,9 @@ type SerializerOptions struct { // Strict: configures the Serializer to return strictDecodingError's when duplicate fields are present decoding JSON or YAML. // Note that enabling this option is not as performant as the non-strict variant, and should not be used in fast paths. Strict bool + + // StreamingCollectionsEncoding enables encoding collection, one item at the time, drastically reducing memory needed. + StreamingCollectionsEncoding bool } // Serializer handles encoding versioned objects into the proper JSON form @@ -242,6 +245,15 @@ func (s *Serializer) doEncode(obj runtime.Object, w io.Writer) error { _, err = w.Write(data) return err } + if s.options.StreamingCollectionsEncoding { + ok, err := streamEncodeCollections(obj, w) + if err != nil { + return err + } + if ok { + return nil + } + } encoder := json.NewEncoder(w) return encoder.Encode(obj) } diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf/collections.go b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf/collections.go new file mode 100644 index 000000000000..754a80820b06 --- /dev/null +++ b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf/collections.go @@ -0,0 +1,174 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package protobuf + +import ( + "errors" + "io" + "math/bits" + + "github.com/gogo/protobuf/proto" + + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/conversion" + "k8s.io/apimachinery/pkg/runtime" +) + +var ( + errFieldCount = errors.New("expected ListType to have 3 fields") + errTypeMetaField = errors.New("expected TypeMeta field to have TypeMeta type") + errTypeMetaProtobufTag = errors.New(`expected TypeMeta protobuf field tag to be ""`) + errListMetaField = errors.New("expected ListMeta field to have ListMeta type") + errListMetaProtobufTag = errors.New(`expected ListMeta protobuf field tag to be "bytes,1,opt,name=metadata"`) + errItemsProtobufTag = errors.New(`expected Items protobuf field tag to be "bytes,2,rep,name=items"`) + errItemsSizer = errors.New(`expected Items elements to implement proto.Sizer`) +) + +// getStreamingListData implements list extraction logic for protobuf stream serialization. +// +// Reason for a custom logic instead of reusing accessors from meta package: +// * Validate proto tags to prevent incompatibility with proto standard package. +// * ListMetaAccessor doesn't distinguish empty from nil value. +// * TypeAccessor reparsing "apiVersion" and serializing it with "{group}/{version}" +func getStreamingListData(list runtime.Object) (data streamingListData, err error) { + listValue, err := conversion.EnforcePtr(list) + if err != nil { + return data, err + } + listType := listValue.Type() + if listType.NumField() != 3 { + return data, errFieldCount + } + // TypeMeta: validated, but not returned as is not serialized. + _, ok := listValue.Field(0).Interface().(metav1.TypeMeta) + if !ok { + return data, errTypeMetaField + } + if listType.Field(0).Tag.Get("protobuf") != "" { + return data, errTypeMetaProtobufTag + } + // ListMeta + listMeta, ok := listValue.Field(1).Interface().(metav1.ListMeta) + if !ok { + return data, errListMetaField + } + // if we were ever to relax the protobuf tag check we should update the hardcoded `0xa` below when writing ListMeta. + if listType.Field(1).Tag.Get("protobuf") != "bytes,1,opt,name=metadata" { + return data, errListMetaProtobufTag + } + data.listMeta = listMeta + // Items; if we were ever to relax the protobuf tag check we should update the hardcoded `0x12` below when writing Items. + if listType.Field(2).Tag.Get("protobuf") != "bytes,2,rep,name=items" { + return data, errItemsProtobufTag + } + items, err := meta.ExtractList(list) + if err != nil { + return data, err + } + data.items = items + data.totalSize, data.listMetaSize, data.itemsSizes, err = listSize(listMeta, items) + return data, err +} + +type streamingListData struct { + // totalSize is the total size of the serialized List object, including their proto headers/size bytes + totalSize int + + // listMetaSize caches results from .Size() call to listMeta, doesn't include header bytes (field identifier, size) + listMetaSize int + listMeta metav1.ListMeta + + // itemsSizes caches results from .Size() call to items, doesn't include header bytes (field identifier, size) + itemsSizes []int + items []runtime.Object +} + +// listSize return size of ListMeta and items to be later used for preallocations. +// listMetaSize and itemSizes do not include header bytes (field identifier, size). +func listSize(listMeta metav1.ListMeta, items []runtime.Object) (totalSize, listMetaSize int, itemSizes []int, err error) { + // ListMeta + listMetaSize = listMeta.Size() + totalSize += 1 + sovGenerated(uint64(listMetaSize)) + listMetaSize + // Items + itemSizes = make([]int, len(items)) + for i, item := range items { + sizer, ok := item.(proto.Sizer) + if !ok { + return totalSize, listMetaSize, nil, errItemsSizer + } + n := sizer.Size() + itemSizes[i] = n + totalSize += 1 + sovGenerated(uint64(n)) + n + } + return totalSize, listMetaSize, itemSizes, nil +} + +func streamingEncodeUnknownList(w io.Writer, unk runtime.Unknown, listData streamingListData, memAlloc runtime.MemoryAllocator) error { + _, err := w.Write(protoEncodingPrefix) + if err != nil { + return err + } + // encodeList is responsible for encoding the List into the unknown Raw. + encodeList := func(writer io.Writer) (int, error) { + return streamingEncodeList(writer, listData, memAlloc) + } + _, err = unk.MarshalToWriter(w, listData.totalSize, encodeList) + return err +} + +func streamingEncodeList(w io.Writer, listData streamingListData, memAlloc runtime.MemoryAllocator) (size int, err error) { + // ListMeta; 0xa = (1 << 3) | 2; field number: 1, type: 2 (LEN). https://protobuf.dev/programming-guides/encoding/#structure + n, err := doEncodeWithHeader(&listData.listMeta, w, 0xa, listData.listMetaSize, memAlloc) + size += n + if err != nil { + return size, err + } + // Items; 0x12 = (2 << 3) | 2; field number: 2, type: 2 (LEN). https://protobuf.dev/programming-guides/encoding/#structure + for i, item := range listData.items { + n, err := doEncodeWithHeader(item, w, 0x12, listData.itemsSizes[i], memAlloc) + size += n + if err != nil { + return size, err + } + } + return size, nil +} + +func writeVarintGenerated(w io.Writer, v int) (int, error) { + buf := make([]byte, sovGenerated(uint64(v))) + encodeVarintGenerated(buf, len(buf), uint64(v)) + return w.Write(buf) +} + +// sovGenerated is copied from `generated.pb.go` returns size of varint. +func sovGenerated(v uint64) int { + return (bits.Len64(v|1) + 6) / 7 +} + +// encodeVarintGenerated is copied from `generated.pb.go` encodes varint. +func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int { + offset -= sovGenerated(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf/protobuf.go b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf/protobuf.go index c63e6dc63f6b..c66c49ac4c2d 100644 --- a/vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf/protobuf.go +++ b/vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf/protobuf.go @@ -72,10 +72,18 @@ func IsNotMarshalable(err error) bool { // is passed, the encoded object will have group, version, and kind fields set. If typer is nil, the objects will be written // as-is (any type info passed with the object will be used). func NewSerializer(creater runtime.ObjectCreater, typer runtime.ObjectTyper) *Serializer { + return NewSerializerWithOptions(creater, typer, SerializerOptions{}) +} + +// NewSerializerWithOptions creates a Protobuf serializer that handles encoding versioned objects into the proper wire form. If a typer +// is passed, the encoded object will have group, version, and kind fields set. If typer is nil, the objects will be written +// as-is (any type info passed with the object will be used). +func NewSerializerWithOptions(creater runtime.ObjectCreater, typer runtime.ObjectTyper, opts SerializerOptions) *Serializer { return &Serializer{ prefix: protoEncodingPrefix, creater: creater, typer: typer, + options: opts, } } @@ -84,6 +92,14 @@ type Serializer struct { prefix []byte creater runtime.ObjectCreater typer runtime.ObjectTyper + + options SerializerOptions +} + +// SerializerOptions holds the options which are used to configure a Proto serializer. +type SerializerOptions struct { + // StreamingCollectionsEncoding enables encoding collection, one item at the time, drastically reducing memory needed. + StreamingCollectionsEncoding bool } var _ runtime.Serializer = &Serializer{} @@ -209,6 +225,13 @@ func (s *Serializer) doEncode(obj runtime.Object, w io.Writer, memAlloc runtime. }, } } + if s.options.StreamingCollectionsEncoding { + listData, err := getStreamingListData(obj) + if err == nil { + // Doesn't honor custom proto marshaling methods (like json streaming), because all proto objects implement proto methods. + return streamingEncodeUnknownList(w, unk, listData, memAlloc) + } + } switch t := obj.(type) { case bufferedMarshaller: @@ -428,6 +451,39 @@ func (s *RawSerializer) encode(obj runtime.Object, w io.Writer, memAlloc runtime } func (s *RawSerializer) doEncode(obj runtime.Object, w io.Writer, memAlloc runtime.MemoryAllocator) error { + _, err := doEncode(obj, w, nil, memAlloc) + return err +} + +func doEncodeWithHeader(obj any, w io.Writer, field byte, precomputedSize int, memAlloc runtime.MemoryAllocator) (size int, err error) { + // Field identifier + n, err := w.Write([]byte{field}) + size += n + if err != nil { + return size, err + } + // Size + n, err = writeVarintGenerated(w, precomputedSize) + size += n + if err != nil { + return size, err + } + // Obj + n, err = doEncode(obj, w, &precomputedSize, memAlloc) + size += n + if err != nil { + return size, err + } + if n != precomputedSize { + return size, fmt.Errorf("the size value was %d, but doEncode wrote %d bytes to data", precomputedSize, n) + } + return size, nil +} + +// doEncode encodes provided object into writer using a allocator if possible. +// Avoids call by object Size if precomputedObjSize is provided. +// precomputedObjSize should not include header bytes (field identifier, size). +func doEncode(obj any, w io.Writer, precomputedObjSize *int, memAlloc runtime.MemoryAllocator) (int, error) { if memAlloc == nil { klog.Error("a mandatory memory allocator wasn't provided, this might have a negative impact on performance, check invocations of EncodeWithAllocator method, falling back on runtime.SimpleAllocator") memAlloc = &runtime.SimpleAllocator{} @@ -436,40 +492,43 @@ func (s *RawSerializer) doEncode(obj runtime.Object, w io.Writer, memAlloc runti case bufferedReverseMarshaller: // this path performs a single allocation during write only when the Allocator wasn't provided // it also requires the caller to implement the more efficient Size and MarshalToSizedBuffer methods - encodedSize := uint64(t.Size()) - data := memAlloc.Allocate(encodedSize) + if precomputedObjSize == nil { + s := t.Size() + precomputedObjSize = &s + } + data := memAlloc.Allocate(uint64(*precomputedObjSize)) n, err := t.MarshalToSizedBuffer(data) if err != nil { - return err + return 0, err } - _, err = w.Write(data[:n]) - return err + return w.Write(data[:n]) case bufferedMarshaller: // this path performs a single allocation during write only when the Allocator wasn't provided // it also requires the caller to implement the more efficient Size and MarshalTo methods - encodedSize := uint64(t.Size()) - data := memAlloc.Allocate(encodedSize) + if precomputedObjSize == nil { + s := t.Size() + precomputedObjSize = &s + } + data := memAlloc.Allocate(uint64(*precomputedObjSize)) n, err := t.MarshalTo(data) if err != nil { - return err + return 0, err } - _, err = w.Write(data[:n]) - return err + return w.Write(data[:n]) case proto.Marshaler: // this path performs extra allocations data, err := t.Marshal() if err != nil { - return err + return 0, err } - _, err = w.Write(data) - return err + return w.Write(data) default: - return errNotMarshalable{reflect.TypeOf(obj)} + return 0, errNotMarshalable{reflect.TypeOf(obj)} } } diff --git a/vendor/k8s.io/apimachinery/pkg/runtime/types_proto.go b/vendor/k8s.io/apimachinery/pkg/runtime/types_proto.go index a82227b239af..27a2064c4163 100644 --- a/vendor/k8s.io/apimachinery/pkg/runtime/types_proto.go +++ b/vendor/k8s.io/apimachinery/pkg/runtime/types_proto.go @@ -18,6 +18,7 @@ package runtime import ( "fmt" + "io" ) type ProtobufMarshaller interface { @@ -28,6 +29,124 @@ type ProtobufReverseMarshaller interface { MarshalToSizedBuffer(data []byte) (int, error) } +const ( + typeMetaTag = 0xa + rawTag = 0x12 + contentEncodingTag = 0x1a + contentTypeTag = 0x22 + + // max length of a varint for a uint64 + maxUint64VarIntLength = 10 +) + +// MarshalToWriter allows a caller to provide a streaming writer for raw bytes, +// instead of populating them inside the Unknown struct. +// rawSize is the number of bytes rawWriter will write in a success case. +// writeRaw is called when it is time to write the raw bytes. It must return `rawSize, nil` or an error. +func (m *Unknown) MarshalToWriter(w io.Writer, rawSize int, writeRaw func(io.Writer) (int, error)) (int, error) { + size := 0 + + // reuse the buffer for varint marshaling + varintBuffer := make([]byte, maxUint64VarIntLength) + writeVarint := func(i int) (int, error) { + offset := encodeVarintGenerated(varintBuffer, len(varintBuffer), uint64(i)) + return w.Write(varintBuffer[offset:]) + } + + // TypeMeta + { + n, err := w.Write([]byte{typeMetaTag}) + size += n + if err != nil { + return size, err + } + + typeMetaBytes, err := m.TypeMeta.Marshal() + if err != nil { + return size, err + } + + n, err = writeVarint(len(typeMetaBytes)) + size += n + if err != nil { + return size, err + } + + n, err = w.Write(typeMetaBytes) + size += n + if err != nil { + return size, err + } + } + + // Raw, delegating write to writeRaw() + { + n, err := w.Write([]byte{rawTag}) + size += n + if err != nil { + return size, err + } + + n, err = writeVarint(rawSize) + size += n + if err != nil { + return size, err + } + + n, err = writeRaw(w) + size += n + if err != nil { + return size, err + } + if n != int(rawSize) { + return size, fmt.Errorf("the size value was %d, but encoding wrote %d bytes to data", rawSize, n) + } + } + + // ContentEncoding + { + n, err := w.Write([]byte{contentEncodingTag}) + size += n + if err != nil { + return size, err + } + + n, err = writeVarint(len(m.ContentEncoding)) + size += n + if err != nil { + return size, err + } + + n, err = w.Write([]byte(m.ContentEncoding)) + size += n + if err != nil { + return size, err + } + } + + // ContentEncoding + { + n, err := w.Write([]byte{contentTypeTag}) + size += n + if err != nil { + return size, err + } + + n, err = writeVarint(len(m.ContentType)) + size += n + if err != nil { + return size, err + } + + n, err = w.Write([]byte(m.ContentType)) + size += n + if err != nil { + return size, err + } + } + return size, nil +} + // NestedMarshalTo allows a caller to avoid extra allocations during serialization of an Unknown // that will contain an object that implements ProtobufMarshaller or ProtobufReverseMarshaller. func (m *Unknown) NestedMarshalTo(data []byte, b ProtobufMarshaller, size uint64) (int, error) { @@ -43,12 +162,12 @@ func (m *Unknown) NestedMarshalTo(data []byte, b ProtobufMarshaller, size uint64 copy(data[i:], m.ContentType) i = encodeVarintGenerated(data, i, uint64(len(m.ContentType))) i-- - data[i] = 0x22 + data[i] = contentTypeTag i -= len(m.ContentEncoding) copy(data[i:], m.ContentEncoding) i = encodeVarintGenerated(data, i, uint64(len(m.ContentEncoding))) i-- - data[i] = 0x1a + data[i] = contentEncodingTag if b != nil { if r, ok := b.(ProtobufReverseMarshaller); ok { n1, err := r.MarshalToSizedBuffer(data[:i]) @@ -75,7 +194,7 @@ func (m *Unknown) NestedMarshalTo(data []byte, b ProtobufMarshaller, size uint64 } i = encodeVarintGenerated(data, i, size) i-- - data[i] = 0x12 + data[i] = rawTag } n2, err := m.TypeMeta.MarshalToSizedBuffer(data[:i]) if err != nil { @@ -84,6 +203,6 @@ func (m *Unknown) NestedMarshalTo(data []byte, b ProtobufMarshaller, size uint64 i -= n2 i = encodeVarintGenerated(data, i, uint64(n2)) i-- - data[i] = 0xa + data[i] = typeMetaTag return msgSize - i, nil } diff --git a/vendor/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/writers.go b/vendor/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/writers.go index acd8f0357aaf..e6f566aa3a32 100644 --- a/vendor/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/writers.go +++ b/vendor/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/writers.go @@ -156,6 +156,9 @@ const ( // (usually the entire object), and if the size is smaller no gzipping will be performed // if the client requests it. defaultGzipThresholdBytes = 128 * 1024 + // Use the length of the first write to recognize streaming implementations. + // When streaming JSON first write is "{", while Kubernetes protobuf starts unique 4 byte header. + firstWriteStreamingThresholdBytes = 4 ) // negotiateContentEncoding returns a supported client-requested content encoding for the @@ -191,14 +194,53 @@ type deferredResponseWriter struct { statusCode int contentEncoding string - hasWritten bool - hw http.ResponseWriter - w io.Writer + hasBuffered bool + buffer []byte + hasWritten bool + hw http.ResponseWriter + w io.Writer ctx context.Context } func (w *deferredResponseWriter) Write(p []byte) (n int, err error) { + switch { + case w.hasWritten: + // already written, cannot buffer + return w.unbufferedWrite(p) + + case w.contentEncoding != "gzip": + // non-gzip, no need to buffer + return w.unbufferedWrite(p) + + case !w.hasBuffered && len(p) > defaultGzipThresholdBytes: + // not yet buffered, first write is long enough to trigger gzip, no need to buffer + return w.unbufferedWrite(p) + + case !w.hasBuffered && len(p) > firstWriteStreamingThresholdBytes: + // not yet buffered, first write is longer than expected for streaming scenarios that would require buffering, no need to buffer + return w.unbufferedWrite(p) + + default: + if !w.hasBuffered { + w.hasBuffered = true + // Start at 80 bytes to avoid rapid reallocation of the buffer. + // The minimum size of a 0-item serialized list object is 80 bytes: + // {"kind":"List","apiVersion":"v1","metadata":{"resourceVersion":"1"},"items":[]}\n + w.buffer = make([]byte, 0, max(80, len(p))) + } + w.buffer = append(w.buffer, p...) + var err error + if len(w.buffer) > defaultGzipThresholdBytes { + // we've accumulated enough to trigger gzip, write and clear buffer + _, err = w.unbufferedWrite(w.buffer) + w.buffer = nil + } + return len(p), err + } +} + +func (w *deferredResponseWriter) unbufferedWrite(p []byte) (n int, err error) { ctx := w.ctx span := tracing.SpanFromContext(ctx) // This Step usually wraps in-memory object serialization. @@ -244,11 +286,17 @@ func (w *deferredResponseWriter) Write(p []byte) (n int, err error) { return w.w.Write(p) } -func (w *deferredResponseWriter) Close() error { +func (w *deferredResponseWriter) Close() (err error) { if !w.hasWritten { - return nil + if !w.hasBuffered { + return nil + } + // never reached defaultGzipThresholdBytes, no need to do the gzip writer cleanup + _, err := w.unbufferedWrite(w.buffer) + w.buffer = nil + return err } - var err error + switch t := w.w.(type) { case *gzip.Writer: err = t.Close() diff --git a/vendor/k8s.io/apiserver/pkg/features/kube_features.go b/vendor/k8s.io/apiserver/pkg/features/kube_features.go index e524e0c6474c..da0d0cb693b9 100644 --- a/vendor/k8s.io/apiserver/pkg/features/kube_features.go +++ b/vendor/k8s.io/apiserver/pkg/features/kube_features.go @@ -218,6 +218,14 @@ const ( // document. StorageVersionHash featuregate.Feature = "StorageVersionHash" + // owner: @serathius + // Allow API server JSON encoder to encode collections item by item, instead of all at once. + StreamingCollectionEncodingToJSON featuregate.Feature = "StreamingCollectionEncodingToJSON" + + // owner: @serathius + // Allow API server Protobuf encoder to encode collections item by item, instead of all at once. + StreamingCollectionEncodingToProtobuf featuregate.Feature = "StreamingCollectionEncodingToProtobuf" + // owner: @aramase, @enj, @nabokihms // kep: https://kep.k8s.io/3331 // alpha: v1.29 @@ -326,6 +334,10 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS StorageVersionHash: {Default: true, PreRelease: featuregate.Beta}, + StreamingCollectionEncodingToJSON: {Default: false, PreRelease: featuregate.Beta}, + + StreamingCollectionEncodingToProtobuf: {Default: false, PreRelease: featuregate.Beta}, + StructuredAuthenticationConfiguration: {Default: false, PreRelease: featuregate.Alpha}, StructuredAuthorizationConfiguration: {Default: false, PreRelease: featuregate.Alpha}, diff --git a/vendor/k8s.io/apiserver/pkg/server/genericapiserver.go b/vendor/k8s.io/apiserver/pkg/server/genericapiserver.go index 4b1ca5947129..79ee3f900be2 100644 --- a/vendor/k8s.io/apiserver/pkg/server/genericapiserver.go +++ b/vendor/k8s.io/apiserver/pkg/server/genericapiserver.go @@ -979,6 +979,17 @@ func (s *GenericAPIServer) newAPIGroupVersion(apiGroupInfo *APIGroupInfo, groupV // NewDefaultAPIGroupInfo returns an APIGroupInfo stubbed with "normal" values // exposed for easier composition from other packages func NewDefaultAPIGroupInfo(group string, scheme *runtime.Scheme, parameterCodec runtime.ParameterCodec, codecs serializer.CodecFactory) APIGroupInfo { + opts := []serializer.CodecFactoryOptionsMutator{} + if utilfeature.DefaultFeatureGate.Enabled(features.StreamingCollectionEncodingToJSON) { + opts = append(opts, serializer.WithStreamingCollectionEncodingToJSON()) + } + if utilfeature.DefaultFeatureGate.Enabled(features.StreamingCollectionEncodingToProtobuf) { + opts = append(opts, serializer.WithStreamingCollectionEncodingToProtobuf()) + } + if len(opts) != 0 { + codecs = serializer.NewCodecFactory(scheme, opts...) + } + return APIGroupInfo{ PrioritizedVersions: scheme.PrioritizedVersionsForGroup(group), VersionedResourcesStorageMap: map[string]map[string]rest.Storage{}, diff --git a/vendor/k8s.io/apiserver/pkg/storage/etcd3/etcd3retry/retry_etcdclient.go b/vendor/k8s.io/apiserver/pkg/storage/etcd3/etcd3retry/retry_etcdclient.go index 12bd733f3d70..7644563fff78 100644 --- a/vendor/k8s.io/apiserver/pkg/storage/etcd3/etcd3retry/retry_etcdclient.go +++ b/vendor/k8s.io/apiserver/pkg/storage/etcd3/etcd3retry/retry_etcdclient.go @@ -2,6 +2,9 @@ package etcd3retry import ( "context" + "fmt" + "regexp" + "strings" "time" etcdrpc "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" @@ -36,7 +39,7 @@ func NewRetryingEtcdStorage(delegate storage.Interface) storage.Interface { // in seconds (0 means forever). If no error is returned and out is not nil, out will be // set to the read value from database. func (c *retryClient) Create(ctx context.Context, key string, obj, out runtime.Object, ttl uint64) error { - return onError(ctx, defaultRetry, isRetriableEtcdError, func() error { + return onError(ctx, defaultRetry, isRetriableErrorOnWrite, func() error { return c.Interface.Create(ctx, key, obj, out, ttl) }) } @@ -44,7 +47,7 @@ func (c *retryClient) Create(ctx context.Context, key string, obj, out runtime.O // Delete removes the specified key and returns the value that existed at that spot. // If key didn't exist, it will return NotFound storage error. func (c *retryClient) Delete(ctx context.Context, key string, out runtime.Object, preconditions *storage.Preconditions, validateDeletion storage.ValidateObjectFunc, cachedExistingObject runtime.Object) error { - return onError(ctx, defaultRetry, isRetriableEtcdError, func() error { + return onError(ctx, defaultRetry, isRetriableErrorOnWrite, func() error { return c.Interface.Delete(ctx, key, out, preconditions, validateDeletion, cachedExistingObject) }) } @@ -58,7 +61,7 @@ func (c *retryClient) Delete(ctx context.Context, key string, out runtime.Object // and send it in an "ADDED" event, before watch starts. func (c *retryClient) Watch(ctx context.Context, key string, opts storage.ListOptions) (watch.Interface, error) { var ret watch.Interface - err := onError(ctx, defaultRetry, isRetriableEtcdError, func() error { + err := onError(ctx, defaultRetry, isRetriableErrorOnRead, func() error { var innerErr error ret, innerErr = c.Interface.Watch(ctx, key, opts) return innerErr @@ -72,7 +75,7 @@ func (c *retryClient) Watch(ctx context.Context, key string, opts storage.ListOp // The returned contents may be delayed, but it is guaranteed that they will // match 'opts.ResourceVersion' according 'opts.ResourceVersionMatch'. func (c *retryClient) Get(ctx context.Context, key string, opts storage.GetOptions, objPtr runtime.Object) error { - return onError(ctx, defaultRetry, isRetriableEtcdError, func() error { + return onError(ctx, defaultRetry, isRetriableErrorOnRead, func() error { return c.Interface.Get(ctx, key, opts, objPtr) }) } @@ -84,7 +87,7 @@ func (c *retryClient) Get(ctx context.Context, key string, opts storage.GetOptio // The returned contents may be delayed, but it is guaranteed that they will // match 'opts.ResourceVersion' according 'opts.ResourceVersionMatch'. func (c *retryClient) GetList(ctx context.Context, key string, opts storage.ListOptions, listObj runtime.Object) error { - return onError(ctx, defaultRetry, isRetriableEtcdError, func() error { + return onError(ctx, defaultRetry, isRetriableErrorOnRead, func() error { return c.Interface.GetList(ctx, key, opts, listObj) }) } @@ -125,23 +128,65 @@ func (c *retryClient) GetList(ctx context.Context, key string, opts storage.List // ) func (c *retryClient) GuaranteedUpdate(ctx context.Context, key string, destination runtime.Object, ignoreNotFound bool, preconditions *storage.Preconditions, tryUpdate storage.UpdateFunc, cachedExistingObject runtime.Object) error { - return onError(ctx, defaultRetry, isRetriableEtcdError, func() error { + return onError(ctx, defaultRetry, isRetriableErrorOnWrite, func() error { return c.Interface.GuaranteedUpdate(ctx, key, destination, ignoreNotFound, preconditions, tryUpdate, cachedExistingObject) }) } -// isRetriableEtcdError returns true if a retry should be attempted, otherwise false. -// errorLabel is set to a non-empty value that reflects the type of error encountered. -func isRetriableEtcdError(err error) (errorLabel string, retry bool) { - if err != nil { - if etcdError, ok := etcdrpc.Error(err).(etcdrpc.EtcdError); ok { - if etcdError.Code() == codes.Unavailable { - errorLabel = "Unavailable" - retry = true - } - } +// These errors are coming back from the k8s.io/apiserver storage.Interface, not directly from an +// etcd client. Classifying them can be fragile since the storage methods may not return etcd client +// errors directly. +var errorLabelsBySuffix = map[string]string{ + "etcdserver: leader changed": "LeaderChanged", + "etcdserver: no leader": "NoLeader", + "raft proposal dropped": "ProposalDropped", + + "etcdserver: request timed out": "Timeout", + "etcdserver: request timed out, possibly due to previous leader failure": "Timeout", + "etcdserver: request timed out, possible due to connection lost": "Timeout", + "etcdserver: request timed out, waiting for the applied index took too long": "Timeout", + "etcdserver: server stopped": "Stopped", +} + +var retriableWriteErrorSuffixes = func() *regexp.Regexp { + // This list should include only errors the caller is certain have no side effects. + suffixes := []string{ + "etcdserver: leader changed", + "etcdserver: no leader", + "raft proposal dropped", + } + return regexp.MustCompile(fmt.Sprintf(`(%s)$`, strings.Join(suffixes, `|`))) +}() + +// isRetriableErrorOnWrite returns true if and only if a retry should be attempted when the provided +// error is returned from a write attempt. If the error is retriable, a non-empty string classifying +// the error is also returned. +func isRetriableErrorOnWrite(err error) (string, bool) { + if suffix := retriableWriteErrorSuffixes.FindString(err.Error()); suffix != "" { + return errorLabelsBySuffix[suffix], true + } + return "", false +} + +var retriableReadErrorSuffixes = func() *regexp.Regexp { + var suffixes []string + for suffix := range errorLabelsBySuffix { + suffixes = append(suffixes, suffix) + } + return regexp.MustCompile(fmt.Sprintf(`(%s)$`, strings.Join(suffixes, `|`))) +}() + +// isRetriableErrorOnRead returns true if and only if a retry should be attempted when the provided +// error is returned from a read attempt. If the error is retriable, a non-empty string classifying +// the error is also returned. +func isRetriableErrorOnRead(err error) (string, bool) { + if suffix := retriableReadErrorSuffixes.FindString(err.Error()); suffix != "" { + return errorLabelsBySuffix[suffix], true } - return + if etcdError, ok := etcdrpc.Error(err).(etcdrpc.EtcdError); ok && etcdError.Code() == codes.Unavailable { + return "Unavailable", true + } + return "", false } // onError allows the caller to retry fn in case the error returned by fn is retriable @@ -163,6 +208,9 @@ func onError(ctx context.Context, backoff wait.Backoff, retriable func(error) (s } lastErrLabel, retry = retriable(err) + if klog.V(6).Enabled() { + klog.V(6).InfoS("observed storage error", "err", err, "retriable", retry) + } if retry { lastErr = err retryCounter++ diff --git a/vendor/k8s.io/kubernetes/openshift-hack/e2e/annotate/generated/zz_generated.annotations.go b/vendor/k8s.io/kubernetes/openshift-hack/e2e/annotate/generated/zz_generated.annotations.go index aa7412ca0f0e..a3f253dbe415 100644 --- a/vendor/k8s.io/kubernetes/openshift-hack/e2e/annotate/generated/zz_generated.annotations.go +++ b/vendor/k8s.io/kubernetes/openshift-hack/e2e/annotate/generated/zz_generated.annotations.go @@ -14251,7 +14251,7 @@ var Annotations = map[string]string{ "[sig-storage] PersistentVolumes:vsphere [Feature:vsphere] should test that deleting the PV before the pod does not cause pod deletion to fail on vsphere volume detach": " [Disabled:Unsupported] [Suite:k8s]", - "[sig-storage] Pod Disks [Feature:StorageProvider] [Serial] attach on previously attached volumes should work": " [Skipped:NoOptionalCapabilities] [Suite:openshift/conformance/serial] [Suite:k8s]", + "[sig-storage] Pod Disks [Feature:StorageProvider] [Serial] attach on previously attached volumes should work": " [Disabled:Broken] [Skipped:NoOptionalCapabilities] [Suite:k8s]", "[sig-storage] Pod Disks [Feature:StorageProvider] detach in a disrupted environment [Slow] [Disruptive] when node's API object is deleted": " [Serial] [Skipped:NoOptionalCapabilities] [Suite:k8s]", diff --git a/vendor/k8s.io/kubernetes/openshift-hack/e2e/annotate/rules.go b/vendor/k8s.io/kubernetes/openshift-hack/e2e/annotate/rules.go index 91a59c700bd4..fb7e82dee113 100644 --- a/vendor/k8s.io/kubernetes/openshift-hack/e2e/annotate/rules.go +++ b/vendor/k8s.io/kubernetes/openshift-hack/e2e/annotate/rules.go @@ -143,6 +143,9 @@ var ( // https://issues.redhat.com/browse/OCPBUGS-36773 `\[sig-storage\] In-tree Volumes \[Driver: vsphere\] \[Testpattern: Pre-provisioned`, `\[sig-storage\] In-tree Volumes \[Driver: vsphere\] \[Testpattern: Inline-volume`, + + // https://issues.redhat.com/browse/OCPBUGS-72531 + `\[sig-storage\] Pod Disks \[Feature:StorageProvider\] \[Serial\] attach on previously attached volumes should work`, }, // tests that need to be temporarily disabled while the rebase is in progress. "[Disabled:RebaseInProgress]": { diff --git a/vendor/k8s.io/kubernetes/pkg/features/kube_features.go b/vendor/k8s.io/kubernetes/pkg/features/kube_features.go index 43cae7a4b824..486ee75ad99e 100644 --- a/vendor/k8s.io/kubernetes/pkg/features/kube_features.go +++ b/vendor/k8s.io/kubernetes/pkg/features/kube_features.go @@ -452,13 +452,6 @@ const ( // Enable POD resources API with Get method KubeletPodResourcesGet featuregate.Feature = "KubeletPodResourcesGet" - // owner: @ffromani - // alpha: v1.21 - // beta: v1.23 - // GA: v1.28 - // Enable POD resources API to return allocatable resources - KubeletPodResourcesGetAllocatable featuregate.Feature = "KubeletPodResourcesGetAllocatable" - // KubeletSeparateDiskGC enables Kubelet to garbage collection images/containers on different filesystems // owner: @kannon92 // kep: https://kep.k8s.io/4191 @@ -847,6 +840,14 @@ const ( // Enables a StatefulSet to start from an arbitrary non zero ordinal StatefulSetStartOrdinal featuregate.Feature = "StatefulSetStartOrdinal" + // owner: @serathius + // Allow API server JSON encoder to encode collections item by item, instead of all at once. + StreamingCollectionEncodingToJSON featuregate.Feature = "StreamingCollectionEncodingToJSON" + + // owner: serathius + // Allow API server Protobuf encoder to encode collections item by item, instead of all at once. + StreamingCollectionEncodingToProtobuf featuregate.Feature = "StreamingCollectionEncodingToProtobuf" + // owner: @robscott // kep: https://kep.k8s.io/2433 // alpha: v1.21 @@ -1102,8 +1103,6 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS KubeletPodResourcesGet: {Default: false, PreRelease: featuregate.Alpha}, - KubeletPodResourcesGetAllocatable: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // GA in 1.28, remove in 1.30 - KubeletSeparateDiskGC: {Default: false, PreRelease: featuregate.Alpha}, KubeletTracing: {Default: true, PreRelease: featuregate.Beta}, @@ -1204,6 +1203,10 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS StatefulSetStartOrdinal: {Default: true, PreRelease: featuregate.Beta}, + StreamingCollectionEncodingToJSON: {Default: false, PreRelease: featuregate.Beta}, + + StreamingCollectionEncodingToProtobuf: {Default: false, PreRelease: featuregate.Beta}, + TopologyAwareHints: {Default: true, PreRelease: featuregate.Beta}, TopologyManagerPolicyAlphaOptions: {Default: false, PreRelease: featuregate.Alpha}, diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/podresources/server_v1.go b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/podresources/server_v1.go index 58ba9dbba9dd..c261be727afe 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/podresources/server_v1.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/podresources/server_v1.go @@ -20,11 +20,13 @@ import ( "context" "fmt" + v1 "k8s.io/api/core/v1" utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/klog/v2" kubefeatures "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/kubelet/metrics" - "k8s.io/kubelet/pkg/apis/podresources/v1" + podresourcesv1 "k8s.io/kubelet/pkg/apis/podresources/v1" ) // v1PodResourcesServer implements PodResourcesListerServer @@ -34,38 +36,48 @@ type v1PodResourcesServer struct { cpusProvider CPUsProvider memoryProvider MemoryProvider dynamicResourcesProvider DynamicResourcesProvider + useActivePods bool } // NewV1PodResourcesServer returns a PodResourcesListerServer which lists pods provided by the PodsProvider // with device information provided by the DevicesProvider -func NewV1PodResourcesServer(providers PodResourcesProviders) v1.PodResourcesListerServer { +func NewV1PodResourcesServer(providers PodResourcesProviders) podresourcesv1.PodResourcesListerServer { + useActivePods := true + klog.InfoS("podresources", "method", "list", "useActivePods", useActivePods) return &v1PodResourcesServer{ podsProvider: providers.Pods, devicesProvider: providers.Devices, cpusProvider: providers.Cpus, memoryProvider: providers.Memory, dynamicResourcesProvider: providers.DynamicResources, + useActivePods: useActivePods, } } // List returns information about the resources assigned to pods on the node -func (p *v1PodResourcesServer) List(ctx context.Context, req *v1.ListPodResourcesRequest) (*v1.ListPodResourcesResponse, error) { +func (p *v1PodResourcesServer) List(ctx context.Context, req *podresourcesv1.ListPodResourcesRequest) (*podresourcesv1.ListPodResourcesResponse, error) { metrics.PodResourcesEndpointRequestsTotalCount.WithLabelValues("v1").Inc() metrics.PodResourcesEndpointRequestsListCount.WithLabelValues("v1").Inc() - pods := p.podsProvider.GetPods() - podResources := make([]*v1.PodResources, len(pods)) + var pods []*v1.Pod + if p.useActivePods { + pods = p.podsProvider.GetActivePods() + } else { + pods = p.podsProvider.GetPods() + } + + podResources := make([]*podresourcesv1.PodResources, len(pods)) p.devicesProvider.UpdateAllocatedDevices() for i, pod := range pods { - pRes := v1.PodResources{ + pRes := podresourcesv1.PodResources{ Name: pod.Name, Namespace: pod.Namespace, - Containers: make([]*v1.ContainerResources, len(pod.Spec.Containers)), + Containers: make([]*podresourcesv1.ContainerResources, len(pod.Spec.Containers)), } for j, container := range pod.Spec.Containers { - pRes.Containers[j] = &v1.ContainerResources{ + pRes.Containers[j] = &podresourcesv1.ContainerResources{ Name: container.Name, Devices: p.devicesProvider.GetDevices(string(pod.UID), container.Name), CpuIds: p.cpusProvider.GetCPUs(string(pod.UID), container.Name), @@ -79,18 +91,18 @@ func (p *v1PodResourcesServer) List(ctx context.Context, req *v1.ListPodResource podResources[i] = &pRes } - response := &v1.ListPodResourcesResponse{ + response := &podresourcesv1.ListPodResourcesResponse{ PodResources: podResources, } return response, nil } // GetAllocatableResources returns information about all the resources known by the server - this more like the capacity, not like the current amount of free resources. -func (p *v1PodResourcesServer) GetAllocatableResources(ctx context.Context, req *v1.AllocatableResourcesRequest) (*v1.AllocatableResourcesResponse, error) { +func (p *v1PodResourcesServer) GetAllocatableResources(ctx context.Context, req *podresourcesv1.AllocatableResourcesRequest) (*podresourcesv1.AllocatableResourcesResponse, error) { metrics.PodResourcesEndpointRequestsTotalCount.WithLabelValues("v1").Inc() metrics.PodResourcesEndpointRequestsGetAllocatableCount.WithLabelValues("v1").Inc() - response := &v1.AllocatableResourcesResponse{ + response := &podresourcesv1.AllocatableResourcesResponse{ Devices: p.devicesProvider.GetAllocatableDevices(), CpuIds: p.cpusProvider.GetAllocatableCPUs(), Memory: p.memoryProvider.GetAllocatableMemory(), @@ -100,7 +112,7 @@ func (p *v1PodResourcesServer) GetAllocatableResources(ctx context.Context, req } // Get returns information about the resources assigned to a specific pod -func (p *v1PodResourcesServer) Get(ctx context.Context, req *v1.GetPodResourcesRequest) (*v1.GetPodResourcesResponse, error) { +func (p *v1PodResourcesServer) Get(ctx context.Context, req *podresourcesv1.GetPodResourcesRequest) (*podresourcesv1.GetPodResourcesResponse, error) { metrics.PodResourcesEndpointRequestsTotalCount.WithLabelValues("v1").Inc() metrics.PodResourcesEndpointRequestsGetCount.WithLabelValues("v1").Inc() @@ -115,14 +127,14 @@ func (p *v1PodResourcesServer) Get(ctx context.Context, req *v1.GetPodResourcesR return nil, fmt.Errorf("pod %s in namespace %s not found", req.PodName, req.PodNamespace) } - podResources := &v1.PodResources{ + podResources := &podresourcesv1.PodResources{ Name: pod.Name, Namespace: pod.Namespace, - Containers: make([]*v1.ContainerResources, len(pod.Spec.Containers)), + Containers: make([]*podresourcesv1.ContainerResources, len(pod.Spec.Containers)), } for i, container := range pod.Spec.Containers { - podResources.Containers[i] = &v1.ContainerResources{ + podResources.Containers[i] = &podresourcesv1.ContainerResources{ Name: container.Name, Devices: p.devicesProvider.GetDevices(string(pod.UID), container.Name), CpuIds: p.cpusProvider.GetCPUs(string(pod.UID), container.Name), @@ -133,7 +145,7 @@ func (p *v1PodResourcesServer) Get(ctx context.Context, req *v1.GetPodResourcesR } } - response := &v1.GetPodResourcesResponse{ + response := &podresourcesv1.GetPodResourcesResponse{ PodResources: podResources, } return response, nil diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/podresources/types.go b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/podresources/types.go index 155d42abbcc3..9729e210577b 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/apis/podresources/types.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/apis/podresources/types.go @@ -34,6 +34,7 @@ type DevicesProvider interface { // PodsProvider knows how to provide the pods admitted by the node type PodsProvider interface { + GetActivePods() []*v1.Pod GetPods() []*v1.Pod GetPodByName(namespace, name string) (*v1.Pod, bool) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet.go index b19c87103cc7..c1191f1777a8 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kubelet.go @@ -2968,6 +2968,22 @@ func (kl *Kubelet) ListenAndServeReadOnly(address net.IP, port uint) { server.ListenAndServeKubeletReadOnlyServer(kl, kl.resourceAnalyzer, address, port) } +type kubeletPodsProvider struct { + kl *Kubelet +} + +func (pp *kubeletPodsProvider) GetActivePods() []*v1.Pod { + return pp.kl.GetActivePods() +} + +func (pp *kubeletPodsProvider) GetPods() []*v1.Pod { + return pp.kl.podManager.GetPods() +} + +func (pp *kubeletPodsProvider) GetPodByName(namespace, name string) (*v1.Pod, bool) { + return pp.kl.podManager.GetPodByName(namespace, name) +} + // ListenAndServePodResources runs the kubelet podresources grpc service func (kl *Kubelet) ListenAndServePodResources() { endpoint, err := util.LocalEndpoint(kl.getPodResourcesDir(), podresources.Socket) @@ -2977,7 +2993,7 @@ func (kl *Kubelet) ListenAndServePodResources() { } providers := podresources.PodResourcesProviders{ - Pods: kl.podManager, + Pods: &kubeletPodsProvider{kl: kl}, Devices: kl.containerManager, Cpus: kl.containerManager, Memory: kl.containerManager, diff --git a/vendor/k8s.io/kubernetes/pkg/registry/core/rest/storage_core_generic.go b/vendor/k8s.io/kubernetes/pkg/registry/core/rest/storage_core_generic.go index 193b5b98f473..e4eb96ffe13a 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/core/rest/storage_core_generic.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/core/rest/storage_core_generic.go @@ -33,6 +33,9 @@ import ( "k8s.io/client-go/informers" restclient "k8s.io/client-go/rest" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apiserver/pkg/features" + utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" configmapstore "k8s.io/kubernetes/pkg/registry/core/configmap/storage" @@ -68,6 +71,16 @@ func (c *GenericConfig) NewRESTStorage(apiResourceConfigSource serverstorage.API ParameterCodec: legacyscheme.ParameterCodec, NegotiatedSerializer: legacyscheme.Codecs, } + opts := []serializer.CodecFactoryOptionsMutator{} + if utilfeature.DefaultFeatureGate.Enabled(features.StreamingCollectionEncodingToJSON) { + opts = append(opts, serializer.WithStreamingCollectionEncodingToJSON()) + } + if utilfeature.DefaultFeatureGate.Enabled(features.StreamingCollectionEncodingToProtobuf) { + opts = append(opts, serializer.WithStreamingCollectionEncodingToProtobuf()) + } + if len(opts) != 0 { + apiGroupInfo.NegotiatedSerializer = serializer.NewCodecFactory(legacyscheme.Scheme, opts...) + } eventStorage, err := eventstore.NewREST(restOptionsGetter, uint64(c.EventTTL.Seconds())) if err != nil { diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodevolumelimits/csi.go b/vendor/k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodevolumelimits/csi.go index 5db408b33ce7..b69a1110e12c 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodevolumelimits/csi.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodevolumelimits/csi.go @@ -22,6 +22,7 @@ import ( v1 "k8s.io/api/core/v1" storagev1 "k8s.io/api/storage/v1" + "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/rand" corelisters "k8s.io/client-go/listers/core/v1" @@ -54,6 +55,7 @@ type CSILimits struct { pvLister corelisters.PersistentVolumeLister pvcLister corelisters.PersistentVolumeClaimLister scLister storagelisters.StorageClassLister + vaLister storagelisters.VolumeAttachmentLister randomVolumeIDPrefix string @@ -119,6 +121,7 @@ func (pl *CSILimits) Filter(ctx context.Context, _ *framework.CycleState, pod *v logger.V(5).Info("Could not get a CSINode object for the node", "node", klog.KObj(node), "err", err) } + // Count CSI volumes from the new pod newVolumes := make(map[string]string) if err := pl.filterAttachableVolumes(logger, pod, csiNode, true /* new pod */, newVolumes); err != nil { return framework.AsStatus(err) @@ -135,6 +138,7 @@ func (pl *CSILimits) Filter(ctx context.Context, _ *framework.CycleState, pod *v return nil } + // Count CSI volumes from existing pods attachedVolumes := make(map[string]string) for _, existingPod := range nodeInfo.Pods { if err := pl.filterAttachableVolumes(logger, existingPod.Pod, csiNode, false /* existing pod */, attachedVolumes); err != nil { @@ -149,6 +153,19 @@ func (pl *CSILimits) Filter(ctx context.Context, _ *framework.CycleState, pod *v attachedVolumeCount[volumeLimitKey]++ } + // Count CSI volumes from VolumeAttachments + volumeAttachments, err := pl.getNodeVolumeAttachmentInfo(logger, node.Name) + if err != nil { + return framework.AsStatus(err) + } + + for volumeUniqueName, driverName := range volumeAttachments { + // Avoid double-counting volumes already used by existing pods + if _, exists := attachedVolumes[volumeUniqueName]; !exists { + attachedVolumeCount[driverName]++ + } + } + newVolumeCount := map[string]int{} for _, volumeLimitKey := range newVolumes { newVolumeCount[volumeLimitKey]++ @@ -231,7 +248,7 @@ func (pl *CSILimits) filterAttachableVolumes( continue } - volumeUniqueName := fmt.Sprintf("%s/%s", driverName, volumeHandle) + volumeUniqueName := getVolumeUniqueName(driverName, volumeHandle) volumeLimitKey := volumeutil.GetCSIAttachLimitKey(driverName) result[volumeUniqueName] = volumeLimitKey } @@ -273,7 +290,7 @@ func (pl *CSILimits) checkAttachableInlineVolume(logger klog.Logger, vol *v1.Vol if translatedPV.Spec.PersistentVolumeSource.CSI == nil { return nil } - volumeUniqueName := fmt.Sprintf("%s/%s", driverName, translatedPV.Spec.PersistentVolumeSource.CSI.VolumeHandle) + volumeUniqueName := getVolumeUniqueName(driverName, translatedPV.Spec.PersistentVolumeSource.CSI.VolumeHandle) volumeLimitKey := volumeutil.GetCSIAttachLimitKey(driverName) result[volumeUniqueName] = volumeLimitKey return nil @@ -383,6 +400,7 @@ func NewCSI(_ context.Context, _ runtime.Object, handle framework.Handle, fts fe pvcLister := informerFactory.Core().V1().PersistentVolumeClaims().Lister() csiNodesLister := informerFactory.Storage().V1().CSINodes().Lister() scLister := informerFactory.Storage().V1().StorageClasses().Lister() + vaLister := informerFactory.Storage().V1().VolumeAttachments().Lister() csiTranslator := csitrans.New() return &CSILimits{ @@ -390,6 +408,7 @@ func NewCSI(_ context.Context, _ runtime.Object, handle framework.Handle, fts fe pvLister: pvLister, pvcLister: pvcLister, scLister: scLister, + vaLister: vaLister, randomVolumeIDPrefix: rand.String(32), translator: csiTranslator, }, nil @@ -410,3 +429,40 @@ func getVolumeLimits(nodeInfo *framework.NodeInfo, csiNode *storagev1.CSINode) m } return nodeVolumeLimits } + +// getNodeVolumeAttachmentInfo returns a map of volumeID to driver name for the given node. +func (pl *CSILimits) getNodeVolumeAttachmentInfo(logger klog.Logger, nodeName string) (map[string]string, error) { + volumeAttachments := make(map[string]string) + vas, err := pl.vaLister.List(labels.Everything()) + if err != nil { + return nil, err + } + for _, va := range vas { + if va.Spec.NodeName == nodeName { + if va.Spec.Attacher == "" { + logger.V(5).Info("VolumeAttachment has no attacher", "VolumeAttachment", klog.KObj(va)) + continue + } + if va.Spec.Source.PersistentVolumeName == nil { + logger.V(5).Info("VolumeAttachment has no PV name", "VolumeAttachment", klog.KObj(va)) + continue + } + pv, err := pl.pvLister.Get(*va.Spec.Source.PersistentVolumeName) + if err != nil { + logger.V(5).Info("Unable to get PV for VolumeAttachment", "VolumeAttachment", klog.KObj(va), "err", err) + continue + } + if pv.Spec.CSI == nil { + logger.V(5).Info("PV is not a CSI volume", "PV", klog.KObj(pv)) + continue + } + volumeID := getVolumeUniqueName(va.Spec.Attacher, pv.Spec.CSI.VolumeHandle) + volumeAttachments[volumeID] = volumeutil.GetCSIAttachLimitKey(va.Spec.Attacher) + } + } + return volumeAttachments, nil +} + +func getVolumeUniqueName(driverName, volumeHandle string) string { + return fmt.Sprintf("%s/%s", driverName, volumeHandle) +} diff --git a/vendor/k8s.io/kubernetes/pkg/volume/plugins.go b/vendor/k8s.io/kubernetes/pkg/volume/plugins.go index dcccb56f102e..6f744b97e74e 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/plugins.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/plugins.go @@ -663,9 +663,8 @@ func (pm *VolumePluginMgr) initProbedPlugin(probedPlugin VolumePlugin) error { // specification. If no plugins can support or more than one plugin can // support it, return error. func (pm *VolumePluginMgr) FindPluginBySpec(spec *Spec) (VolumePlugin, error) { - pm.mutex.RLock() - defer pm.mutex.RUnlock() - + pm.mutex.Lock() + defer pm.mutex.Unlock() if spec == nil { return nil, fmt.Errorf("could not find plugin because volume spec is nil") } @@ -678,8 +677,8 @@ func (pm *VolumePluginMgr) FindPluginBySpec(spec *Spec) (VolumePlugin, error) { matchedPluginNames = append(matchedPluginNames, v.GetPluginName()) } } - pm.refreshProbedPlugins() + for _, plugin := range pm.probedPlugins { if plugin.CanSupport(spec) { match = plugin @@ -699,14 +698,13 @@ func (pm *VolumePluginMgr) FindPluginBySpec(spec *Spec) (VolumePlugin, error) { // FindPluginByName fetches a plugin by name. If no plugin is found, returns error. func (pm *VolumePluginMgr) FindPluginByName(name string) (VolumePlugin, error) { - pm.mutex.RLock() - defer pm.mutex.RUnlock() + pm.mutex.Lock() + defer pm.mutex.Unlock() var match VolumePlugin if v, found := pm.plugins[name]; found { match = v } - pm.refreshProbedPlugins() if plugin, found := pm.probedPlugins[name]; found { if match != nil { @@ -733,6 +731,7 @@ func (pm *VolumePluginMgr) refreshProbedPlugins() { // because the probe function can return a list of valid plugins // even when an error is present we still must add the plugins // or they will be skipped because each event only fires once + for _, event := range events { if event.Op == ProbeAddOrUpdate { if err := pm.initProbedPlugin(event.Plugin); err != nil { diff --git a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go index 71ed4cb83b43..3e9b2956be4f 100644 --- a/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go +++ b/vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go @@ -573,6 +573,7 @@ func clusterRoles() []rbacv1.ClusterRole { rbacv1helpers.NewRule("create").Groups(authorizationGroup).Resources("subjectaccessreviews").RuleOrDie(), // Needed for volume limits rbacv1helpers.NewRule(Read...).Groups(storageGroup).Resources("csinodes").RuleOrDie(), + rbacv1helpers.NewRule("get", "list", "watch").Groups(storageGroup).Resources("volumeattachments").RuleOrDie(), // Needed for namespaceSelector feature in pod affinity rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("namespaces").RuleOrDie(), rbacv1helpers.NewRule(Read...).Groups(storageGroup).Resources("csidrivers").RuleOrDie(), diff --git a/vendor/modules.txt b/vendor/modules.txt index 6638da49dd10..4529e7bad122 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1793,7 +1793,7 @@ gopkg.in/yaml.v2 # gopkg.in/yaml.v3 v3.0.1 ## explicit gopkg.in/yaml.v3 -# k8s.io/api v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/api v0.0.0-20250808221949-c68a6637efae +# k8s.io/api v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/api v0.0.0-20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/api/admission/v1 k8s.io/api/admission/v1beta1 @@ -1850,7 +1850,7 @@ k8s.io/api/scheduling/v1beta1 k8s.io/api/storage/v1 k8s.io/api/storage/v1alpha1 k8s.io/api/storage/v1beta1 -# k8s.io/apiextensions-apiserver v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/apiextensions-apiserver v0.0.0-20250808221949-c68a6637efae +# k8s.io/apiextensions-apiserver v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/apiextensions-apiserver v0.0.0-20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/apiextensions-apiserver/pkg/apihelpers k8s.io/apiextensions-apiserver/pkg/apis/apiextensions @@ -1900,7 +1900,7 @@ k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition k8s.io/apiextensions-apiserver/test/integration k8s.io/apiextensions-apiserver/test/integration/fixtures -# k8s.io/apimachinery v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/apimachinery v0.0.0-20250808221949-c68a6637efae +# k8s.io/apimachinery v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/apimachinery v0.0.0-20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/apimachinery/pkg/api/apitesting k8s.io/apimachinery/pkg/api/equality @@ -1968,7 +1968,7 @@ k8s.io/apimachinery/pkg/watch k8s.io/apimachinery/third_party/forked/golang/json k8s.io/apimachinery/third_party/forked/golang/netutil k8s.io/apimachinery/third_party/forked/golang/reflect -# k8s.io/apiserver v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/apiserver v0.0.0-20250808221949-c68a6637efae +# k8s.io/apiserver v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/apiserver v0.0.0-20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/apiserver/pkg/admission k8s.io/apiserver/pkg/admission/cel @@ -2138,13 +2138,13 @@ k8s.io/apiserver/plugin/pkg/audit/webhook k8s.io/apiserver/plugin/pkg/authenticator/token/oidc k8s.io/apiserver/plugin/pkg/authenticator/token/webhook k8s.io/apiserver/plugin/pkg/authorizer/webhook -# k8s.io/cli-runtime v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/cli-runtime v0.0.0-20250808221949-c68a6637efae +# k8s.io/cli-runtime v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/cli-runtime v0.0.0-20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/cli-runtime/pkg/genericclioptions k8s.io/cli-runtime/pkg/genericiooptions k8s.io/cli-runtime/pkg/printers k8s.io/cli-runtime/pkg/resource -# k8s.io/client-go v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/client-go v0.0.0-20250808221949-c68a6637efae +# k8s.io/client-go v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/client-go v0.0.0-20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/client-go/applyconfigurations/admissionregistration/v1 k8s.io/client-go/applyconfigurations/admissionregistration/v1alpha1 @@ -2479,7 +2479,7 @@ k8s.io/client-go/util/keyutil k8s.io/client-go/util/retry k8s.io/client-go/util/testing k8s.io/client-go/util/workqueue -# k8s.io/cloud-provider v0.0.0 => github.com/openshift/kubernetes/staging/src/k8s.io/cloud-provider v0.0.0-20250808221949-c68a6637efae +# k8s.io/cloud-provider v0.0.0 => github.com/openshift/kubernetes/staging/src/k8s.io/cloud-provider v0.0.0-20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/cloud-provider k8s.io/cloud-provider/api @@ -2499,13 +2499,13 @@ k8s.io/cloud-provider/service/helpers k8s.io/cloud-provider/volume k8s.io/cloud-provider/volume/errors k8s.io/cloud-provider/volume/helpers -# k8s.io/cluster-bootstrap v0.0.0 => github.com/openshift/kubernetes/staging/src/k8s.io/cluster-bootstrap v0.0.0-20250808221949-c68a6637efae +# k8s.io/cluster-bootstrap v0.0.0 => github.com/openshift/kubernetes/staging/src/k8s.io/cluster-bootstrap v0.0.0-20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/cluster-bootstrap/token/api k8s.io/cluster-bootstrap/token/util k8s.io/cluster-bootstrap/util/secrets k8s.io/cluster-bootstrap/util/tokens -# k8s.io/component-base v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/component-base v0.0.0-20250808221949-c68a6637efae +# k8s.io/component-base v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/component-base v0.0.0-20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/component-base/cli/flag k8s.io/component-base/cli/globalflag @@ -2535,7 +2535,7 @@ k8s.io/component-base/tracing k8s.io/component-base/tracing/api/v1 k8s.io/component-base/version k8s.io/component-base/version/verflag -# k8s.io/component-helpers v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/component-helpers v0.0.0-20250808221949-c68a6637efae +# k8s.io/component-helpers v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/component-helpers v0.0.0-20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/component-helpers/apimachinery/lease k8s.io/component-helpers/apps/poddisruptionbudget @@ -2548,7 +2548,7 @@ k8s.io/component-helpers/scheduling/corev1 k8s.io/component-helpers/scheduling/corev1/nodeaffinity k8s.io/component-helpers/storage/ephemeral k8s.io/component-helpers/storage/volume -# k8s.io/controller-manager v0.0.0 => github.com/openshift/kubernetes/staging/src/k8s.io/controller-manager v0.0.0-20250808221949-c68a6637efae +# k8s.io/controller-manager v0.0.0 => github.com/openshift/kubernetes/staging/src/k8s.io/controller-manager v0.0.0-20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/controller-manager/config k8s.io/controller-manager/config/v1 @@ -2560,16 +2560,16 @@ k8s.io/controller-manager/pkg/features k8s.io/controller-manager/pkg/features/register k8s.io/controller-manager/pkg/leadermigration/config k8s.io/controller-manager/pkg/leadermigration/options -# k8s.io/cri-api v0.0.0 => github.com/openshift/kubernetes/staging/src/k8s.io/cri-api v0.0.0-20250808221949-c68a6637efae +# k8s.io/cri-api v0.0.0 => github.com/openshift/kubernetes/staging/src/k8s.io/cri-api v0.0.0-20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/cri-api/pkg/apis k8s.io/cri-api/pkg/apis/runtime/v1 k8s.io/cri-api/pkg/errors -# k8s.io/csi-translation-lib v0.0.0 => github.com/openshift/kubernetes/staging/src/k8s.io/csi-translation-lib v0.0.0-20250808221949-c68a6637efae +# k8s.io/csi-translation-lib v0.0.0 => github.com/openshift/kubernetes/staging/src/k8s.io/csi-translation-lib v0.0.0-20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/csi-translation-lib k8s.io/csi-translation-lib/plugins -# k8s.io/dynamic-resource-allocation v0.0.0 => github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation v0.0.0-20250808221949-c68a6637efae +# k8s.io/dynamic-resource-allocation v0.0.0 => github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation v0.0.0-20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/dynamic-resource-allocation/resourceclaim # k8s.io/klog/v2 v2.110.1 @@ -2587,7 +2587,7 @@ k8s.io/kms/apis/v1beta1 k8s.io/kms/apis/v2 k8s.io/kms/pkg/service k8s.io/kms/pkg/util -# k8s.io/kube-aggregator v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/kube-aggregator v0.0.0-20250808221949-c68a6637efae +# k8s.io/kube-aggregator v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/kube-aggregator v0.0.0-20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/kube-aggregator/pkg/apis/apiregistration k8s.io/kube-aggregator/pkg/apis/apiregistration/install @@ -2644,11 +2644,11 @@ k8s.io/kube-openapi/pkg/validation/spec k8s.io/kube-openapi/pkg/validation/strfmt k8s.io/kube-openapi/pkg/validation/strfmt/bson k8s.io/kube-openapi/pkg/validation/validate -# k8s.io/kube-scheduler v0.0.0 => github.com/openshift/kubernetes/staging/src/k8s.io/kube-scheduler v0.0.0-20250808221949-c68a6637efae +# k8s.io/kube-scheduler v0.0.0 => github.com/openshift/kubernetes/staging/src/k8s.io/kube-scheduler v0.0.0-20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/kube-scheduler/config/v1 k8s.io/kube-scheduler/extender/v1 -# k8s.io/kubectl v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/kubectl v0.0.0-20250808221949-c68a6637efae +# k8s.io/kubectl v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/kubectl v0.0.0-20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/kubectl/pkg/apps k8s.io/kubectl/pkg/cmd/util @@ -2673,7 +2673,7 @@ k8s.io/kubectl/pkg/util/storage k8s.io/kubectl/pkg/util/templates k8s.io/kubectl/pkg/util/term k8s.io/kubectl/pkg/validation -# k8s.io/kubelet v0.24.0 => github.com/openshift/kubernetes/staging/src/k8s.io/kubelet v0.0.0-20250808221949-c68a6637efae +# k8s.io/kubelet v0.24.0 => github.com/openshift/kubernetes/staging/src/k8s.io/kubelet v0.0.0-20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/kubelet/config/v1 k8s.io/kubelet/config/v1alpha1 @@ -2695,7 +2695,7 @@ k8s.io/kubelet/pkg/cri/streaming k8s.io/kubelet/pkg/cri/streaming/portforward k8s.io/kubelet/pkg/cri/streaming/remotecommand k8s.io/kubelet/pkg/types -# k8s.io/kubernetes v1.29.0 => github.com/openshift/kubernetes v1.29.0-rc.1.0.20250808221949-c68a6637efae +# k8s.io/kubernetes v1.29.0 => github.com/openshift/kubernetes v1.29.0-rc.1.0.20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/kubernetes/cmd/kube-apiserver/app k8s.io/kubernetes/cmd/kube-apiserver/app/options @@ -3486,7 +3486,7 @@ k8s.io/kubernetes/third_party/forked/gonum/graph k8s.io/kubernetes/third_party/forked/gonum/graph/internal/linear k8s.io/kubernetes/third_party/forked/gonum/graph/simple k8s.io/kubernetes/third_party/forked/gonum/graph/traverse -# k8s.io/legacy-cloud-providers v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/legacy-cloud-providers v0.0.0-20250808221949-c68a6637efae +# k8s.io/legacy-cloud-providers v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/legacy-cloud-providers v0.0.0-20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/legacy-cloud-providers/azure k8s.io/legacy-cloud-providers/azure/auth @@ -3528,7 +3528,7 @@ k8s.io/legacy-cloud-providers/gce/gcpcredential k8s.io/legacy-cloud-providers/vsphere k8s.io/legacy-cloud-providers/vsphere/vclib k8s.io/legacy-cloud-providers/vsphere/vclib/diskmanagers -# k8s.io/metrics v0.0.0 => github.com/openshift/kubernetes/staging/src/k8s.io/metrics v0.0.0-20250808221949-c68a6637efae +# k8s.io/metrics v0.0.0 => github.com/openshift/kubernetes/staging/src/k8s.io/metrics v0.0.0-20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/metrics/pkg/apis/custom_metrics k8s.io/metrics/pkg/apis/custom_metrics/v1beta1 @@ -3538,10 +3538,10 @@ k8s.io/metrics/pkg/apis/external_metrics/v1beta1 k8s.io/metrics/pkg/client/custom_metrics k8s.io/metrics/pkg/client/custom_metrics/scheme k8s.io/metrics/pkg/client/external_metrics -# k8s.io/mount-utils v0.0.0 => github.com/openshift/kubernetes/staging/src/k8s.io/mount-utils v0.0.0-20250808221949-c68a6637efae +# k8s.io/mount-utils v0.0.0 => github.com/openshift/kubernetes/staging/src/k8s.io/mount-utils v0.0.0-20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/mount-utils -# k8s.io/pod-security-admission v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/pod-security-admission v0.0.0-20250808221949-c68a6637efae +# k8s.io/pod-security-admission v0.29.0 => github.com/openshift/kubernetes/staging/src/k8s.io/pod-security-admission v0.0.0-20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/pod-security-admission/admission k8s.io/pod-security-admission/admission/api @@ -3554,7 +3554,7 @@ k8s.io/pod-security-admission/admission/api/validation k8s.io/pod-security-admission/api k8s.io/pod-security-admission/metrics k8s.io/pod-security-admission/policy -# k8s.io/sample-apiserver v0.0.0 => github.com/openshift/kubernetes/staging/src/k8s.io/sample-apiserver v0.0.0-20250808221949-c68a6637efae +# k8s.io/sample-apiserver v0.0.0 => github.com/openshift/kubernetes/staging/src/k8s.io/sample-apiserver v0.0.0-20260209193319-41c4e9ba94f4 ## explicit; go 1.21 k8s.io/sample-apiserver/pkg/apis/wardle k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1 @@ -3691,33 +3691,33 @@ sigs.k8s.io/structured-merge-diff/v4/value ## explicit; go 1.12 sigs.k8s.io/yaml # github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20231031162821-c5e24be53ea7 -# k8s.io/api => github.com/openshift/kubernetes/staging/src/k8s.io/api v0.0.0-20250808221949-c68a6637efae -# k8s.io/apiextensions-apiserver => github.com/openshift/kubernetes/staging/src/k8s.io/apiextensions-apiserver v0.0.0-20250808221949-c68a6637efae -# k8s.io/apimachinery => github.com/openshift/kubernetes/staging/src/k8s.io/apimachinery v0.0.0-20250808221949-c68a6637efae -# k8s.io/apiserver => github.com/openshift/kubernetes/staging/src/k8s.io/apiserver v0.0.0-20250808221949-c68a6637efae -# k8s.io/cli-runtime => github.com/openshift/kubernetes/staging/src/k8s.io/cli-runtime v0.0.0-20250808221949-c68a6637efae -# k8s.io/client-go => github.com/openshift/kubernetes/staging/src/k8s.io/client-go v0.0.0-20250808221949-c68a6637efae -# k8s.io/cloud-provider => github.com/openshift/kubernetes/staging/src/k8s.io/cloud-provider v0.0.0-20250808221949-c68a6637efae -# k8s.io/cluster-bootstrap => github.com/openshift/kubernetes/staging/src/k8s.io/cluster-bootstrap v0.0.0-20250808221949-c68a6637efae -# k8s.io/code-generator => github.com/openshift/kubernetes/staging/src/k8s.io/code-generator v0.0.0-20250808221949-c68a6637efae -# k8s.io/component-base => github.com/openshift/kubernetes/staging/src/k8s.io/component-base v0.0.0-20250808221949-c68a6637efae -# k8s.io/component-helpers => github.com/openshift/kubernetes/staging/src/k8s.io/component-helpers v0.0.0-20250808221949-c68a6637efae -# k8s.io/controller-manager => github.com/openshift/kubernetes/staging/src/k8s.io/controller-manager v0.0.0-20250808221949-c68a6637efae -# k8s.io/cri-api => github.com/openshift/kubernetes/staging/src/k8s.io/cri-api v0.0.0-20250808221949-c68a6637efae -# k8s.io/csi-translation-lib => github.com/openshift/kubernetes/staging/src/k8s.io/csi-translation-lib v0.0.0-20250808221949-c68a6637efae -# k8s.io/dynamic-resource-allocation => github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation v0.0.0-20250808221949-c68a6637efae -# k8s.io/endpointslice => github.com/openshift/kubernetes/staging/src/k8s.io/endpointslice v0.0.0-20250808221949-c68a6637efae -# k8s.io/kube-aggregator => github.com/openshift/kubernetes/staging/src/k8s.io/kube-aggregator v0.0.0-20250808221949-c68a6637efae -# k8s.io/kube-controller-manager => github.com/openshift/kubernetes/staging/src/k8s.io/kube-controller-manager v0.0.0-20250808221949-c68a6637efae -# k8s.io/kube-proxy => github.com/openshift/kubernetes/staging/src/k8s.io/kube-proxy v0.0.0-20250808221949-c68a6637efae -# k8s.io/kube-scheduler => github.com/openshift/kubernetes/staging/src/k8s.io/kube-scheduler v0.0.0-20250808221949-c68a6637efae -# k8s.io/kubectl => github.com/openshift/kubernetes/staging/src/k8s.io/kubectl v0.0.0-20250808221949-c68a6637efae -# k8s.io/kubelet => github.com/openshift/kubernetes/staging/src/k8s.io/kubelet v0.0.0-20250808221949-c68a6637efae -# k8s.io/kubernetes => github.com/openshift/kubernetes v1.29.0-rc.1.0.20250808221949-c68a6637efae -# k8s.io/legacy-cloud-providers => github.com/openshift/kubernetes/staging/src/k8s.io/legacy-cloud-providers v0.0.0-20250808221949-c68a6637efae -# k8s.io/metrics => github.com/openshift/kubernetes/staging/src/k8s.io/metrics v0.0.0-20250808221949-c68a6637efae -# k8s.io/mount-utils => github.com/openshift/kubernetes/staging/src/k8s.io/mount-utils v0.0.0-20250808221949-c68a6637efae -# k8s.io/pod-security-admission => github.com/openshift/kubernetes/staging/src/k8s.io/pod-security-admission v0.0.0-20250808221949-c68a6637efae -# k8s.io/sample-apiserver => github.com/openshift/kubernetes/staging/src/k8s.io/sample-apiserver v0.0.0-20250808221949-c68a6637efae -# k8s.io/sample-cli-plugin => github.com/openshift/kubernetes/staging/src/k8s.io/sample-cli-plugin v0.0.0-20250808221949-c68a6637efae -# k8s.io/sample-controller => github.com/openshift/kubernetes/staging/src/k8s.io/sample-controller v0.0.0-20250808221949-c68a6637efae +# k8s.io/api => github.com/openshift/kubernetes/staging/src/k8s.io/api v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/apiextensions-apiserver => github.com/openshift/kubernetes/staging/src/k8s.io/apiextensions-apiserver v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/apimachinery => github.com/openshift/kubernetes/staging/src/k8s.io/apimachinery v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/apiserver => github.com/openshift/kubernetes/staging/src/k8s.io/apiserver v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/cli-runtime => github.com/openshift/kubernetes/staging/src/k8s.io/cli-runtime v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/client-go => github.com/openshift/kubernetes/staging/src/k8s.io/client-go v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/cloud-provider => github.com/openshift/kubernetes/staging/src/k8s.io/cloud-provider v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/cluster-bootstrap => github.com/openshift/kubernetes/staging/src/k8s.io/cluster-bootstrap v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/code-generator => github.com/openshift/kubernetes/staging/src/k8s.io/code-generator v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/component-base => github.com/openshift/kubernetes/staging/src/k8s.io/component-base v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/component-helpers => github.com/openshift/kubernetes/staging/src/k8s.io/component-helpers v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/controller-manager => github.com/openshift/kubernetes/staging/src/k8s.io/controller-manager v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/cri-api => github.com/openshift/kubernetes/staging/src/k8s.io/cri-api v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/csi-translation-lib => github.com/openshift/kubernetes/staging/src/k8s.io/csi-translation-lib v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/dynamic-resource-allocation => github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/endpointslice => github.com/openshift/kubernetes/staging/src/k8s.io/endpointslice v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/kube-aggregator => github.com/openshift/kubernetes/staging/src/k8s.io/kube-aggregator v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/kube-controller-manager => github.com/openshift/kubernetes/staging/src/k8s.io/kube-controller-manager v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/kube-proxy => github.com/openshift/kubernetes/staging/src/k8s.io/kube-proxy v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/kube-scheduler => github.com/openshift/kubernetes/staging/src/k8s.io/kube-scheduler v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/kubectl => github.com/openshift/kubernetes/staging/src/k8s.io/kubectl v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/kubelet => github.com/openshift/kubernetes/staging/src/k8s.io/kubelet v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/kubernetes => github.com/openshift/kubernetes v1.29.0-rc.1.0.20260209193319-41c4e9ba94f4 +# k8s.io/legacy-cloud-providers => github.com/openshift/kubernetes/staging/src/k8s.io/legacy-cloud-providers v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/metrics => github.com/openshift/kubernetes/staging/src/k8s.io/metrics v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/mount-utils => github.com/openshift/kubernetes/staging/src/k8s.io/mount-utils v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/pod-security-admission => github.com/openshift/kubernetes/staging/src/k8s.io/pod-security-admission v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/sample-apiserver => github.com/openshift/kubernetes/staging/src/k8s.io/sample-apiserver v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/sample-cli-plugin => github.com/openshift/kubernetes/staging/src/k8s.io/sample-cli-plugin v0.0.0-20260209193319-41c4e9ba94f4 +# k8s.io/sample-controller => github.com/openshift/kubernetes/staging/src/k8s.io/sample-controller v0.0.0-20260209193319-41c4e9ba94f4 From 74a522887c3c83fe543663b68b2810ce4571f5fb Mon Sep 17 00:00:00 2001 From: Fabio Bertinatto Date: Mon, 2 Mar 2026 18:22:45 -0300 Subject: [PATCH 2/2] Skip broken storage test --- test/extended/util/annotate/rules.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/extended/util/annotate/rules.go b/test/extended/util/annotate/rules.go index 6b5ebc3fdc60..9f38a0450f9b 100644 --- a/test/extended/util/annotate/rules.go +++ b/test/extended/util/annotate/rules.go @@ -56,6 +56,9 @@ var ( // https://issues.redhat.com/browse/OCPBUGS-37799 `\[sig-builds\]\[Feature:Builds\]\[Slow\] can use private repositories as build input build using an HTTP token should be able to clone source code via an HTTP token \[apigroup:build.openshift.io\]`, + + // https://issues.redhat.com/browse/OCPBUGS-72531 + `\[sig-storage\] Pod Disks \[Feature:StorageProvider\] \[Serial\] attach on previously attached volumes should work`, }, // tests that may work, but we don't support them "[Disabled:Unsupported]": {},