rebase: bump k8s.io dependencies to v0.26.7

Bumping the k8s.io dependencies to v0.26.7. The main intention
is to update the client-go library dependency for kube 1.27+,
where aggregated discovery is enabled. With client-go lower than
v0.26.4 in some cases it is possible that the discovery response
comes with the malformed response with nil GVK leading to Crash
Loop Back Off state.

Upstream kubernetes issue:
https://github.com/kubernetes/kubernetes/pull/116603

Signed-off-by: karthik-us <ksubrahm@redhat.com>
This commit is contained in:
karthik-us 2023-08-16 14:47:13 +05:30 committed by mergify[bot]
parent a9415f82e9
commit 71925d553e
30 changed files with 597 additions and 355 deletions

70
go.mod
View File

@ -32,16 +32,16 @@ require (
golang.org/x/sys v0.6.0 golang.org/x/sys v0.6.0
google.golang.org/grpc v1.53.0 google.golang.org/grpc v1.53.0
google.golang.org/protobuf v1.29.1 google.golang.org/protobuf v1.29.1
k8s.io/api v0.26.1 k8s.io/api v0.26.7
k8s.io/apimachinery v0.26.1 k8s.io/apimachinery v0.26.7
k8s.io/client-go v12.0.0+incompatible k8s.io/client-go v12.0.0+incompatible
k8s.io/cloud-provider v0.26.1 k8s.io/cloud-provider v0.26.7
k8s.io/klog/v2 v2.90.0 k8s.io/klog/v2 v2.90.0
// //
// when updating k8s.io/kubernetes, make sure to update the replace section too // when updating k8s.io/kubernetes, make sure to update the replace section too
// //
k8s.io/kubernetes v1.26.1 k8s.io/kubernetes v1.26.1
k8s.io/mount-utils v0.26.1 k8s.io/mount-utils v0.26.7
k8s.io/pod-security-admission v0.0.0 k8s.io/pod-security-admission v0.0.0
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 k8s.io/utils v0.0.0-20221128185143-99ec85e7a448
sigs.k8s.io/controller-runtime v0.14.4 sigs.k8s.io/controller-runtime v0.14.4
@ -150,14 +150,14 @@ require (
gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apiextensions-apiserver v0.26.1 // indirect k8s.io/apiextensions-apiserver v0.26.7 // indirect
k8s.io/apiserver v0.26.1 // indirect k8s.io/apiserver v0.26.7 // indirect
k8s.io/component-base v0.26.1 // indirect k8s.io/component-base v0.26.7 // indirect
k8s.io/component-helpers v0.26.1 // indirect k8s.io/component-helpers v0.26.7 // indirect
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect
k8s.io/kubectl v0.0.0 // indirect k8s.io/kubectl v0.0.0 // indirect
k8s.io/kubelet v0.0.0 // indirect k8s.io/kubelet v0.0.0 // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.35 // indirect sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.37 // indirect
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect sigs.k8s.io/yaml v1.3.0 // indirect
@ -180,32 +180,32 @@ replace (
// //
// k8s.io/kubernetes depends on these k8s.io packages, but unversioned // k8s.io/kubernetes depends on these k8s.io packages, but unversioned
// //
k8s.io/api => k8s.io/api v0.26.1 k8s.io/api => k8s.io/api v0.26.7
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.26.1 k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.26.7
k8s.io/apimachinery => k8s.io/apimachinery v0.26.1 k8s.io/apimachinery => k8s.io/apimachinery v0.26.7
k8s.io/apiserver => k8s.io/apiserver v0.26.1 k8s.io/apiserver => k8s.io/apiserver v0.26.7
k8s.io/cli-runtime => k8s.io/cli-runtime v0.26.1 k8s.io/cli-runtime => k8s.io/cli-runtime v0.26.7
k8s.io/client-go => k8s.io/client-go v0.26.1 k8s.io/client-go => k8s.io/client-go v0.26.7
k8s.io/cloud-provider => k8s.io/cloud-provider v0.26.1 k8s.io/cloud-provider => k8s.io/cloud-provider v0.26.7
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.26.1 k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.26.7
k8s.io/code-generator => k8s.io/code-generator v0.26.1 k8s.io/code-generator => k8s.io/code-generator v0.26.7
k8s.io/component-base => k8s.io/component-base v0.26.1 k8s.io/component-base => k8s.io/component-base v0.26.7
k8s.io/component-helpers => k8s.io/component-helpers v0.26.1 k8s.io/component-helpers => k8s.io/component-helpers v0.26.7
k8s.io/controller-manager => k8s.io/controller-manager v0.26.1 k8s.io/controller-manager => k8s.io/controller-manager v0.26.7
k8s.io/cri-api => k8s.io/cri-api v0.26.1 k8s.io/cri-api => k8s.io/cri-api v0.26.7
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.26.1 k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.26.7
k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.26.1 k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.26.7
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.26.1 k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.26.7
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.26.1 k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.26.7
k8s.io/kube-proxy => k8s.io/kube-proxy v0.26.1 k8s.io/kube-proxy => k8s.io/kube-proxy v0.26.7
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.26.1 k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.26.7
k8s.io/kubectl => k8s.io/kubectl v0.26.1 k8s.io/kubectl => k8s.io/kubectl v0.26.7
k8s.io/kubelet => k8s.io/kubelet v0.26.1 k8s.io/kubelet => k8s.io/kubelet v0.26.7
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.26.1 k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.26.7
k8s.io/metrics => k8s.io/metrics v0.26.1 k8s.io/metrics => k8s.io/metrics v0.26.7
k8s.io/mount-utils => k8s.io/mount-utils v0.26.1 k8s.io/mount-utils => k8s.io/mount-utils v0.26.7
k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.26.1 k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.26.7
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.26.1 k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.26.7
// layeh.com seems to be misbehaving // layeh.com seems to be misbehaving
layeh.com/radius => github.com/layeh/radius v0.0.0-20190322222518-890bc1058917 layeh.com/radius => github.com/layeh/radius v0.0.0-20190322222518-890bc1058917
) )

69
go.sum
View File

@ -1268,6 +1268,8 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -1324,7 +1326,8 @@ golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -1364,6 +1367,7 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180903190138-2b024373dcd9/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180903190138-2b024373dcd9/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -1451,7 +1455,7 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
@ -1459,7 +1463,7 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn
golang.org/x/term v0.0.0-20210422114643-f5beecf764ed/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210422114643-f5beecf764ed/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -1473,7 +1477,7 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -1555,6 +1559,7 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -1792,23 +1797,23 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.26.1 h1:f+SWYiPd/GsiWwVRz+NbFyCgvv75Pk9NK6dlkZgpCRQ= k8s.io/api v0.26.7 h1:Lf4iEBEJb5OFNmawtBfSZV/UNi9riSJ0t1qdhyZqI40=
k8s.io/api v0.26.1/go.mod h1:xd/GBNgR0f707+ATNyPmQ1oyKSgndzXij81FzWGsejg= k8s.io/api v0.26.7/go.mod h1:Vk9bMadzA49UHPmHB//lX7VRCQSXGoVwfLd3Sc1SSXI=
k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI= k8s.io/apiextensions-apiserver v0.26.7 h1:L7ImW831auK1ZQBtNJPaG5qyrFxeISEBlgfZJfnaIPk=
k8s.io/apiextensions-apiserver v0.26.1/go.mod h1:AptjOSXDGuE0JICx/Em15PaoO7buLwTs0dGleIHixSM= k8s.io/apiextensions-apiserver v0.26.7/go.mod h1:3DbZBfS3kO7/Jaj7qqzcBtPcKP0/KcklyAnk8zc+fs4=
k8s.io/apimachinery v0.26.1 h1:8EZ/eGJL+hY/MYCNwhmDzVqq2lPl3N3Bo8rvweJwXUQ= k8s.io/apimachinery v0.26.7 h1:590jSBwaSHCAFCqltaEogY/zybFlhGsnLteLpuF2wig=
k8s.io/apimachinery v0.26.1/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74= k8s.io/apimachinery v0.26.7/go.mod h1:qYzLkrQ9lhrZRh0jNKo2cfvf/R1/kQONnSiyB7NUJU0=
k8s.io/apiserver v0.26.1 h1:6vmnAqCDO194SVCPU3MU8NcDgSqsUA62tBUSWrFXhsc= k8s.io/apiserver v0.26.7 h1:NX/zBZZn4R+Cq6shwyn8Pn8REd0yJJ16dbtv9WkEVEU=
k8s.io/apiserver v0.26.1/go.mod h1:wr75z634Cv+sifswE9HlAo5FQ7UoUauIICRlOE+5dCg= k8s.io/apiserver v0.26.7/go.mod h1:r0wDRWHI7VL/KlQLTkJJBVGZ3KeNfv+VetlyRtr86xs=
k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU= k8s.io/client-go v0.26.7 h1:hyU9aKHlwVOykgyxzGYkrDSLCc4+mimZVyUJjPyUn1E=
k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE= k8s.io/client-go v0.26.7/go.mod h1:okYjy0jtq6sdeztALDvCh24tg4opOQS1XNvsJlERDAo=
k8s.io/cloud-provider v0.26.1 h1:qEZmsGWGptOtVSpeMdTsapHX2BEqIk7rc5MA4caBqE0= k8s.io/cloud-provider v0.26.7 h1:J4wYrZ+pvNMQULvNuChLdYXLGf8veBX+vUVfgwo+eoU=
k8s.io/cloud-provider v0.26.1/go.mod h1:6PheIxRySYuRBBxtTUADya8S2rbr18xKi+fhGbLkduc= k8s.io/cloud-provider v0.26.7/go.mod h1:9MqA8lIARGxyNnffsm++P4fpfDttg5BrxeXLMuQVL0o=
k8s.io/code-generator v0.26.1/go.mod h1:OMoJ5Dqx1wgaQzKgc+ZWaZPfGjdRq/Y3WubFrZmeI3I= k8s.io/code-generator v0.26.7/go.mod h1:seNkA/wYpeG1GT1REW1xHk4MCjQcVbx6FFAXKwCgdlE=
k8s.io/component-base v0.26.1 h1:4ahudpeQXHZL5kko+iDHqLj/FSGAEUnSVO0EBbgDd+4= k8s.io/component-base v0.26.7 h1:uqsOyZh0Zqoaup8tmHa491D/CvgFdGUs+X2H/inNUKM=
k8s.io/component-base v0.26.1/go.mod h1:VHrLR0b58oC035w6YQiBSbtsf0ThuSwXP+p5dD/kAWU= k8s.io/component-base v0.26.7/go.mod h1:CZe1HTmX/DQdeBrb9XYOXzs96jXth8ZbFvhLMsoJLUg=
k8s.io/component-helpers v0.26.1 h1:Y5h1OYUJTGyHZlSAsc7mcfNsWF08S/MlrQyF/vn93mU= k8s.io/component-helpers v0.26.7 h1:WWdNnJfRQcsxP1NCcMhGMpi9vdlOKPFzZzx48wREvzE=
k8s.io/component-helpers v0.26.1/go.mod h1:jxNTnHb1axLe93MyVuvKj9T/+f4nxBVrj/xf01/UNFk= k8s.io/component-helpers v0.26.7/go.mod h1:r98dtcDwYAv+awPp9hIS6Y35q+jX4YvpX1egBO0u8hw=
k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/gengo v0.0.0-20220902162205-c0856e24416d/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/gengo v0.0.0-20220902162205-c0856e24416d/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
@ -1820,20 +1825,20 @@ k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/klog/v2 v2.90.0 h1:VkTxIV/FjRXn1fgNNcKGM8cfmL1Z33ZjXRTVxKCoF5M= k8s.io/klog/v2 v2.90.0 h1:VkTxIV/FjRXn1fgNNcKGM8cfmL1Z33ZjXRTVxKCoF5M=
k8s.io/klog/v2 v2.90.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/klog/v2 v2.90.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kms v0.26.1/go.mod h1:ReC1IEGuxgfN+PDCIpR6w8+XMmDE7uJhxcCwMZFdIYc= k8s.io/kms v0.26.7/go.mod h1:AYuV9ZebRhr6cb1eT9L6kZVxvgIUxmE1Fe6kPhqYvuc=
k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc=
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E=
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4=
k8s.io/kubectl v0.26.1 h1:K8A0Jjlwg8GqrxOXxAbjY5xtmXYeYjLU96cHp2WMQ7s= k8s.io/kubectl v0.26.7 h1:s24r6MjKDMW4sMOsuBLaNYQHlweTZeDC0BPkMiom8s0=
k8s.io/kubectl v0.26.1/go.mod h1:miYFVzldVbdIiXMrHZYmL/EDWwJKM+F0sSsdxsATFPo= k8s.io/kubectl v0.26.7/go.mod h1:4PGqS2bPQ5yGE0ZSQajzYdWKFUAi8HiuWBZQ2/iEFHg=
k8s.io/kubelet v0.26.1 h1:wQyCQYmLW6GN3v7gVTxnc3jAE4zMYDlzdF3FZV4rKas= k8s.io/kubelet v0.26.7 h1:YzVtyhQzKcpbZktVyeOMzE5d77fFUKf5TiWD/fDKMnc=
k8s.io/kubelet v0.26.1/go.mod h1:gFVZ1Ab4XdjtnYdVRATwGwku7FhTxo6LVEZwYoQaDT8= k8s.io/kubelet v0.26.7/go.mod h1:X/T8bnhE26lE5hOkpAVXx0MQQfXg1dwlsngz7avDWyI=
k8s.io/kubernetes v1.26.1 h1:N+qxlptxpSU/VSLvqBGWyyw/kNhJRpEn1b5YP57+5rk= k8s.io/kubernetes v1.26.1 h1:N+qxlptxpSU/VSLvqBGWyyw/kNhJRpEn1b5YP57+5rk=
k8s.io/kubernetes v1.26.1/go.mod h1:dEfAfGVZBOr2uZLeVazLPj/8E+t8jYFbQqCiBudkB8o= k8s.io/kubernetes v1.26.1/go.mod h1:dEfAfGVZBOr2uZLeVazLPj/8E+t8jYFbQqCiBudkB8o=
k8s.io/mount-utils v0.26.1 h1:deN1IBPyi5UFEAgQYXBEDUejzQUNzRC1ML7BUMWljzA= k8s.io/mount-utils v0.26.7 h1:ZWFWELqEvsvYPhWXGqa2wY3n3JR/ntY1+TK5XsQnRsc=
k8s.io/mount-utils v0.26.1/go.mod h1:au99w4FWU5ZWelLb3Yx6kJc8RZ387IyWVM9tN65Yhxo= k8s.io/mount-utils v0.26.7/go.mod h1:S+09/ujdtdKRo3bzSQXonHpIEKc+svPe8SNgBUJBj8E=
k8s.io/pod-security-admission v0.26.1 h1:EDIxsYFeKMzNvN/JB0PgQcuwBP6fIkIG2O8ZWJhzOp4= k8s.io/pod-security-admission v0.26.7 h1:HNzfuXlo8QMOLHBUnFydLJ/nDSdiv/AAqMI6kZjF5Qc=
k8s.io/pod-security-admission v0.26.1/go.mod h1:hCbYTG5UtLlivmukkMPjAWf23PUBUHzEvR60xNVWN4c= k8s.io/pod-security-admission v0.26.7/go.mod h1:/YQf4FOvgi6ElokZn6KebLFo904bOTdMuMhKJW3z1zw=
k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20221107191617-1a15be271d1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= k8s.io/utils v0.0.0-20221107191617-1a15be271d1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
@ -1843,8 +1848,8 @@ nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.35 h1:+xBL5uTc+BkPBwmMi3vYfUJjq+N3K+H6PXeETwf5cPI= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.37 h1:fAPTNEpzQMOLMGwOHNbUkR2xXTQwMJOZYNx+/mLlOh0=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.35/go.mod h1:WxjusMwXlKzfAs4p9km6XJRndVt2FROgMVCE4cdohFo= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.37/go.mod h1:vfnxT4FXNT8eGvO+xi/DsyC/qHmdujqwrUa1WSspCsk=
sigs.k8s.io/controller-runtime v0.2.2/go.mod h1:9dyohw3ZtoXQuV1e766PHUn+cmrRCIcBh6XIMFNMZ+I= sigs.k8s.io/controller-runtime v0.2.2/go.mod h1:9dyohw3ZtoXQuV1e766PHUn+cmrRCIcBh6XIMFNMZ+I=
sigs.k8s.io/controller-runtime v0.14.4 h1:Kd/Qgx5pd2XUL08eOV2vwIq3L9GhIbJ5Nxengbd4/0M= sigs.k8s.io/controller-runtime v0.14.4 h1:Kd/Qgx5pd2XUL08eOV2vwIq3L9GhIbJ5Nxengbd4/0M=
sigs.k8s.io/controller-runtime v0.14.4/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0= sigs.k8s.io/controller-runtime v0.14.4/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0=

View File

@ -213,8 +213,8 @@ message JobSpec {
// checked against the backoffLimit. This field cannot be used in combination // checked against the backoffLimit. This field cannot be used in combination
// with restartPolicy=OnFailure. // with restartPolicy=OnFailure.
// //
// This field is alpha-level. To use this field, you must enable the // This field is beta-level. It can be used when the `JobPodFailurePolicy`
// `JobPodFailurePolicy` feature gate (disabled by default). // feature gate is enabled (enabled by default).
// +optional // +optional
optional PodFailurePolicy podFailurePolicy = 11; optional PodFailurePolicy podFailurePolicy = 11;

View File

@ -240,8 +240,8 @@ type JobSpec struct {
// checked against the backoffLimit. This field cannot be used in combination // checked against the backoffLimit. This field cannot be used in combination
// with restartPolicy=OnFailure. // with restartPolicy=OnFailure.
// //
// This field is alpha-level. To use this field, you must enable the // This field is beta-level. It can be used when the `JobPodFailurePolicy`
// `JobPodFailurePolicy` feature gate (disabled by default). // feature gate is enabled (enabled by default).
// +optional // +optional
PodFailurePolicy *PodFailurePolicy `json:"podFailurePolicy,omitempty" protobuf:"bytes,11,opt,name=podFailurePolicy"` PodFailurePolicy *PodFailurePolicy `json:"podFailurePolicy,omitempty" protobuf:"bytes,11,opt,name=podFailurePolicy"`

View File

@ -115,7 +115,7 @@ var map_JobSpec = map[string]string{
"parallelism": "Specifies the maximum desired number of pods the job should run at any given time. The actual number of pods running in steady state will be less than this number when ((.spec.completions - .status.successful) < .spec.parallelism), i.e. when the work left to do is less than max parallelism. More info: https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/", "parallelism": "Specifies the maximum desired number of pods the job should run at any given time. The actual number of pods running in steady state will be less than this number when ((.spec.completions - .status.successful) < .spec.parallelism), i.e. when the work left to do is less than max parallelism. More info: https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/",
"completions": "Specifies the desired number of successfully finished pods the job should be run with. Setting to nil means that the success of any pod signals the success of all pods, and allows parallelism to have any positive value. Setting to 1 means that parallelism is limited to 1 and the success of that pod signals the success of the job. More info: https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/", "completions": "Specifies the desired number of successfully finished pods the job should be run with. Setting to nil means that the success of any pod signals the success of all pods, and allows parallelism to have any positive value. Setting to 1 means that parallelism is limited to 1 and the success of that pod signals the success of the job. More info: https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/",
"activeDeadlineSeconds": "Specifies the duration in seconds relative to the startTime that the job may be continuously active before the system tries to terminate it; value must be positive integer. If a Job is suspended (at creation or through an update), this timer will effectively be stopped and reset when the Job is resumed again.", "activeDeadlineSeconds": "Specifies the duration in seconds relative to the startTime that the job may be continuously active before the system tries to terminate it; value must be positive integer. If a Job is suspended (at creation or through an update), this timer will effectively be stopped and reset when the Job is resumed again.",
"podFailurePolicy": "Specifies the policy of handling failed pods. In particular, it allows to specify the set of actions and conditions which need to be satisfied to take the associated action. If empty, the default behaviour applies - the counter of failed pods, represented by the jobs's .status.failed field, is incremented and it is checked against the backoffLimit. This field cannot be used in combination with restartPolicy=OnFailure.\n\nThis field is alpha-level. To use this field, you must enable the `JobPodFailurePolicy` feature gate (disabled by default).", "podFailurePolicy": "Specifies the policy of handling failed pods. In particular, it allows to specify the set of actions and conditions which need to be satisfied to take the associated action. If empty, the default behaviour applies - the counter of failed pods, represented by the jobs's .status.failed field, is incremented and it is checked against the backoffLimit. This field cannot be used in combination with restartPolicy=OnFailure.\n\nThis field is beta-level. It can be used when the `JobPodFailurePolicy` feature gate is enabled (enabled by default).",
"backoffLimit": "Specifies the number of retries before marking this job failed. Defaults to 6", "backoffLimit": "Specifies the number of retries before marking this job failed. Defaults to 6",
"selector": "A label query over pods that should match the pod count. Normally, the system sets this field for you. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors", "selector": "A label query over pods that should match the pod count. Normally, the system sets this field for you. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors",
"manualSelector": "manualSelector controls generation of pod labels and pod selectors. Leave `manualSelector` unset unless you are certain what you are doing. When false or unset, the system pick labels unique to this job and appends those labels to the pod template. When true, the user is responsible for picking unique labels and specifying the selector. Failure to pick a unique label may cause this and other jobs to not function correctly. However, You may see `manualSelector=true` in jobs that were created with the old `extensions/v1beta1` API. More info: https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/#specifying-your-own-pod-selector", "manualSelector": "manualSelector controls generation of pod labels and pod selectors. Leave `manualSelector` unset unless you are certain what you are doing. When false or unset, the system pick labels unique to this job and appends those labels to the pod template. When true, the user is responsible for picking unique labels and specifying the selector. Failure to pick a unique label may cause this and other jobs to not function correctly. However, You may see `manualSelector=true` in jobs that were created with the old `extensions/v1beta1` API. More info: https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/#specifying-your-own-pod-selector",

View File

@ -1791,7 +1791,8 @@ message HTTPGetAction {
// HTTPHeader describes a custom header to be used in HTTP probes // HTTPHeader describes a custom header to be used in HTTP probes
message HTTPHeader { message HTTPHeader {
// The header field name // The header field name.
// This will be canonicalized upon output, so case-variant names will be understood as the same header.
optional string name = 1; optional string name = 1;
// The header field value // The header field value
@ -4512,7 +4513,7 @@ message ResourceRequirements {
// This is an alpha field and requires enabling the // This is an alpha field and requires enabling the
// DynamicResourceAllocation feature gate. // DynamicResourceAllocation feature gate.
// //
// This field is immutable. // This field is immutable. It can only be set for containers.
// //
// +listType=map // +listType=map
// +listMapKey=name // +listMapKey=name

15
vendor/k8s.io/api/core/v1/types.go generated vendored
View File

@ -2137,7 +2137,8 @@ type SecretEnvSource struct {
// HTTPHeader describes a custom header to be used in HTTP probes // HTTPHeader describes a custom header to be used in HTTP probes
type HTTPHeader struct { type HTTPHeader struct {
// The header field name // The header field name.
// This will be canonicalized upon output, so case-variant names will be understood as the same header.
Name string `json:"name" protobuf:"bytes,1,opt,name=name"` Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
// The header field value // The header field value
Value string `json:"value" protobuf:"bytes,2,opt,name=value"` Value string `json:"value" protobuf:"bytes,2,opt,name=value"`
@ -2320,7 +2321,7 @@ type ResourceRequirements struct {
// This is an alpha field and requires enabling the // This is an alpha field and requires enabling the
// DynamicResourceAllocation feature gate. // DynamicResourceAllocation feature gate.
// //
// This field is immutable. // This field is immutable. It can only be set for containers.
// //
// +listType=map // +listType=map
// +listMapKey=name // +listMapKey=name
@ -4404,6 +4405,9 @@ const (
// LoadBalancerPortsError represents the condition of the requested ports // LoadBalancerPortsError represents the condition of the requested ports
// on the cloud load balancer instance. // on the cloud load balancer instance.
LoadBalancerPortsError = "LoadBalancerPortsError" LoadBalancerPortsError = "LoadBalancerPortsError"
// LoadBalancerPortsErrorReason reason in ServiceStatus condition LoadBalancerPortsError
// means the LoadBalancer was not able to be configured correctly.
LoadBalancerPortsErrorReason = "LoadBalancerMixedProtocolNotSupported"
) )
// ServiceStatus represents the current status of a service. // ServiceStatus represents the current status of a service.
@ -6760,6 +6764,13 @@ const (
PortForwardRequestIDHeader = "requestID" PortForwardRequestIDHeader = "requestID"
) )
const (
// MixedProtocolNotSupported error in PortStatus means that the cloud provider
// can't publish the port on the load balancer because mixed values of protocols
// on the same LoadBalancer type of Service are not supported by the cloud provider.
MixedProtocolNotSupported = "MixedProtocolNotSupported"
)
// PortStatus represents the error condition of a service port // PortStatus represents the error condition of a service port
type PortStatus struct { type PortStatus struct {

View File

@ -818,7 +818,7 @@ func (HTTPGetAction) SwaggerDoc() map[string]string {
var map_HTTPHeader = map[string]string{ var map_HTTPHeader = map[string]string{
"": "HTTPHeader describes a custom header to be used in HTTP probes", "": "HTTPHeader describes a custom header to be used in HTTP probes",
"name": "The header field name", "name": "The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header.",
"value": "The header field value", "value": "The header field value",
} }
@ -2041,7 +2041,7 @@ var map_ResourceRequirements = map[string]string{
"": "ResourceRequirements describes the compute resource requirements.", "": "ResourceRequirements describes the compute resource requirements.",
"limits": "Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/", "limits": "Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
"requests": "Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/", "requests": "Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
"claims": "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container.\n\nThis is an alpha field and requires enabling the DynamicResourceAllocation feature gate.\n\nThis field is immutable.", "claims": "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container.\n\nThis is an alpha field and requires enabling the DynamicResourceAllocation feature gate.\n\nThis field is immutable. It can only be set for containers.",
} }
func (ResourceRequirements) SwaggerDoc() map[string]string { func (ResourceRequirements) SwaggerDoc() map[string]string {

View File

@ -248,7 +248,8 @@ message ResourceClaimStatus {
// There can be at most 32 such reservations. This may get increased in // There can be at most 32 such reservations. This may get increased in
// the future, but not reduced. // the future, but not reduced.
// //
// +listType=set // +listType=map
// +listMapKey=uid
// +optional // +optional
repeated ResourceClaimConsumerReference reservedFor = 3; repeated ResourceClaimConsumerReference reservedFor = 3;

View File

@ -112,7 +112,8 @@ type ResourceClaimStatus struct {
// There can be at most 32 such reservations. This may get increased in // There can be at most 32 such reservations. This may get increased in
// the future, but not reduced. // the future, but not reduced.
// //
// +listType=set // +listType=map
// +listMapKey=uid
// +optional // +optional
ReservedFor []ResourceClaimConsumerReference `json:"reservedFor,omitempty" protobuf:"bytes,3,opt,name=reservedFor"` ReservedFor []ResourceClaimConsumerReference `json:"reservedFor,omitempty" protobuf:"bytes,3,opt,name=reservedFor"`

View File

@ -231,7 +231,7 @@ func (c *fromUnstructuredContext) pushKey(key string) {
} }
// FromUnstructuredWIthValidation converts an object from map[string]interface{} representation into a concrete type. // FromUnstructuredWithValidation converts an object from map[string]interface{} representation into a concrete type.
// It uses encoding/json/Unmarshaler if object implements it or reflection if not. // It uses encoding/json/Unmarshaler if object implements it or reflection if not.
// It takes a validationDirective that indicates how to behave when it encounters unknown fields. // It takes a validationDirective that indicates how to behave when it encounters unknown fields.
func (c *unstructuredConverter) FromUnstructuredWithValidation(u map[string]interface{}, obj interface{}, returnUnknownFields bool) error { func (c *unstructuredConverter) FromUnstructuredWithValidation(u map[string]interface{}, obj interface{}, returnUnknownFields bool) error {
@ -465,7 +465,7 @@ func sliceFromUnstructured(sv, dv reflect.Value, ctx *fromUnstructuredContext) e
} }
dv.SetBytes(data) dv.SetBytes(data)
} else { } else {
dv.Set(reflect.Zero(dt)) dv.Set(reflect.MakeSlice(dt, 0, 0))
} }
return nil return nil
} }

View File

@ -36,7 +36,7 @@ import (
utilnet "k8s.io/apimachinery/pkg/util/net" utilnet "k8s.io/apimachinery/pkg/util/net"
"k8s.io/apiserver/pkg/apis/apiserver" "k8s.io/apiserver/pkg/apis/apiserver"
egressmetrics "k8s.io/apiserver/pkg/server/egressselector/metrics" egressmetrics "k8s.io/apiserver/pkg/server/egressselector/metrics"
compbasemetrics "k8s.io/component-base/metrics" "k8s.io/component-base/metrics/legacyregistry"
"k8s.io/component-base/tracing" "k8s.io/component-base/tracing"
"k8s.io/klog/v2" "k8s.io/klog/v2"
client "sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client" client "sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client"
@ -45,7 +45,7 @@ import (
var directDialer utilnet.DialFunc = http.DefaultTransport.(*http.Transport).DialContext var directDialer utilnet.DialFunc = http.DefaultTransport.(*http.Transport).DialContext
func init() { func init() {
client.Metrics.RegisterMetrics(compbasemetrics.NewKubeRegistry().Registerer()) client.Metrics.RegisterMetrics(legacyregistry.Registerer())
} }
// EgressSelector is the map of network context type to context dialer, for network egress. // EgressSelector is the map of network context type to context dialer, for network egress.

View File

@ -11661,6 +11661,8 @@ var schemaYAML = typed.YAMLObject(`types:
elementType: elementType:
namedType: io.k8s.api.resource.v1alpha1.ResourceClaimConsumerReference namedType: io.k8s.api.resource.v1alpha1.ResourceClaimConsumerReference
elementRelationship: associative elementRelationship: associative
keys:
- uid
- name: io.k8s.api.resource.v1alpha1.ResourceClaimTemplate - name: io.k8s.api.resource.v1alpha1.ResourceClaimTemplate
map: map:
fields: fields:

View File

@ -24,19 +24,36 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
) )
// StaleGroupVersionError encasulates failed GroupVersion marked "stale"
// in the returned AggregatedDiscovery format.
type StaleGroupVersionError struct {
gv schema.GroupVersion
}
func (s StaleGroupVersionError) Error() string {
return fmt.Sprintf("stale GroupVersion discovery: %v", s.gv)
}
// SplitGroupsAndResources transforms "aggregated" discovery top-level structure into // SplitGroupsAndResources transforms "aggregated" discovery top-level structure into
// the previous "unaggregated" discovery groups and resources. // the previous "unaggregated" discovery groups and resources.
func SplitGroupsAndResources(aggregatedGroups apidiscovery.APIGroupDiscoveryList) (*metav1.APIGroupList, map[schema.GroupVersion]*metav1.APIResourceList) { func SplitGroupsAndResources(aggregatedGroups apidiscovery.APIGroupDiscoveryList) (
*metav1.APIGroupList,
map[schema.GroupVersion]*metav1.APIResourceList,
map[schema.GroupVersion]error) {
// Aggregated group list will contain the entirety of discovery, including // Aggregated group list will contain the entirety of discovery, including
// groups, versions, and resources. // groups, versions, and resources. GroupVersions marked "stale" are failed.
groups := []*metav1.APIGroup{} groups := []*metav1.APIGroup{}
failedGVs := map[schema.GroupVersion]error{}
resourcesByGV := map[schema.GroupVersion]*metav1.APIResourceList{} resourcesByGV := map[schema.GroupVersion]*metav1.APIResourceList{}
for _, aggGroup := range aggregatedGroups.Items { for _, aggGroup := range aggregatedGroups.Items {
group, resources := convertAPIGroup(aggGroup) group, resources, failed := convertAPIGroup(aggGroup)
groups = append(groups, group) groups = append(groups, group)
for gv, resourceList := range resources { for gv, resourceList := range resources {
resourcesByGV[gv] = resourceList resourcesByGV[gv] = resourceList
} }
for gv, err := range failed {
failedGVs[gv] = err
}
} }
// Transform slice of groups to group list before returning. // Transform slice of groups to group list before returning.
groupList := &metav1.APIGroupList{} groupList := &metav1.APIGroupList{}
@ -44,65 +61,94 @@ func SplitGroupsAndResources(aggregatedGroups apidiscovery.APIGroupDiscoveryList
for _, group := range groups { for _, group := range groups {
groupList.Groups = append(groupList.Groups, *group) groupList.Groups = append(groupList.Groups, *group)
} }
return groupList, resourcesByGV return groupList, resourcesByGV, failedGVs
} }
// convertAPIGroup tranforms an "aggregated" APIGroupDiscovery to an "legacy" APIGroup, // convertAPIGroup tranforms an "aggregated" APIGroupDiscovery to an "legacy" APIGroup,
// also returning the map of APIResourceList for resources within GroupVersions. // also returning the map of APIResourceList for resources within GroupVersions.
func convertAPIGroup(g apidiscovery.APIGroupDiscovery) (*metav1.APIGroup, map[schema.GroupVersion]*metav1.APIResourceList) { func convertAPIGroup(g apidiscovery.APIGroupDiscovery) (
*metav1.APIGroup,
map[schema.GroupVersion]*metav1.APIResourceList,
map[schema.GroupVersion]error) {
// Iterate through versions to convert to group and resources. // Iterate through versions to convert to group and resources.
group := &metav1.APIGroup{} group := &metav1.APIGroup{}
gvResources := map[schema.GroupVersion]*metav1.APIResourceList{} gvResources := map[schema.GroupVersion]*metav1.APIResourceList{}
failedGVs := map[schema.GroupVersion]error{}
group.Name = g.ObjectMeta.Name group.Name = g.ObjectMeta.Name
for i, v := range g.Versions { for _, v := range g.Versions {
version := metav1.GroupVersionForDiscovery{}
gv := schema.GroupVersion{Group: g.Name, Version: v.Version} gv := schema.GroupVersion{Group: g.Name, Version: v.Version}
if v.Freshness == apidiscovery.DiscoveryFreshnessStale {
failedGVs[gv] = StaleGroupVersionError{gv: gv}
continue
}
version := metav1.GroupVersionForDiscovery{}
version.GroupVersion = gv.String() version.GroupVersion = gv.String()
version.Version = v.Version version.Version = v.Version
group.Versions = append(group.Versions, version) group.Versions = append(group.Versions, version)
if i == 0 { // PreferredVersion is first non-stale Version
if group.PreferredVersion == (metav1.GroupVersionForDiscovery{}) {
group.PreferredVersion = version group.PreferredVersion = version
} }
resourceList := &metav1.APIResourceList{} resourceList := &metav1.APIResourceList{}
resourceList.GroupVersion = gv.String() resourceList.GroupVersion = gv.String()
for _, r := range v.Resources { for _, r := range v.Resources {
resource := convertAPIResource(r) resource, err := convertAPIResource(r)
resourceList.APIResources = append(resourceList.APIResources, resource) if err == nil {
resourceList.APIResources = append(resourceList.APIResources, resource)
}
// Subresources field in new format get transformed into full APIResources. // Subresources field in new format get transformed into full APIResources.
// It is possible a partial result with an error was returned to be used
// as the parent resource for the subresource.
for _, subresource := range r.Subresources { for _, subresource := range r.Subresources {
sr := convertAPISubresource(resource, subresource) sr, err := convertAPISubresource(resource, subresource)
resourceList.APIResources = append(resourceList.APIResources, sr) if err == nil {
resourceList.APIResources = append(resourceList.APIResources, sr)
}
} }
} }
gvResources[gv] = resourceList gvResources[gv] = resourceList
} }
return group, gvResources return group, gvResources, failedGVs
} }
// convertAPIResource tranforms a APIResourceDiscovery to an APIResource. // convertAPIResource tranforms a APIResourceDiscovery to an APIResource. We are
func convertAPIResource(in apidiscovery.APIResourceDiscovery) metav1.APIResource { // resilient to missing GVK, since this resource might be the parent resource
return metav1.APIResource{ // for a subresource. If the parent is missing a GVK, it is not returned in
// discovery, and the subresource MUST have the GVK.
func convertAPIResource(in apidiscovery.APIResourceDiscovery) (metav1.APIResource, error) {
result := metav1.APIResource{
Name: in.Resource, Name: in.Resource,
SingularName: in.SingularResource, SingularName: in.SingularResource,
Namespaced: in.Scope == apidiscovery.ScopeNamespace, Namespaced: in.Scope == apidiscovery.ScopeNamespace,
Group: in.ResponseKind.Group,
Version: in.ResponseKind.Version,
Kind: in.ResponseKind.Kind,
Verbs: in.Verbs, Verbs: in.Verbs,
ShortNames: in.ShortNames, ShortNames: in.ShortNames,
Categories: in.Categories, Categories: in.Categories,
} }
var err error
if in.ResponseKind != nil {
result.Group = in.ResponseKind.Group
result.Version = in.ResponseKind.Version
result.Kind = in.ResponseKind.Kind
} else {
err = fmt.Errorf("discovery resource %s missing GVK", in.Resource)
}
// Can return partial result with error, which can be the parent for a
// subresource. Do not add this result to the returned discovery resources.
return result, err
} }
// convertAPISubresource tranforms a APISubresourceDiscovery to an APIResource. // convertAPISubresource tranforms a APISubresourceDiscovery to an APIResource.
func convertAPISubresource(parent metav1.APIResource, in apidiscovery.APISubresourceDiscovery) metav1.APIResource { func convertAPISubresource(parent metav1.APIResource, in apidiscovery.APISubresourceDiscovery) (metav1.APIResource, error) {
return metav1.APIResource{ result := metav1.APIResource{}
Name: fmt.Sprintf("%s/%s", parent.Name, in.Subresource), if in.ResponseKind == nil {
SingularName: parent.SingularName, return result, fmt.Errorf("subresource %s/%s missing GVK", parent.Name, in.Subresource)
Namespaced: parent.Namespaced,
Group: in.ResponseKind.Group,
Version: in.ResponseKind.Version,
Kind: in.ResponseKind.Kind,
Verbs: in.Verbs,
} }
result.Name = fmt.Sprintf("%s/%s", parent.Name, in.Subresource)
result.SingularName = parent.SingularName
result.Namespaced = parent.Namespaced
result.Group = in.ResponseKind.Group
result.Version = in.ResponseKind.Version
result.Kind = in.ResponseKind.Kind
result.Verbs = in.Verbs
return result, nil
} }

View File

@ -33,6 +33,7 @@ import (
"k8s.io/client-go/openapi" "k8s.io/client-go/openapi"
cachedopenapi "k8s.io/client-go/openapi/cached" cachedopenapi "k8s.io/client-go/openapi/cached"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/klog/v2"
) )
type cacheEntry struct { type cacheEntry struct {
@ -61,6 +62,15 @@ var (
ErrCacheNotFound = errors.New("not found") ErrCacheNotFound = errors.New("not found")
) )
// Server returning empty ResourceList for Group/Version.
type emptyResponseError struct {
gv string
}
func (e *emptyResponseError) Error() string {
return fmt.Sprintf("received empty response for: %s", e.gv)
}
var _ discovery.CachedDiscoveryInterface = &memCacheClient{} var _ discovery.CachedDiscoveryInterface = &memCacheClient{}
// isTransientConnectionError checks whether given error is "Connection refused" or // isTransientConnectionError checks whether given error is "Connection refused" or
@ -103,7 +113,13 @@ func (d *memCacheClient) ServerResourcesForGroupVersion(groupVersion string) (*m
if cachedVal.err != nil && isTransientError(cachedVal.err) { if cachedVal.err != nil && isTransientError(cachedVal.err) {
r, err := d.serverResourcesForGroupVersion(groupVersion) r, err := d.serverResourcesForGroupVersion(groupVersion)
if err != nil { if err != nil {
utilruntime.HandleError(fmt.Errorf("couldn't get resource list for %v: %v", groupVersion, err)) // Don't log "empty response" as an error; it is a common response for metrics.
if _, emptyErr := err.(*emptyResponseError); emptyErr {
// Log at same verbosity as disk cache.
klog.V(3).Infof("%v", err)
} else {
utilruntime.HandleError(fmt.Errorf("couldn't get resource list for %v: %v", groupVersion, err))
}
} }
cachedVal = &cacheEntry{r, err} cachedVal = &cacheEntry{r, err}
d.groupToServerResources[groupVersion] = cachedVal d.groupToServerResources[groupVersion] = cachedVal
@ -120,32 +136,38 @@ func (d *memCacheClient) ServerGroupsAndResources() ([]*metav1.APIGroup, []*meta
// GroupsAndMaybeResources returns the list of APIGroups, and possibly the map of group/version // GroupsAndMaybeResources returns the list of APIGroups, and possibly the map of group/version
// to resources. The returned groups will never be nil, but the resources map can be nil // to resources. The returned groups will never be nil, but the resources map can be nil
// if there are no cached resources. // if there are no cached resources.
func (d *memCacheClient) GroupsAndMaybeResources() (*metav1.APIGroupList, map[schema.GroupVersion]*metav1.APIResourceList, error) { func (d *memCacheClient) GroupsAndMaybeResources() (*metav1.APIGroupList, map[schema.GroupVersion]*metav1.APIResourceList, map[schema.GroupVersion]error, error) {
d.lock.Lock() d.lock.Lock()
defer d.lock.Unlock() defer d.lock.Unlock()
if !d.cacheValid { if !d.cacheValid {
if err := d.refreshLocked(); err != nil { if err := d.refreshLocked(); err != nil {
return nil, nil, err return nil, nil, nil, err
} }
} }
// Build the resourceList from the cache? // Build the resourceList from the cache?
var resourcesMap map[schema.GroupVersion]*metav1.APIResourceList var resourcesMap map[schema.GroupVersion]*metav1.APIResourceList
var failedGVs map[schema.GroupVersion]error
if d.receivedAggregatedDiscovery && len(d.groupToServerResources) > 0 { if d.receivedAggregatedDiscovery && len(d.groupToServerResources) > 0 {
resourcesMap = map[schema.GroupVersion]*metav1.APIResourceList{} resourcesMap = map[schema.GroupVersion]*metav1.APIResourceList{}
failedGVs = map[schema.GroupVersion]error{}
for gv, cacheEntry := range d.groupToServerResources { for gv, cacheEntry := range d.groupToServerResources {
groupVersion, err := schema.ParseGroupVersion(gv) groupVersion, err := schema.ParseGroupVersion(gv)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("failed to parse group version (%v): %v", gv, err) return nil, nil, nil, fmt.Errorf("failed to parse group version (%v): %v", gv, err)
}
if cacheEntry.err != nil {
failedGVs[groupVersion] = cacheEntry.err
} else {
resourcesMap[groupVersion] = cacheEntry.resourceList
} }
resourcesMap[groupVersion] = cacheEntry.resourceList
} }
} }
return d.groupList, resourcesMap, nil return d.groupList, resourcesMap, failedGVs, nil
} }
func (d *memCacheClient) ServerGroups() (*metav1.APIGroupList, error) { func (d *memCacheClient) ServerGroups() (*metav1.APIGroupList, error) {
groups, _, err := d.GroupsAndMaybeResources() groups, _, _, err := d.GroupsAndMaybeResources()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -219,7 +241,8 @@ func (d *memCacheClient) refreshLocked() error {
if ad, ok := d.delegate.(discovery.AggregatedDiscoveryInterface); ok { if ad, ok := d.delegate.(discovery.AggregatedDiscoveryInterface); ok {
var resources map[schema.GroupVersion]*metav1.APIResourceList var resources map[schema.GroupVersion]*metav1.APIResourceList
gl, resources, err = ad.GroupsAndMaybeResources() var failedGVs map[schema.GroupVersion]error
gl, resources, failedGVs, err = ad.GroupsAndMaybeResources()
if resources != nil && err == nil { if resources != nil && err == nil {
// Cache the resources. // Cache the resources.
d.groupToServerResources = map[string]*cacheEntry{} d.groupToServerResources = map[string]*cacheEntry{}
@ -227,6 +250,10 @@ func (d *memCacheClient) refreshLocked() error {
for gv, resources := range resources { for gv, resources := range resources {
d.groupToServerResources[gv.String()] = &cacheEntry{resources, nil} d.groupToServerResources[gv.String()] = &cacheEntry{resources, nil}
} }
// Cache GroupVersion discovery errors
for gv, err := range failedGVs {
d.groupToServerResources[gv.String()] = &cacheEntry{nil, err}
}
d.receivedAggregatedDiscovery = true d.receivedAggregatedDiscovery = true
d.cacheValid = true d.cacheValid = true
return nil return nil
@ -252,7 +279,13 @@ func (d *memCacheClient) refreshLocked() error {
r, err := d.serverResourcesForGroupVersion(gv) r, err := d.serverResourcesForGroupVersion(gv)
if err != nil { if err != nil {
utilruntime.HandleError(fmt.Errorf("couldn't get resource list for %v: %v", gv, err)) // Don't log "empty response" as an error; it is a common response for metrics.
if _, emptyErr := err.(*emptyResponseError); emptyErr {
// Log at same verbosity as disk cache.
klog.V(3).Infof("%v", err)
} else {
utilruntime.HandleError(fmt.Errorf("couldn't get resource list for %v: %v", gv, err))
}
} }
resultLock.Lock() resultLock.Lock()
@ -274,7 +307,7 @@ func (d *memCacheClient) serverResourcesForGroupVersion(groupVersion string) (*m
return r, err return r, err
} }
if len(r.APIResources) == 0 { if len(r.APIResources) == 0 {
return r, fmt.Errorf("Got empty response for: %v", groupVersion) return r, &emptyResponseError{gv: groupVersion}
} }
return r, nil return r, nil
} }

View File

@ -20,6 +20,7 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"mime"
"net/http" "net/http"
"net/url" "net/url"
"sort" "sort"
@ -58,8 +59,9 @@ const (
defaultBurst = 300 defaultBurst = 300
AcceptV1 = runtime.ContentTypeJSON AcceptV1 = runtime.ContentTypeJSON
// Aggregated discovery content-type (currently v2beta1). NOTE: Currently, we are assuming the order // Aggregated discovery content-type (v2beta1). NOTE: content-type parameters
// for "g", "v", and "as" from the server. We can only compare this string if we can make that assumption. // MUST be ordered (g, v, as) for server in "Accept" header (BUT we are resilient
// to ordering when comparing returned values in "Content-Type" header).
AcceptV2Beta1 = runtime.ContentTypeJSON + ";" + "g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList" AcceptV2Beta1 = runtime.ContentTypeJSON + ";" + "g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList"
// Prioritize aggregated discovery by placing first in the order of discovery accept types. // Prioritize aggregated discovery by placing first in the order of discovery accept types.
acceptDiscoveryFormats = AcceptV2Beta1 + "," + AcceptV1 acceptDiscoveryFormats = AcceptV2Beta1 + "," + AcceptV1
@ -86,7 +88,7 @@ type DiscoveryInterface interface {
type AggregatedDiscoveryInterface interface { type AggregatedDiscoveryInterface interface {
DiscoveryInterface DiscoveryInterface
GroupsAndMaybeResources() (*metav1.APIGroupList, map[schema.GroupVersion]*metav1.APIResourceList, error) GroupsAndMaybeResources() (*metav1.APIGroupList, map[schema.GroupVersion]*metav1.APIResourceList, map[schema.GroupVersion]error, error)
} }
// CachedDiscoveryInterface is a DiscoveryInterface with cache invalidation and freshness. // CachedDiscoveryInterface is a DiscoveryInterface with cache invalidation and freshness.
@ -186,18 +188,23 @@ func apiVersionsToAPIGroup(apiVersions *metav1.APIVersions) (apiGroup metav1.API
// and resources from /api and /apis (either aggregated or not). Legacy groups // and resources from /api and /apis (either aggregated or not). Legacy groups
// must be ordered first. The server will either return both endpoints (/api, /apis) // must be ordered first. The server will either return both endpoints (/api, /apis)
// as aggregated discovery format or legacy format. For safety, resources will only // as aggregated discovery format or legacy format. For safety, resources will only
// be returned if both endpoints returned resources. // be returned if both endpoints returned resources. Returned "failedGVs" can be
func (d *DiscoveryClient) GroupsAndMaybeResources() (*metav1.APIGroupList, map[schema.GroupVersion]*metav1.APIResourceList, error) { // empty, but will only be nil in the case an error is returned.
func (d *DiscoveryClient) GroupsAndMaybeResources() (
*metav1.APIGroupList,
map[schema.GroupVersion]*metav1.APIResourceList,
map[schema.GroupVersion]error,
error) {
// Legacy group ordered first (there is only one -- core/v1 group). Returned groups must // Legacy group ordered first (there is only one -- core/v1 group). Returned groups must
// be non-nil, but it could be empty. Returned resources, apiResources map could be nil. // be non-nil, but it could be empty. Returned resources, apiResources map could be nil.
groups, resources, err := d.downloadLegacy() groups, resources, failedGVs, err := d.downloadLegacy()
if err != nil { if err != nil {
return nil, nil, err return nil, nil, nil, err
} }
// Discovery groups and (possibly) resources downloaded from /apis. // Discovery groups and (possibly) resources downloaded from /apis.
apiGroups, apiResources, aerr := d.downloadAPIs() apiGroups, apiResources, failedApisGVs, aerr := d.downloadAPIs()
if aerr != nil { if aerr != nil {
return nil, nil, aerr return nil, nil, nil, aerr
} }
// Merge apis groups into the legacy groups. // Merge apis groups into the legacy groups.
for _, group := range apiGroups.Groups { for _, group := range apiGroups.Groups {
@ -211,14 +218,23 @@ func (d *DiscoveryClient) GroupsAndMaybeResources() (*metav1.APIGroupList, map[s
} else if resources != nil { } else if resources != nil {
resources = nil resources = nil
} }
return groups, resources, err // Merge failed GroupVersions from /api and /apis
for gv, err := range failedApisGVs {
failedGVs[gv] = err
}
return groups, resources, failedGVs, err
} }
// downloadLegacy returns the discovery groups and possibly resources // downloadLegacy returns the discovery groups and possibly resources
// for the legacy v1 GVR at /api, or an error if one occurred. It is // for the legacy v1 GVR at /api, or an error if one occurred. It is
// possible for the resource map to be nil if the server returned // possible for the resource map to be nil if the server returned
// the unaggregated discovery. // the unaggregated discovery. Returned "failedGVs" can be empty, but
func (d *DiscoveryClient) downloadLegacy() (*metav1.APIGroupList, map[schema.GroupVersion]*metav1.APIResourceList, error) { // will only be nil in the case of a returned error.
func (d *DiscoveryClient) downloadLegacy() (
*metav1.APIGroupList,
map[schema.GroupVersion]*metav1.APIResourceList,
map[schema.GroupVersion]error,
error) {
accept := acceptDiscoveryFormats accept := acceptDiscoveryFormats
if d.UseLegacyDiscovery { if d.UseLegacyDiscovery {
accept = AcceptV1 accept = AcceptV1
@ -230,48 +246,55 @@ func (d *DiscoveryClient) downloadLegacy() (*metav1.APIGroupList, map[schema.Gro
Do(context.TODO()). Do(context.TODO()).
ContentType(&responseContentType). ContentType(&responseContentType).
Raw() Raw()
// Special error handling for 403 or 404 to be compatible with older v1.0 servers. apiGroupList := &metav1.APIGroupList{}
// Return empty group list to be merged with /apis. failedGVs := map[schema.GroupVersion]error{}
if err != nil && !errors.IsNotFound(err) && !errors.IsForbidden(err) { if err != nil {
return nil, nil, err // Tolerate 404, since aggregated api servers can return it.
} if errors.IsNotFound(err) {
if err != nil && (errors.IsNotFound(err) || errors.IsForbidden(err)) { // Return empty structures and no error.
return &metav1.APIGroupList{}, nil, nil emptyGVMap := map[schema.GroupVersion]*metav1.APIResourceList{}
return apiGroupList, emptyGVMap, failedGVs, nil
} else {
return nil, nil, nil, err
}
} }
apiGroupList := &metav1.APIGroupList{}
var resourcesByGV map[schema.GroupVersion]*metav1.APIResourceList var resourcesByGV map[schema.GroupVersion]*metav1.APIResourceList
// Switch on content-type server responded with: aggregated or unaggregated. // Switch on content-type server responded with: aggregated or unaggregated.
switch responseContentType { switch {
case AcceptV1: case isV2Beta1ContentType(responseContentType):
var aggregatedDiscovery apidiscovery.APIGroupDiscoveryList
err = json.Unmarshal(body, &aggregatedDiscovery)
if err != nil {
return nil, nil, nil, err
}
apiGroupList, resourcesByGV, failedGVs = SplitGroupsAndResources(aggregatedDiscovery)
default:
// Default is unaggregated discovery v1.
var v metav1.APIVersions var v metav1.APIVersions
err = json.Unmarshal(body, &v) err = json.Unmarshal(body, &v)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, nil, err
} }
apiGroup := metav1.APIGroup{} apiGroup := metav1.APIGroup{}
if len(v.Versions) != 0 { if len(v.Versions) != 0 {
apiGroup = apiVersionsToAPIGroup(&v) apiGroup = apiVersionsToAPIGroup(&v)
} }
apiGroupList.Groups = []metav1.APIGroup{apiGroup} apiGroupList.Groups = []metav1.APIGroup{apiGroup}
case AcceptV2Beta1:
var aggregatedDiscovery apidiscovery.APIGroupDiscoveryList
err = json.Unmarshal(body, &aggregatedDiscovery)
if err != nil {
return nil, nil, err
}
apiGroupList, resourcesByGV = SplitGroupsAndResources(aggregatedDiscovery)
default:
return nil, nil, fmt.Errorf("Unknown discovery response content-type: %s", responseContentType)
} }
return apiGroupList, resourcesByGV, nil return apiGroupList, resourcesByGV, failedGVs, nil
} }
// downloadAPIs returns the discovery groups and (if aggregated format) the // downloadAPIs returns the discovery groups and (if aggregated format) the
// discovery resources. The returned groups will always exist, but the // discovery resources. The returned groups will always exist, but the
// resources map may be nil. // resources map may be nil. Returned "failedGVs" can be empty, but will
func (d *DiscoveryClient) downloadAPIs() (*metav1.APIGroupList, map[schema.GroupVersion]*metav1.APIResourceList, error) { // only be nil in the case of a returned error.
func (d *DiscoveryClient) downloadAPIs() (
*metav1.APIGroupList,
map[schema.GroupVersion]*metav1.APIResourceList,
map[schema.GroupVersion]error,
error) {
accept := acceptDiscoveryFormats accept := acceptDiscoveryFormats
if d.UseLegacyDiscovery { if d.UseLegacyDiscovery {
accept = AcceptV1 accept = AcceptV1
@ -283,42 +306,59 @@ func (d *DiscoveryClient) downloadAPIs() (*metav1.APIGroupList, map[schema.Group
Do(context.TODO()). Do(context.TODO()).
ContentType(&responseContentType). ContentType(&responseContentType).
Raw() Raw()
// Special error handling for 403 or 404 to be compatible with older v1.0 servers. if err != nil {
// Return empty group list to be merged with /api. return nil, nil, nil, err
if err != nil && !errors.IsNotFound(err) && !errors.IsForbidden(err) {
return nil, nil, err
}
if err != nil && (errors.IsNotFound(err) || errors.IsForbidden(err)) {
return &metav1.APIGroupList{}, nil, nil
} }
apiGroupList := &metav1.APIGroupList{} apiGroupList := &metav1.APIGroupList{}
failedGVs := map[schema.GroupVersion]error{}
var resourcesByGV map[schema.GroupVersion]*metav1.APIResourceList var resourcesByGV map[schema.GroupVersion]*metav1.APIResourceList
// Switch on content-type server responded with: aggregated or unaggregated. // Switch on content-type server responded with: aggregated or unaggregated.
switch responseContentType { switch {
case AcceptV1: case isV2Beta1ContentType(responseContentType):
err = json.Unmarshal(body, apiGroupList)
if err != nil {
return nil, nil, err
}
case AcceptV2Beta1:
var aggregatedDiscovery apidiscovery.APIGroupDiscoveryList var aggregatedDiscovery apidiscovery.APIGroupDiscoveryList
err = json.Unmarshal(body, &aggregatedDiscovery) err = json.Unmarshal(body, &aggregatedDiscovery)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, nil, err
} }
apiGroupList, resourcesByGV = SplitGroupsAndResources(aggregatedDiscovery) apiGroupList, resourcesByGV, failedGVs = SplitGroupsAndResources(aggregatedDiscovery)
default: default:
return nil, nil, fmt.Errorf("Unknown discovery response content-type: %s", responseContentType) // Default is unaggregated discovery v1.
err = json.Unmarshal(body, apiGroupList)
if err != nil {
return nil, nil, nil, err
}
} }
return apiGroupList, resourcesByGV, nil return apiGroupList, resourcesByGV, failedGVs, nil
}
// isV2Beta1ContentType checks of the content-type string is both
// "application/json" and contains the v2beta1 content-type params.
// NOTE: This function is resilient to the ordering of the
// content-type parameters, as well as parameters added by
// intermediaries such as proxies or gateways. Examples:
//
// "application/json; g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList" = true
// "application/json; as=APIGroupDiscoveryList;v=v2beta1;g=apidiscovery.k8s.io" = true
// "application/json; as=APIGroupDiscoveryList;v=v2beta1;g=apidiscovery.k8s.io;charset=utf-8" = true
// "application/json" = false
// "application/json; charset=UTF-8" = false
func isV2Beta1ContentType(contentType string) bool {
base, params, err := mime.ParseMediaType(contentType)
if err != nil {
return false
}
return runtime.ContentTypeJSON == base &&
params["g"] == "apidiscovery.k8s.io" &&
params["v"] == "v2beta1" &&
params["as"] == "APIGroupDiscoveryList"
} }
// ServerGroups returns the supported groups, with information like supported versions and the // ServerGroups returns the supported groups, with information like supported versions and the
// preferred version. // preferred version.
func (d *DiscoveryClient) ServerGroups() (*metav1.APIGroupList, error) { func (d *DiscoveryClient) ServerGroups() (*metav1.APIGroupList, error) {
groups, _, err := d.GroupsAndMaybeResources() groups, _, _, err := d.GroupsAndMaybeResources()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -341,8 +381,10 @@ func (d *DiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (r
} }
err = d.restClient.Get().AbsPath(url.String()).Do(context.TODO()).Into(resources) err = d.restClient.Get().AbsPath(url.String()).Do(context.TODO()).Into(resources)
if err != nil { if err != nil {
// ignore 403 or 404 error to be compatible with an v1.0 server. // Tolerate core/v1 not found response by returning empty resource list;
if groupVersion == "v1" && (errors.IsNotFound(err) || errors.IsForbidden(err)) { // this probably should not happen. But we should verify all callers are
// not depending on this toleration before removal.
if groupVersion == "v1" && errors.IsNotFound(err) {
return resources, nil return resources, nil
} }
return nil, err return nil, err
@ -383,13 +425,14 @@ func IsGroupDiscoveryFailedError(err error) bool {
func ServerGroupsAndResources(d DiscoveryInterface) ([]*metav1.APIGroup, []*metav1.APIResourceList, error) { func ServerGroupsAndResources(d DiscoveryInterface) ([]*metav1.APIGroup, []*metav1.APIResourceList, error) {
var sgs *metav1.APIGroupList var sgs *metav1.APIGroupList
var resources []*metav1.APIResourceList var resources []*metav1.APIResourceList
var failedGVs map[schema.GroupVersion]error
var err error var err error
// If the passed discovery object implements the wider AggregatedDiscoveryInterface, // If the passed discovery object implements the wider AggregatedDiscoveryInterface,
// then attempt to retrieve aggregated discovery with both groups and the resources. // then attempt to retrieve aggregated discovery with both groups and the resources.
if ad, ok := d.(AggregatedDiscoveryInterface); ok { if ad, ok := d.(AggregatedDiscoveryInterface); ok {
var resourcesByGV map[schema.GroupVersion]*metav1.APIResourceList var resourcesByGV map[schema.GroupVersion]*metav1.APIResourceList
sgs, resourcesByGV, err = ad.GroupsAndMaybeResources() sgs, resourcesByGV, failedGVs, err = ad.GroupsAndMaybeResources()
for _, resourceList := range resourcesByGV { for _, resourceList := range resourcesByGV {
resources = append(resources, resourceList) resources = append(resources, resourceList)
} }
@ -404,8 +447,15 @@ func ServerGroupsAndResources(d DiscoveryInterface) ([]*metav1.APIGroup, []*meta
for i := range sgs.Groups { for i := range sgs.Groups {
resultGroups = append(resultGroups, &sgs.Groups[i]) resultGroups = append(resultGroups, &sgs.Groups[i])
} }
// resources is non-nil if aggregated discovery succeeded.
if resources != nil { if resources != nil {
return resultGroups, resources, nil // Any stale Group/Versions returned by aggregated discovery
// must be surfaced to the caller as failed Group/Versions.
var ferr error
if len(failedGVs) > 0 {
ferr = &ErrGroupDiscoveryFailed{Groups: failedGVs}
}
return resultGroups, resources, ferr
} }
groupVersionResources, failedGroups := fetchGroupVersionResources(d, sgs) groupVersionResources, failedGroups := fetchGroupVersionResources(d, sgs)
@ -436,16 +486,18 @@ func ServerPreferredResources(d DiscoveryInterface) ([]*metav1.APIResourceList,
var err error var err error
// If the passed discovery object implements the wider AggregatedDiscoveryInterface, // If the passed discovery object implements the wider AggregatedDiscoveryInterface,
// then it is attempt to retrieve both the groups and the resources. // then it is attempt to retrieve both the groups and the resources. "failedGroups"
// are Group/Versions returned as stale in AggregatedDiscovery format.
ad, ok := d.(AggregatedDiscoveryInterface) ad, ok := d.(AggregatedDiscoveryInterface)
if ok { if ok {
serverGroupList, groupVersionResources, err = ad.GroupsAndMaybeResources() serverGroupList, groupVersionResources, failedGroups, err = ad.GroupsAndMaybeResources()
} else { } else {
serverGroupList, err = d.ServerGroups() serverGroupList, err = d.ServerGroups()
} }
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Non-aggregated discovery must fetch resources from Groups.
if groupVersionResources == nil { if groupVersionResources == nil {
groupVersionResources, failedGroups = fetchGroupVersionResources(d, serverGroupList) groupVersionResources, failedGroups = fetchGroupVersionResources(d, serverGroupList)
} }

View File

@ -19,6 +19,7 @@ package openapi
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"strings"
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
"k8s.io/kube-openapi/pkg/handler3" "k8s.io/kube-openapi/pkg/handler3"
@ -58,7 +59,11 @@ func (c *client) Paths() (map[string]GroupVersion, error) {
// Create GroupVersions for each element of the result // Create GroupVersions for each element of the result
result := map[string]GroupVersion{} result := map[string]GroupVersion{}
for k, v := range discoMap.Paths { for k, v := range discoMap.Paths {
result[k] = newGroupVersion(c, v) // If the server returned a URL rooted at /openapi/v3, preserve any additional client-side prefix.
// If the server returned a URL not rooted at /openapi/v3, treat it as an actual server-relative URL.
// See https://github.com/kubernetes/kubernetes/issues/117463 for details
useClientPrefix := strings.HasPrefix(v.ServerRelativeURL, "/openapi/v3")
result[k] = newGroupVersion(c, v, useClientPrefix)
} }
return result, nil return result, nil
} }

View File

@ -18,6 +18,7 @@ package openapi
import ( import (
"context" "context"
"net/url"
"k8s.io/kube-openapi/pkg/handler3" "k8s.io/kube-openapi/pkg/handler3"
) )
@ -29,18 +30,41 @@ type GroupVersion interface {
} }
type groupversion struct { type groupversion struct {
client *client client *client
item handler3.OpenAPIV3DiscoveryGroupVersion item handler3.OpenAPIV3DiscoveryGroupVersion
useClientPrefix bool
} }
func newGroupVersion(client *client, item handler3.OpenAPIV3DiscoveryGroupVersion) *groupversion { func newGroupVersion(client *client, item handler3.OpenAPIV3DiscoveryGroupVersion, useClientPrefix bool) *groupversion {
return &groupversion{client: client, item: item} return &groupversion{client: client, item: item, useClientPrefix: useClientPrefix}
} }
func (g *groupversion) Schema(contentType string) ([]byte, error) { func (g *groupversion) Schema(contentType string) ([]byte, error) {
return g.client.restClient.Get(). if !g.useClientPrefix {
RequestURI(g.item.ServerRelativeURL). return g.client.restClient.Get().
SetHeader("Accept", contentType). RequestURI(g.item.ServerRelativeURL).
Do(context.TODO()). SetHeader("Accept", contentType).
Raw() Do(context.TODO()).
Raw()
}
locator, err := url.Parse(g.item.ServerRelativeURL)
if err != nil {
return nil, err
}
path := g.client.restClient.Get().
AbsPath(locator.Path).
SetHeader("Accept", contentType)
// Other than root endpoints(openapiv3/apis), resources have hash query parameter to support etags.
// However, absPath does not support handling query parameters internally,
// so that hash query parameter is added manually
for k, value := range locator.Query() {
for _, v := range value {
path.Param(k, v)
}
}
return path.Do(context.TODO()).Raw()
} }

View File

@ -353,17 +353,6 @@ func NewIndexerInformer(
return clientState, newInformer(lw, objType, resyncPeriod, h, clientState, nil) return clientState, newInformer(lw, objType, resyncPeriod, h, clientState, nil)
} }
// TransformFunc allows for transforming an object before it will be processed
// and put into the controller cache and before the corresponding handlers will
// be called on it.
// TransformFunc (similarly to ResourceEventHandler functions) should be able
// to correctly handle the tombstone of type cache.DeletedFinalStateUnknown
//
// The most common usage pattern is to clean-up some parts of the object to
// reduce component memory usage if a given component doesn't care about them.
// given controller doesn't care for them
type TransformFunc func(interface{}) (interface{}, error)
// NewTransformingInformer returns a Store and a controller for populating // NewTransformingInformer returns a Store and a controller for populating
// the store while also providing event notifications. You should only used // the store while also providing event notifications. You should only used
// the returned Store for Get/List operations; Add/Modify/Deletes will cause // the returned Store for Get/List operations; Add/Modify/Deletes will cause
@ -411,19 +400,11 @@ func processDeltas(
// Object which receives event notifications from the given deltas // Object which receives event notifications from the given deltas
handler ResourceEventHandler, handler ResourceEventHandler,
clientState Store, clientState Store,
transformer TransformFunc,
deltas Deltas, deltas Deltas,
) error { ) error {
// from oldest to newest // from oldest to newest
for _, d := range deltas { for _, d := range deltas {
obj := d.Object obj := d.Object
if transformer != nil {
var err error
obj, err = transformer(obj)
if err != nil {
return err
}
}
switch d.Type { switch d.Type {
case Sync, Replaced, Added, Updated: case Sync, Replaced, Added, Updated:
@ -475,6 +456,7 @@ func newInformer(
fifo := NewDeltaFIFOWithOptions(DeltaFIFOOptions{ fifo := NewDeltaFIFOWithOptions(DeltaFIFOOptions{
KnownObjects: clientState, KnownObjects: clientState,
EmitDeltaTypeReplaced: true, EmitDeltaTypeReplaced: true,
Transformer: transformer,
}) })
cfg := &Config{ cfg := &Config{
@ -486,7 +468,7 @@ func newInformer(
Process: func(obj interface{}) error { Process: func(obj interface{}) error {
if deltas, ok := obj.(Deltas); ok { if deltas, ok := obj.(Deltas); ok {
return processDeltas(h, clientState, transformer, deltas) return processDeltas(h, clientState, deltas)
} }
return errors.New("object given as Process argument is not Deltas") return errors.New("object given as Process argument is not Deltas")
}, },

View File

@ -51,6 +51,10 @@ type DeltaFIFOOptions struct {
// When true, `Replaced` events will be sent for items passed to a Replace() call. // When true, `Replaced` events will be sent for items passed to a Replace() call.
// When false, `Sync` events will be sent instead. // When false, `Sync` events will be sent instead.
EmitDeltaTypeReplaced bool EmitDeltaTypeReplaced bool
// If set, will be called for objects before enqueueing them. Please
// see the comment on TransformFunc for details.
Transformer TransformFunc
} }
// DeltaFIFO is like FIFO, but differs in two ways. One is that the // DeltaFIFO is like FIFO, but differs in two ways. One is that the
@ -129,8 +133,32 @@ type DeltaFIFO struct {
// emitDeltaTypeReplaced is whether to emit the Replaced or Sync // emitDeltaTypeReplaced is whether to emit the Replaced or Sync
// DeltaType when Replace() is called (to preserve backwards compat). // DeltaType when Replace() is called (to preserve backwards compat).
emitDeltaTypeReplaced bool emitDeltaTypeReplaced bool
// Called with every object if non-nil.
transformer TransformFunc
} }
// TransformFunc allows for transforming an object before it will be processed.
// TransformFunc (similarly to ResourceEventHandler functions) should be able
// to correctly handle the tombstone of type cache.DeletedFinalStateUnknown.
//
// New in v1.27: In such cases, the contained object will already have gone
// through the transform object separately (when it was added / updated prior
// to the delete), so the TransformFunc can likely safely ignore such objects
// (i.e., just return the input object).
//
// The most common usage pattern is to clean-up some parts of the object to
// reduce component memory usage if a given component doesn't care about them.
//
// New in v1.27: unless the object is a DeletedFinalStateUnknown, TransformFunc
// sees the object before any other actor, and it is now safe to mutate the
// object in place instead of making a copy.
//
// Note that TransformFunc is called while inserting objects into the
// notification queue and is therefore extremely performance sensitive; please
// do not do anything that will take a long time.
type TransformFunc func(interface{}) (interface{}, error)
// DeltaType is the type of a change (addition, deletion, etc) // DeltaType is the type of a change (addition, deletion, etc)
type DeltaType string type DeltaType string
@ -227,6 +255,7 @@ func NewDeltaFIFOWithOptions(opts DeltaFIFOOptions) *DeltaFIFO {
knownObjects: opts.KnownObjects, knownObjects: opts.KnownObjects,
emitDeltaTypeReplaced: opts.EmitDeltaTypeReplaced, emitDeltaTypeReplaced: opts.EmitDeltaTypeReplaced,
transformer: opts.Transformer,
} }
f.cond.L = &f.lock f.cond.L = &f.lock
return f return f
@ -411,6 +440,21 @@ func (f *DeltaFIFO) queueActionLocked(actionType DeltaType, obj interface{}) err
if err != nil { if err != nil {
return KeyError{obj, err} return KeyError{obj, err}
} }
// Every object comes through this code path once, so this is a good
// place to call the transform func. If obj is a
// DeletedFinalStateUnknown tombstone, then the containted inner object
// will already have gone through the transformer, but we document that
// this can happen. In cases involving Replace(), such an object can
// come through multiple times.
if f.transformer != nil {
var err error
obj, err = f.transformer(obj)
if err != nil {
return err
}
}
oldDeltas := f.items[id] oldDeltas := f.items[id]
newDeltas := append(oldDeltas, Delta{actionType, obj}) newDeltas := append(oldDeltas, Delta{actionType, obj})
newDeltas = dedupDeltas(newDeltas) newDeltas = dedupDeltas(newDeltas)
@ -566,12 +610,11 @@ func (f *DeltaFIFO) Pop(process PopProcessFunc) (interface{}, error) {
// using the Sync or Replace DeltaType and then (2) it does some deletions. // using the Sync or Replace DeltaType and then (2) it does some deletions.
// In particular: for every pre-existing key K that is not the key of // In particular: for every pre-existing key K that is not the key of
// an object in `list` there is the effect of // an object in `list` there is the effect of
// `Delete(DeletedFinalStateUnknown{K, O})` where O is current object // `Delete(DeletedFinalStateUnknown{K, O})` where O is the latest known
// of K. If `f.knownObjects == nil` then the pre-existing keys are // object of K. The pre-existing keys are those in the union set of the keys in
// those in `f.items` and the current object of K is the `.Newest()` // `f.items` and `f.knownObjects` (if not nil). The last known object for key K is
// of the Deltas associated with K. Otherwise the pre-existing keys // the one present in the last delta in `f.items`. If there is no delta for K
// are those listed by `f.knownObjects` and the current object of K is // in `f.items`, it is the object in `f.knownObjects`
// what `f.knownObjects.GetByKey(K)` returns.
func (f *DeltaFIFO) Replace(list []interface{}, _ string) error { func (f *DeltaFIFO) Replace(list []interface{}, _ string) error {
f.lock.Lock() f.lock.Lock()
defer f.lock.Unlock() defer f.lock.Unlock()
@ -595,56 +638,54 @@ func (f *DeltaFIFO) Replace(list []interface{}, _ string) error {
} }
} }
if f.knownObjects == nil { // Do deletion detection against objects in the queue
// Do deletion detection against our own list. queuedDeletions := 0
queuedDeletions := 0 for k, oldItem := range f.items {
for k, oldItem := range f.items { if keys.Has(k) {
continue
}
// Delete pre-existing items not in the new list.
// This could happen if watch deletion event was missed while
// disconnected from apiserver.
var deletedObj interface{}
if n := oldItem.Newest(); n != nil {
deletedObj = n.Object
// if the previous object is a DeletedFinalStateUnknown, we have to extract the actual Object
if d, ok := deletedObj.(DeletedFinalStateUnknown); ok {
deletedObj = d.Obj
}
}
queuedDeletions++
if err := f.queueActionLocked(Deleted, DeletedFinalStateUnknown{k, deletedObj}); err != nil {
return err
}
}
if f.knownObjects != nil {
// Detect deletions for objects not present in the queue, but present in KnownObjects
knownKeys := f.knownObjects.ListKeys()
for _, k := range knownKeys {
if keys.Has(k) { if keys.Has(k) {
continue continue
} }
// Delete pre-existing items not in the new list. if len(f.items[k]) > 0 {
// This could happen if watch deletion event was missed while continue
// disconnected from apiserver. }
var deletedObj interface{}
if n := oldItem.Newest(); n != nil { deletedObj, exists, err := f.knownObjects.GetByKey(k)
deletedObj = n.Object if err != nil {
deletedObj = nil
klog.Errorf("Unexpected error %v during lookup of key %v, placing DeleteFinalStateUnknown marker without object", err, k)
} else if !exists {
deletedObj = nil
klog.Infof("Key %v does not exist in known objects store, placing DeleteFinalStateUnknown marker without object", k)
} }
queuedDeletions++ queuedDeletions++
if err := f.queueActionLocked(Deleted, DeletedFinalStateUnknown{k, deletedObj}); err != nil { if err := f.queueActionLocked(Deleted, DeletedFinalStateUnknown{k, deletedObj}); err != nil {
return err return err
} }
} }
if !f.populated {
f.populated = true
// While there shouldn't be any queued deletions in the initial
// population of the queue, it's better to be on the safe side.
f.initialPopulationCount = keys.Len() + queuedDeletions
}
return nil
}
// Detect deletions not already in the queue.
knownKeys := f.knownObjects.ListKeys()
queuedDeletions := 0
for _, k := range knownKeys {
if keys.Has(k) {
continue
}
deletedObj, exists, err := f.knownObjects.GetByKey(k)
if err != nil {
deletedObj = nil
klog.Errorf("Unexpected error %v during lookup of key %v, placing DeleteFinalStateUnknown marker without object", err, k)
} else if !exists {
deletedObj = nil
klog.Infof("Key %v does not exist in known objects store, placing DeleteFinalStateUnknown marker without object", k)
}
queuedDeletions++
if err := f.queueActionLocked(Deleted, DeletedFinalStateUnknown{k, deletedObj}); err != nil {
return err
}
} }
if !f.populated { if !f.populated {

View File

@ -198,10 +198,7 @@ type SharedInformer interface {
// //
// Must be set before starting the informer. // Must be set before starting the informer.
// //
// Note: Since the object given to the handler may be already shared with // Please see the comment on TransformFunc for more details.
// other goroutines, it is advisable to copy the object being
// transform before mutating it at all and returning the copy to prevent
// data races.
SetTransform(handler TransformFunc) error SetTransform(handler TransformFunc) error
// IsStopped reports whether the informer has already been stopped. // IsStopped reports whether the informer has already been stopped.
@ -422,6 +419,7 @@ func (s *sharedIndexInformer) Run(stopCh <-chan struct{}) {
fifo := NewDeltaFIFOWithOptions(DeltaFIFOOptions{ fifo := NewDeltaFIFOWithOptions(DeltaFIFOOptions{
KnownObjects: s.indexer, KnownObjects: s.indexer,
EmitDeltaTypeReplaced: true, EmitDeltaTypeReplaced: true,
Transformer: s.transform,
}) })
cfg := &Config{ cfg := &Config{
@ -585,7 +583,7 @@ func (s *sharedIndexInformer) HandleDeltas(obj interface{}) error {
defer s.blockDeltas.Unlock() defer s.blockDeltas.Unlock()
if deltas, ok := obj.(Deltas); ok { if deltas, ok := obj.(Deltas); ok {
return processDeltas(s, s.indexer, s.transform, deltas) return processDeltas(s, s.indexer, deltas)
} }
return errors.New("object given as Process argument is not Deltas") return errors.New("object given as Process argument is not Deltas")
} }

View File

@ -109,7 +109,7 @@ func (c *tlsTransportCache) get(config *Config) (http.RoundTripper, error) {
// If we use are reloading files, we need to handle certificate rotation properly // If we use are reloading files, we need to handle certificate rotation properly
// TODO(jackkleeman): We can also add rotation here when config.HasCertCallback() is true // TODO(jackkleeman): We can also add rotation here when config.HasCertCallback() is true
if config.TLS.ReloadTLSFiles { if config.TLS.ReloadTLSFiles && tlsConfig != nil && tlsConfig.GetClientCertificate != nil {
dynamicCertDialer := certRotatingDialer(tlsConfig.GetClientCertificate, dial) dynamicCertDialer := certRotatingDialer(tlsConfig.GetClientCertificate, dial)
tlsConfig.GetClientCertificate = dynamicCertDialer.GetClientCertificate tlsConfig.GetClientCertificate = dynamicCertDialer.GetClientCertificate
dial = dynamicCertDialer.connDialer.DialContext dial = dynamicCertDialer.connDialer.DialContext

View File

@ -25,6 +25,7 @@ import (
"crypto/x509/pkix" "crypto/x509/pkix"
"encoding/pem" "encoding/pem"
"fmt" "fmt"
"math"
"math/big" "math/big"
"net" "net"
"os" "os"
@ -57,8 +58,14 @@ type AltNames struct {
// NewSelfSignedCACert creates a CA certificate // NewSelfSignedCACert creates a CA certificate
func NewSelfSignedCACert(cfg Config, key crypto.Signer) (*x509.Certificate, error) { func NewSelfSignedCACert(cfg Config, key crypto.Signer) (*x509.Certificate, error) {
now := time.Now() now := time.Now()
// returns a uniform random value in [0, max-1), then add 1 to serial to make it a uniform random value in [1, max).
serial, err := cryptorand.Int(cryptorand.Reader, new(big.Int).SetInt64(math.MaxInt64-1))
if err != nil {
return nil, err
}
serial = new(big.Int).Add(serial, big.NewInt(1))
tmpl := x509.Certificate{ tmpl := x509.Certificate{
SerialNumber: new(big.Int).SetInt64(0), SerialNumber: serial,
Subject: pkix.Name{ Subject: pkix.Name{
CommonName: cfg.CommonName, CommonName: cfg.CommonName,
Organization: cfg.Organization, Organization: cfg.Organization,
@ -116,9 +123,14 @@ func GenerateSelfSignedCertKeyWithFixtures(host string, alternateIPs []net.IP, a
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
// returns a uniform random value in [0, max-1), then add 1 to serial to make it a uniform random value in [1, max).
serial, err := cryptorand.Int(cryptorand.Reader, new(big.Int).SetInt64(math.MaxInt64-1))
if err != nil {
return nil, nil, err
}
serial = new(big.Int).Add(serial, big.NewInt(1))
caTemplate := x509.Certificate{ caTemplate := x509.Certificate{
SerialNumber: big.NewInt(1), SerialNumber: serial,
Subject: pkix.Name{ Subject: pkix.Name{
CommonName: fmt.Sprintf("%s-ca@%d", host, time.Now().Unix()), CommonName: fmt.Sprintf("%s-ca@%d", host, time.Now().Unix()),
}, },
@ -144,9 +156,14 @@ func GenerateSelfSignedCertKeyWithFixtures(host string, alternateIPs []net.IP, a
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
// returns a uniform random value in [0, max-1), then add 1 to serial to make it a uniform random value in [1, max).
serial, err = cryptorand.Int(cryptorand.Reader, new(big.Int).SetInt64(math.MaxInt64-1))
if err != nil {
return nil, nil, err
}
serial = new(big.Int).Add(serial, big.NewInt(1))
template := x509.Certificate{ template := x509.Certificate{
SerialNumber: big.NewInt(2), SerialNumber: serial,
Subject: pkix.Name{ Subject: pkix.Name{
CommonName: fmt.Sprintf("%s@%d", host, time.Now().Unix()), CommonName: fmt.Sprintf("%s@%d", host, time.Now().Unix()),
}, },

View File

@ -218,6 +218,11 @@ type Route struct {
Name string Name string
// TargetNode is the NodeName of the target instance. // TargetNode is the NodeName of the target instance.
TargetNode types.NodeName TargetNode types.NodeName
// EnableNodeAddresses is a feature gate for TargetNodeAddresses. If false, ignore TargetNodeAddresses.
// Without this, if users haven't updated their cloud-provider, reconcile() will delete and create same route every time.
EnableNodeAddresses bool
// TargetNodeAddresses are the Node IPs of the target Node.
TargetNodeAddresses []v1.NodeAddress
// DestinationCIDR is the CIDR format IP range that this routing rule // DestinationCIDR is the CIDR format IP range that this routing rule
// applies to. // applies to.
DestinationCIDR string DestinationCIDR string

View File

@ -36,6 +36,9 @@ type vmoduleConfigurationPFlag struct {
// String returns the -vmodule parameter (comma-separated list of pattern=N). // String returns the -vmodule parameter (comma-separated list of pattern=N).
func (wrapper vmoduleConfigurationPFlag) String() string { func (wrapper vmoduleConfigurationPFlag) String() string {
if wrapper.value == nil {
return ""
}
var patterns []string var patterns []string
for _, item := range *wrapper.value { for _, item := range *wrapper.value {
patterns = append(patterns, fmt.Sprintf("%s=%d", item.FilePattern, item.Verbosity)) patterns = append(patterns, fmt.Sprintf("%s=%d", item.FilePattern, item.Verbosity))
@ -82,10 +85,16 @@ type verbosityLevelPflag struct {
} }
func (wrapper verbosityLevelPflag) String() string { func (wrapper verbosityLevelPflag) String() string {
if wrapper.value == nil {
return "0"
}
return strconv.FormatInt(int64(*wrapper.value), 10) return strconv.FormatInt(int64(*wrapper.value), 10)
} }
func (wrapper verbosityLevelPflag) Get() interface{} { func (wrapper verbosityLevelPflag) Get() interface{} {
if wrapper.value == nil {
return VerbosityLevel(0)
}
return *wrapper.value return *wrapper.value
} }

View File

@ -42,6 +42,9 @@ var (
// Register registers a collectable metric but uses the global registry // Register registers a collectable metric but uses the global registry
Register = defaultRegistry.Register Register = defaultRegistry.Register
// Registerer exposes the global registerer
Registerer = defaultRegistry.Registerer
) )
func init() { func init() {

View File

@ -216,7 +216,6 @@ var noopCounterVec = &prometheus.CounterVec{}
var noopHistogramVec = &prometheus.HistogramVec{} var noopHistogramVec = &prometheus.HistogramVec{}
var noopTimingHistogramVec = &promext.TimingHistogramVec{} var noopTimingHistogramVec = &promext.TimingHistogramVec{}
var noopGaugeVec = &prometheus.GaugeVec{} var noopGaugeVec = &prometheus.GaugeVec{}
var noopObserverVec = &noopObserverVector{}
// just use a convenience struct for all the no-ops // just use a convenience struct for all the no-ops
var noop = &noopMetric{} var noop = &noopMetric{}
@ -235,22 +234,3 @@ func (noopMetric) Desc() *prometheus.Desc { return nil }
func (noopMetric) Write(*dto.Metric) error { return nil } func (noopMetric) Write(*dto.Metric) error { return nil }
func (noopMetric) Describe(chan<- *prometheus.Desc) {} func (noopMetric) Describe(chan<- *prometheus.Desc) {}
func (noopMetric) Collect(chan<- prometheus.Metric) {} func (noopMetric) Collect(chan<- prometheus.Metric) {}
type noopObserverVector struct{}
func (noopObserverVector) GetMetricWith(prometheus.Labels) (prometheus.Observer, error) {
return noop, nil
}
func (noopObserverVector) GetMetricWithLabelValues(...string) (prometheus.Observer, error) {
return noop, nil
}
func (noopObserverVector) With(prometheus.Labels) prometheus.Observer { return noop }
func (noopObserverVector) WithLabelValues(...string) prometheus.Observer { return noop }
func (noopObserverVector) CurryWith(prometheus.Labels) (prometheus.ObserverVec, error) {
return noopObserverVec, nil
}
func (noopObserverVector) MustCurryWith(prometheus.Labels) prometheus.ObserverVec {
return noopObserverVec
}
func (noopObserverVector) Describe(chan<- *prometheus.Desc) {}
func (noopObserverVector) Collect(chan<- prometheus.Metric) {}

78
vendor/modules.txt vendored
View File

@ -745,7 +745,7 @@ gopkg.in/yaml.v2
# gopkg.in/yaml.v3 v3.0.1 # gopkg.in/yaml.v3 v3.0.1
## explicit ## explicit
gopkg.in/yaml.v3 gopkg.in/yaml.v3
# k8s.io/api v0.26.1 => k8s.io/api v0.26.1 # k8s.io/api v0.26.7 => k8s.io/api v0.26.7
## explicit; go 1.19 ## explicit; go 1.19
k8s.io/api/admission/v1 k8s.io/api/admission/v1
k8s.io/api/admission/v1beta1 k8s.io/api/admission/v1beta1
@ -800,11 +800,11 @@ k8s.io/api/scheduling/v1beta1
k8s.io/api/storage/v1 k8s.io/api/storage/v1
k8s.io/api/storage/v1alpha1 k8s.io/api/storage/v1alpha1
k8s.io/api/storage/v1beta1 k8s.io/api/storage/v1beta1
# k8s.io/apiextensions-apiserver v0.26.1 => k8s.io/apiextensions-apiserver v0.26.1 # k8s.io/apiextensions-apiserver v0.26.7 => k8s.io/apiextensions-apiserver v0.26.7
## explicit; go 1.19 ## explicit; go 1.19
k8s.io/apiextensions-apiserver/pkg/apis/apiextensions k8s.io/apiextensions-apiserver/pkg/apis/apiextensions
k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1 k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1
# k8s.io/apimachinery v0.26.1 => k8s.io/apimachinery v0.26.1 # k8s.io/apimachinery v0.26.7 => k8s.io/apimachinery v0.26.7
## explicit; go 1.19 ## explicit; go 1.19
k8s.io/apimachinery/pkg/api/equality k8s.io/apimachinery/pkg/api/equality
k8s.io/apimachinery/pkg/api/errors k8s.io/apimachinery/pkg/api/errors
@ -860,7 +860,7 @@ k8s.io/apimachinery/pkg/watch
k8s.io/apimachinery/third_party/forked/golang/json k8s.io/apimachinery/third_party/forked/golang/json
k8s.io/apimachinery/third_party/forked/golang/netutil k8s.io/apimachinery/third_party/forked/golang/netutil
k8s.io/apimachinery/third_party/forked/golang/reflect k8s.io/apimachinery/third_party/forked/golang/reflect
# k8s.io/apiserver v0.26.1 => k8s.io/apiserver v0.26.1 # k8s.io/apiserver v0.26.7 => k8s.io/apiserver v0.26.7
## explicit; go 1.19 ## explicit; go 1.19
k8s.io/apiserver/pkg/admission k8s.io/apiserver/pkg/admission
k8s.io/apiserver/pkg/admission/configuration k8s.io/apiserver/pkg/admission/configuration
@ -898,7 +898,7 @@ k8s.io/apiserver/pkg/util/feature
k8s.io/apiserver/pkg/util/webhook k8s.io/apiserver/pkg/util/webhook
k8s.io/apiserver/pkg/util/x509metrics k8s.io/apiserver/pkg/util/x509metrics
k8s.io/apiserver/pkg/warning k8s.io/apiserver/pkg/warning
# k8s.io/client-go v12.0.0+incompatible => k8s.io/client-go v0.26.1 # k8s.io/client-go v12.0.0+incompatible => k8s.io/client-go v0.26.7
## explicit; go 1.19 ## explicit; go 1.19
k8s.io/client-go/applyconfigurations/admissionregistration/v1 k8s.io/client-go/applyconfigurations/admissionregistration/v1
k8s.io/client-go/applyconfigurations/admissionregistration/v1alpha1 k8s.io/client-go/applyconfigurations/admissionregistration/v1alpha1
@ -1160,12 +1160,12 @@ k8s.io/client-go/util/homedir
k8s.io/client-go/util/keyutil k8s.io/client-go/util/keyutil
k8s.io/client-go/util/retry k8s.io/client-go/util/retry
k8s.io/client-go/util/workqueue k8s.io/client-go/util/workqueue
# k8s.io/cloud-provider v0.26.1 => k8s.io/cloud-provider v0.26.1 # k8s.io/cloud-provider v0.26.7 => k8s.io/cloud-provider v0.26.7
## explicit; go 1.19 ## explicit; go 1.19
k8s.io/cloud-provider k8s.io/cloud-provider
k8s.io/cloud-provider/volume k8s.io/cloud-provider/volume
k8s.io/cloud-provider/volume/helpers k8s.io/cloud-provider/volume/helpers
# k8s.io/component-base v0.26.1 => k8s.io/component-base v0.26.1 # k8s.io/component-base v0.26.7 => k8s.io/component-base v0.26.7
## explicit; go 1.19 ## explicit; go 1.19
k8s.io/component-base/cli/flag k8s.io/component-base/cli/flag
k8s.io/component-base/config k8s.io/component-base/config
@ -1181,7 +1181,7 @@ k8s.io/component-base/metrics/testutil
k8s.io/component-base/tracing k8s.io/component-base/tracing
k8s.io/component-base/tracing/api/v1 k8s.io/component-base/tracing/api/v1
k8s.io/component-base/version k8s.io/component-base/version
# k8s.io/component-helpers v0.26.1 => k8s.io/component-helpers v0.26.1 # k8s.io/component-helpers v0.26.7 => k8s.io/component-helpers v0.26.7
## explicit; go 1.19 ## explicit; go 1.19
k8s.io/component-helpers/node/util/sysctl k8s.io/component-helpers/node/util/sysctl
k8s.io/component-helpers/scheduling/corev1 k8s.io/component-helpers/scheduling/corev1
@ -1209,11 +1209,11 @@ k8s.io/kube-openapi/pkg/schemamutation
k8s.io/kube-openapi/pkg/spec3 k8s.io/kube-openapi/pkg/spec3
k8s.io/kube-openapi/pkg/util/proto k8s.io/kube-openapi/pkg/util/proto
k8s.io/kube-openapi/pkg/validation/spec k8s.io/kube-openapi/pkg/validation/spec
# k8s.io/kubectl v0.0.0 => k8s.io/kubectl v0.26.1 # k8s.io/kubectl v0.0.0 => k8s.io/kubectl v0.26.7
## explicit; go 1.19 ## explicit; go 1.19
k8s.io/kubectl/pkg/scale k8s.io/kubectl/pkg/scale
k8s.io/kubectl/pkg/util/podutils k8s.io/kubectl/pkg/util/podutils
# k8s.io/kubelet v0.0.0 => k8s.io/kubelet v0.26.1 # k8s.io/kubelet v0.0.0 => k8s.io/kubelet v0.26.7
## explicit; go 1.19 ## explicit; go 1.19
k8s.io/kubelet/pkg/apis/stats/v1alpha1 k8s.io/kubelet/pkg/apis/stats/v1alpha1
# k8s.io/kubernetes v1.26.1 # k8s.io/kubernetes v1.26.1
@ -1281,10 +1281,10 @@ k8s.io/kubernetes/test/e2e/testing-manifests
k8s.io/kubernetes/test/utils k8s.io/kubernetes/test/utils
k8s.io/kubernetes/test/utils/image k8s.io/kubernetes/test/utils/image
k8s.io/kubernetes/test/utils/kubeconfig k8s.io/kubernetes/test/utils/kubeconfig
# k8s.io/mount-utils v0.26.1 => k8s.io/mount-utils v0.26.1 # k8s.io/mount-utils v0.26.7 => k8s.io/mount-utils v0.26.7
## explicit; go 1.19 ## explicit; go 1.19
k8s.io/mount-utils k8s.io/mount-utils
# k8s.io/pod-security-admission v0.0.0 => k8s.io/pod-security-admission v0.26.1 # k8s.io/pod-security-admission v0.0.0 => k8s.io/pod-security-admission v0.26.7
## explicit; go 1.19 ## explicit; go 1.19
k8s.io/pod-security-admission/api k8s.io/pod-security-admission/api
k8s.io/pod-security-admission/policy k8s.io/pod-security-admission/policy
@ -1307,7 +1307,7 @@ k8s.io/utils/pointer
k8s.io/utils/strings k8s.io/utils/strings
k8s.io/utils/strings/slices k8s.io/utils/strings/slices
k8s.io/utils/trace k8s.io/utils/trace
# sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.35 # sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.37
## explicit; go 1.17 ## explicit; go 1.17
sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client
sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/metrics sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/metrics
@ -1373,30 +1373,30 @@ sigs.k8s.io/yaml
# go.opentelemetry.io/otel/sdk => go.opentelemetry.io/otel/sdk v1.11.1 # go.opentelemetry.io/otel/sdk => go.opentelemetry.io/otel/sdk v1.11.1
# go.opentelemetry.io/otel/trace => go.opentelemetry.io/otel/trace v1.11.2 # go.opentelemetry.io/otel/trace => go.opentelemetry.io/otel/trace v1.11.2
# gomodules.xyz/jsonpatch/v2 => github.com/gomodules/jsonpatch/v2 v2.2.0 # gomodules.xyz/jsonpatch/v2 => github.com/gomodules/jsonpatch/v2 v2.2.0
# k8s.io/api => k8s.io/api v0.26.1 # k8s.io/api => k8s.io/api v0.26.7
# k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.26.1 # k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.26.7
# k8s.io/apimachinery => k8s.io/apimachinery v0.26.1 # k8s.io/apimachinery => k8s.io/apimachinery v0.26.7
# k8s.io/apiserver => k8s.io/apiserver v0.26.1 # k8s.io/apiserver => k8s.io/apiserver v0.26.7
# k8s.io/cli-runtime => k8s.io/cli-runtime v0.26.1 # k8s.io/cli-runtime => k8s.io/cli-runtime v0.26.7
# k8s.io/client-go => k8s.io/client-go v0.26.1 # k8s.io/client-go => k8s.io/client-go v0.26.7
# k8s.io/cloud-provider => k8s.io/cloud-provider v0.26.1 # k8s.io/cloud-provider => k8s.io/cloud-provider v0.26.7
# k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.26.1 # k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.26.7
# k8s.io/code-generator => k8s.io/code-generator v0.26.1 # k8s.io/code-generator => k8s.io/code-generator v0.26.7
# k8s.io/component-base => k8s.io/component-base v0.26.1 # k8s.io/component-base => k8s.io/component-base v0.26.7
# k8s.io/component-helpers => k8s.io/component-helpers v0.26.1 # k8s.io/component-helpers => k8s.io/component-helpers v0.26.7
# k8s.io/controller-manager => k8s.io/controller-manager v0.26.1 # k8s.io/controller-manager => k8s.io/controller-manager v0.26.7
# k8s.io/cri-api => k8s.io/cri-api v0.26.1 # k8s.io/cri-api => k8s.io/cri-api v0.26.7
# k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.26.1 # k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.26.7
# k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.26.1 # k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.26.7
# k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.26.1 # k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.26.7
# k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.26.1 # k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.26.7
# k8s.io/kube-proxy => k8s.io/kube-proxy v0.26.1 # k8s.io/kube-proxy => k8s.io/kube-proxy v0.26.7
# k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.26.1 # k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.26.7
# k8s.io/kubectl => k8s.io/kubectl v0.26.1 # k8s.io/kubectl => k8s.io/kubectl v0.26.7
# k8s.io/kubelet => k8s.io/kubelet v0.26.1 # k8s.io/kubelet => k8s.io/kubelet v0.26.7
# k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.26.1 # k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.26.7
# k8s.io/metrics => k8s.io/metrics v0.26.1 # k8s.io/metrics => k8s.io/metrics v0.26.7
# k8s.io/mount-utils => k8s.io/mount-utils v0.26.1 # k8s.io/mount-utils => k8s.io/mount-utils v0.26.7
# k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.26.1 # k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.26.7
# k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.26.1 # k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.26.7
# layeh.com/radius => github.com/layeh/radius v0.0.0-20190322222518-890bc1058917 # layeh.com/radius => github.com/layeh/radius v0.0.0-20190322222518-890bc1058917

View File

@ -118,6 +118,8 @@ func (cm *connectionManager) closeAll() {
// grpcTunnel implements Tunnel // grpcTunnel implements Tunnel
type grpcTunnel struct { type grpcTunnel struct {
stream client.ProxyService_ProxyClient stream client.ProxyService_ProxyClient
sendLock sync.Mutex
recvLock sync.Mutex
clientConn clientConn clientConn clientConn
pendingDial pendingDialManager pendingDial pendingDialManager
conns connectionManager conns connectionManager
@ -243,20 +245,17 @@ func (t *grpcTunnel) serve(tunnelCtx context.Context) {
}() }()
for { for {
pkt, err := t.stream.Recv() pkt, err := t.Recv()
if err == io.EOF { if err == io.EOF {
return return
} }
const segment = commonmetrics.SegmentToClient
isClosing := t.isClosing() isClosing := t.isClosing()
if err != nil || pkt == nil { if err != nil || pkt == nil {
if !isClosing { if !isClosing {
klog.ErrorS(err, "stream read failure") klog.ErrorS(err, "stream read failure")
} }
metrics.Metrics.ObserveStreamErrorNoPacket(segment, err)
return return
} }
metrics.Metrics.ObservePacket(segment, pkt.Type)
if isClosing { if isClosing {
return return
} }
@ -335,11 +334,23 @@ func (t *grpcTunnel) serve(tunnelCtx context.Context) {
case client.PacketType_DATA: case client.PacketType_DATA:
resp := pkt.GetData() resp := pkt.GetData()
if resp.ConnectID == 0 {
klog.ErrorS(nil, "Received packet missing ConnectID", "packetType", "DATA")
continue
}
// TODO: flow control // TODO: flow control
conn, ok := t.conns.get(resp.ConnectID) conn, ok := t.conns.get(resp.ConnectID)
if !ok { if !ok {
klog.V(1).InfoS("Connection not recognized", "connectionID", resp.ConnectID) klog.ErrorS(nil, "Connection not recognized", "connectionID", resp.ConnectID, "packetType", "DATA")
t.Send(&client.Packet{
Type: client.PacketType_CLOSE_REQ,
Payload: &client.Packet_CloseRequest{
CloseRequest: &client.CloseRequest{
ConnectID: resp.ConnectID,
},
},
})
continue continue
} }
timer := time.NewTimer((time.Duration)(t.readTimeoutSeconds) * time.Second) timer := time.NewTimer((time.Duration)(t.readTimeoutSeconds) * time.Second)
@ -358,7 +369,7 @@ func (t *grpcTunnel) serve(tunnelCtx context.Context) {
conn, ok := t.conns.get(resp.ConnectID) conn, ok := t.conns.get(resp.ConnectID)
if !ok { if !ok {
klog.V(1).InfoS("Connection not recognized", "connectionID", resp.ConnectID) klog.V(1).InfoS("Connection not recognized", "connectionID", resp.ConnectID, "packetType", "CLOSE_RSP")
continue continue
} }
close(conn.readCh) close(conn.readCh)
@ -418,18 +429,15 @@ func (t *grpcTunnel) dialContext(requestCtx context.Context, protocol, address s
} }
klog.V(5).InfoS("[tracing] send packet", "type", req.Type) klog.V(5).InfoS("[tracing] send packet", "type", req.Type)
const segment = commonmetrics.SegmentFromClient err := t.Send(req)
metrics.Metrics.ObservePacket(segment, req.Type)
err := t.stream.Send(req)
if err != nil { if err != nil {
metrics.Metrics.ObserveStreamError(segment, err, req.Type)
return nil, err return nil, err
} }
klog.V(5).Infoln("DIAL_REQ sent to proxy server") klog.V(5).Infoln("DIAL_REQ sent to proxy server")
c := &conn{ c := &conn{
stream: t.stream, tunnel: t,
random: random, random: random,
closeTunnel: t.closeTunnel, closeTunnel: t.closeTunnel,
} }
@ -473,10 +481,7 @@ func (t *grpcTunnel) closeDial(dialID int64) {
}, },
}, },
} }
const segment = commonmetrics.SegmentFromClient if err := t.Send(req); err != nil {
metrics.Metrics.ObservePacket(segment, req.Type)
if err := t.stream.Send(req); err != nil {
metrics.Metrics.ObserveStreamError(segment, err, req.Type)
klog.V(5).InfoS("Failed to send DIAL_CLS", "err", err, "dialID", dialID) klog.V(5).InfoS("Failed to send DIAL_CLS", "err", err, "dialID", dialID)
} }
t.closeTunnel() t.closeTunnel()
@ -491,6 +496,35 @@ func (t *grpcTunnel) isClosing() bool {
return atomic.LoadUint32(&t.closing) != 0 return atomic.LoadUint32(&t.closing) != 0
} }
func (t *grpcTunnel) Send(pkt *client.Packet) error {
t.sendLock.Lock()
defer t.sendLock.Unlock()
const segment = commonmetrics.SegmentFromClient
metrics.Metrics.ObservePacket(segment, pkt.Type)
err := t.stream.Send(pkt)
if err != nil && err != io.EOF {
metrics.Metrics.ObserveStreamError(segment, err, pkt.Type)
}
return err
}
func (t *grpcTunnel) Recv() (*client.Packet, error) {
t.recvLock.Lock()
defer t.recvLock.Unlock()
const segment = commonmetrics.SegmentToClient
pkt, err := t.stream.Recv()
if err != nil {
if err != io.EOF {
metrics.Metrics.ObserveStreamErrorNoPacket(segment, err)
}
return nil, err
}
metrics.Metrics.ObservePacket(segment, pkt.Type)
return pkt, nil
}
func GetDialFailureReason(err error) (isDialFailure bool, reason metrics.DialFailureReason) { func GetDialFailureReason(err error) (isDialFailure bool, reason metrics.DialFailureReason) {
var df *dialFailure var df *dialFailure
if errors.As(err, &df) { if errors.As(err, &df) {

View File

@ -24,8 +24,6 @@ import (
"k8s.io/klog/v2" "k8s.io/klog/v2"
"sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/metrics"
commonmetrics "sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/common/metrics"
"sigs.k8s.io/apiserver-network-proxy/konnectivity-client/proto/client" "sigs.k8s.io/apiserver-network-proxy/konnectivity-client/proto/client"
) )
@ -38,7 +36,7 @@ var errConnCloseTimeout = errors.New("close timeout")
// conn is an implementation of net.Conn, where the data is transported // conn is an implementation of net.Conn, where the data is transported
// over an established tunnel defined by a gRPC service ProxyService. // over an established tunnel defined by a gRPC service ProxyService.
type conn struct { type conn struct {
stream client.ProxyService_ProxyClient tunnel *grpcTunnel
connID int64 connID int64
random int64 random int64
readCh chan []byte readCh chan []byte
@ -65,11 +63,8 @@ func (c *conn) Write(data []byte) (n int, err error) {
klog.V(5).InfoS("[tracing] send req", "type", req.Type) klog.V(5).InfoS("[tracing] send req", "type", req.Type)
const segment = commonmetrics.SegmentFromClient err = c.tunnel.Send(req)
metrics.Metrics.ObservePacket(segment, req.Type)
err = c.stream.Send(req)
if err != nil { if err != nil {
metrics.Metrics.ObserveStreamError(segment, err, req.Type)
return 0, err return 0, err
} }
return len(data), err return len(data), err
@ -153,10 +148,7 @@ func (c *conn) Close() error {
klog.V(5).InfoS("[tracing] send req", "type", req.Type) klog.V(5).InfoS("[tracing] send req", "type", req.Type)
const segment = commonmetrics.SegmentFromClient if err := c.tunnel.Send(req); err != nil {
metrics.Metrics.ObservePacket(segment, req.Type)
if err := c.stream.Send(req); err != nil {
metrics.Metrics.ObserveStreamError(segment, err, req.Type)
return err return err
} }