From 8e71777a303ba060f91eec37595081a2ebfc4006 Mon Sep 17 00:00:00 2001 From: andyzhangx Date: Sun, 2 Apr 2023 14:32:01 +0000 Subject: [PATCH] fix: CVE-2022-3294 --- go.mod | 72 ++-- go.sum | 78 ++-- vendor/k8s.io/api/apps/v1/generated.proto | 1 + vendor/k8s.io/api/apps/v1/types.go | 1 + .../k8s.io/api/apps/v1beta1/generated.proto | 1 + vendor/k8s.io/api/apps/v1beta1/types.go | 1 + .../k8s.io/api/apps/v1beta2/generated.proto | 1 + vendor/k8s.io/api/apps/v1beta2/types.go | 1 + vendor/k8s.io/api/batch/v1/types.go | 3 +- vendor/k8s.io/api/certificates/v1/types.go | 1 - vendor/k8s.io/api/core/v1/types.go | 19 +- .../k8s.io/api/policy/v1beta1/generated.proto | 1 - vendor/k8s.io/api/policy/v1beta1/types.go | 3 +- .../pkg/apis/meta/v1/micro_time_proto.go | 10 +- vendor/k8s.io/apiserver/pkg/audit/union.go | 1 + .../k8s.io/client-go/kubernetes/clientset.go | 4 + .../client-go/pkg/version/.gitattributes | 1 - .../plugin/pkg/client/auth/exec/exec.go | 30 +- vendor/k8s.io/client-go/rest/request.go | 38 +- .../tools/cache/thread_safe_store.go | 13 +- .../client-go/tools/clientcmd/auth_loaders.go | 2 +- vendor/k8s.io/client-go/transport/cache.go | 25 +- vendor/k8s.io/client-go/transport/config.go | 21 +- .../k8s.io/client-go/transport/transport.go | 25 ++ .../component-base/version/.gitattributes | 1 - .../k8s.io/kubernetes/pkg/api/v1/pod/util.go | 23 ++ .../k8s.io/kubernetes/pkg/apis/apps/types.go | 1 + .../pkg/apis/core/validation/events.go | 13 +- .../pkg/controller/controller_utils.go | 11 +- .../kubernetes/pkg/features/kube_features.go | 2 +- .../k8s.io/kubernetes/pkg/proxy/util/utils.go | 2 +- .../pkg/volume/util/subpath/subpath_linux.go | 7 +- .../test/e2e/framework/framework.go | 3 + .../test/e2e/framework/nodes_util.go | 2 +- .../test/e2e/framework/test_context.go | 3 +- .../kubernetes/test/e2e/framework/util.go | 57 ++- .../kubernetes/test/utils/image/manifest.go | 47 ++- vendor/modules.txt | 76 ++-- .../konnectivity-client/pkg/client/client.go | 380 ++++++++++++++---- .../konnectivity-client/pkg/client/conn.go | 11 +- 40 files changed, 712 insertions(+), 280 deletions(-) delete mode 100644 vendor/k8s.io/client-go/pkg/version/.gitattributes delete mode 100644 vendor/k8s.io/component-base/version/.gitattributes diff --git a/go.mod b/go.mod index d5824db2..5140a414 100644 --- a/go.mod +++ b/go.mod @@ -12,12 +12,12 @@ require ( github.com/stretchr/testify v1.8.0 golang.org/x/net v0.7.0 google.golang.org/grpc v1.40.0 - k8s.io/api v0.23.3 - k8s.io/apimachinery v0.23.3 - k8s.io/client-go v0.23.3 + k8s.io/api v0.23.14 + k8s.io/apimachinery v0.23.14 + k8s.io/client-go v0.23.14 k8s.io/klog/v2 v2.80.1 - k8s.io/kubernetes v1.23.3 - k8s.io/mount-utils v0.23.3 + k8s.io/kubernetes v1.23.14 + k8s.io/mount-utils v0.23.14 k8s.io/utils v0.0.0-20221107191617-1a15be271d1d sigs.k8s.io/yaml v1.2.0 ) @@ -87,44 +87,44 @@ require ( gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiserver v0.23.3 // indirect - k8s.io/cloud-provider v0.23.3 // indirect - k8s.io/component-base v0.23.3 // indirect - k8s.io/component-helpers v0.23.3 // indirect + k8s.io/apiserver v0.23.14 // indirect + k8s.io/cloud-provider v0.23.14 // indirect + k8s.io/component-base v0.23.14 // indirect + k8s.io/component-helpers v0.23.14 // indirect k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect k8s.io/kubectl v0.0.0 // indirect k8s.io/kubelet v0.0.0 // indirect - sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.27 // indirect + sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.33 // indirect sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect ) replace ( - k8s.io/api => k8s.io/api v0.23.3 - k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.23.3 - k8s.io/apimachinery => k8s.io/apimachinery v0.23.3 - k8s.io/apiserver => k8s.io/apiserver v0.23.3 - k8s.io/cli-runtime => k8s.io/cli-runtime v0.23.3 - k8s.io/client-go => k8s.io/client-go v0.23.3 - k8s.io/cloud-provider => k8s.io/cloud-provider v0.23.3 - k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.23.3 - k8s.io/code-generator => k8s.io/code-generator v0.23.3 - k8s.io/component-base => k8s.io/component-base v0.23.3 - k8s.io/component-helpers => k8s.io/component-helpers v0.23.3 - k8s.io/controller-manager => k8s.io/controller-manager v0.23.3 - k8s.io/cri-api => k8s.io/cri-api v0.23.3 - k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.23.3 - k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.23.3 - k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.23.3 - k8s.io/kube-proxy => k8s.io/kube-proxy v0.23.3 - k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.23.3 - k8s.io/kubectl => k8s.io/kubectl v0.23.3 - k8s.io/kubelet => k8s.io/kubelet v0.23.3 - k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.23.3 - k8s.io/metrics => k8s.io/metrics v0.23.3 + k8s.io/api => k8s.io/api v0.23.14 + k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.23.14 + k8s.io/apimachinery => k8s.io/apimachinery v0.23.14 + k8s.io/apiserver => k8s.io/apiserver v0.23.14 + k8s.io/cli-runtime => k8s.io/cli-runtime v0.23.14 + k8s.io/client-go => k8s.io/client-go v0.23.14 + k8s.io/cloud-provider => k8s.io/cloud-provider v0.23.14 + k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.23.14 + k8s.io/code-generator => k8s.io/code-generator v0.23.14 + k8s.io/component-base => k8s.io/component-base v0.23.14 + k8s.io/component-helpers => k8s.io/component-helpers v0.23.14 + k8s.io/controller-manager => k8s.io/controller-manager v0.23.14 + k8s.io/cri-api => k8s.io/cri-api v0.23.14 + k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.23.14 + k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.23.14 + k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.23.14 + k8s.io/kube-proxy => k8s.io/kube-proxy v0.23.14 + k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.23.14 + k8s.io/kubectl => k8s.io/kubectl v0.23.14 + k8s.io/kubelet => k8s.io/kubelet v0.23.14 + k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.23.14 + k8s.io/metrics => k8s.io/metrics v0.23.14 k8s.io/mount-utils => k8s.io/mount-utils v0.0.0-20230103133730-1df1a57439e2 - k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.23.3 - k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.23.3 - k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.23.3 - k8s.io/sample-controller => k8s.io/sample-controller v0.23.3 + k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.23.14 + k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.23.14 + k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.23.14 + k8s.io/sample-controller => k8s.io/sample-controller v0.23.14 ) diff --git a/go.sum b/go.sum index 10886ff3..9b21a8d2 100644 --- a/go.sum +++ b/go.sum @@ -271,7 +271,7 @@ github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA// github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/cadvisor v0.43.0/go.mod h1:+RdMSbc3FVr5NYCD2dOEJy/LI0jYJ/0xJXkzWXEyiFQ= +github.com/google/cadvisor v0.43.1/go.mod h1:+RdMSbc3FVr5NYCD2dOEJy/LI0jYJ/0xJXkzWXEyiFQ= github.com/google/cel-go v0.9.0/go.mod h1:U7ayypeSkw23szu4GaQTPJGx66c20mx8JklMSxrmI1w= github.com/google/cel-spec v0.6.0/go.mod h1:Nwjgxy5CbjlPrtCWjeDjUyKMl8w41YBYGjsyDdqk0xA= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -641,6 +641,8 @@ go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0H go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= @@ -1115,27 +1117,27 @@ 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-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= -k8s.io/api v0.23.3 h1:KNrME8KHGr12Ozjf8ytOewKzZh6hl/hHUZeHddT3a38= -k8s.io/api v0.23.3/go.mod h1:w258XdGyvCmnBj/vGzQMj6kzdufJZVUwEM1U2fRJwSQ= -k8s.io/apiextensions-apiserver v0.23.3/go.mod h1:/ZpRXdgKZA6DvIVPEmXDCZJN53YIQEUDF+hrpIQJL38= -k8s.io/apimachinery v0.23.3 h1:7IW6jxNzrXTsP0c8yXz2E5Yx/WTzVPTsHIx/2Vm0cIk= -k8s.io/apimachinery v0.23.3/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM= -k8s.io/apiserver v0.23.3 h1:gWY1DmA0AdAGR/H+Q/1FtyGkFq8xqSaZOw7oLopmO8k= -k8s.io/apiserver v0.23.3/go.mod h1:3HhsTmC+Pn+Jctw+Ow0LHA4dQ4oXrQ4XJDzrVDG64T4= -k8s.io/cli-runtime v0.23.3/go.mod h1:yA00O5pDqnjkBh8fkuugBbfIfjB1nOpz+aYLotbnOfc= -k8s.io/client-go v0.23.3 h1:23QYUmCQ/W6hW78xIwm3XqZrrKZM+LWDqW2zfo+szJs= -k8s.io/client-go v0.23.3/go.mod h1:47oMd+YvAOqZM7pcQ6neJtBiFH7alOyfunYN48VsmwE= -k8s.io/cloud-provider v0.23.3 h1:/3hcsBAyG5VpeDAyJQvRqf5US4dHU0Hu57MJiq4zG/w= -k8s.io/cloud-provider v0.23.3/go.mod h1:Ik+pKlpPOp0Zs906xyOpT3g2xB9A8VGNdejMTZS6EeA= -k8s.io/cluster-bootstrap v0.23.3/go.mod h1:NwUIksUHKNOKIHg/AfLH4NxqylbfEVXUh9EX2NxHZII= -k8s.io/code-generator v0.23.3/go.mod h1:S0Q1JVA+kSzTI1oUvbKAxZY/DYbA/ZUb4Uknog12ETk= -k8s.io/component-base v0.23.3 h1:q+epprVdylgecijVGVdf4MbizEL2feW4ssd7cdo6LVY= -k8s.io/component-base v0.23.3/go.mod h1:1Smc4C60rWG7d3HjSYpIwEbySQ3YWg0uzH5a2AtaTLg= -k8s.io/component-helpers v0.23.3 h1:OzuQpfsJsjGvT2nYnp0JsyxpGbnsv0GSvRlIkMKx+I8= -k8s.io/component-helpers v0.23.3/go.mod h1:SH+W/WPTaTenbWyDEeY7iytAQiMh45aqKxkvlqQ57cg= -k8s.io/controller-manager v0.23.3/go.mod h1:E0ss6ogA93sZ+AuibQSa7H4xWIiICTYFjowkjellVeU= -k8s.io/cri-api v0.23.3/go.mod h1:REJE3PSU0h/LOV1APBrupxrEJqnoxZC8KWzkBUHwrK4= -k8s.io/csi-translation-lib v0.23.3/go.mod h1:8J7hpeqMoCJWofd1lCs4vZrEshdbVYrqurFeB6GZ/+E= +k8s.io/api v0.23.14 h1:1gRN0u72YpSEsnnyM5P16XNbRztFefV8pU+mb8aC4Io= +k8s.io/api v0.23.14/go.mod h1:sWeFZzeE9lLU75pogeht6lIcAP+wkqzTlM8V/REymxs= +k8s.io/apiextensions-apiserver v0.23.14/go.mod h1:p3aZ4Flyg0h7A0cfRSVn3B+32idn/qzc52l/RhVtOUE= +k8s.io/apimachinery v0.23.14 h1:UNkDdlj663kkbFiayTMRr37YIE4b7LtIm9gFnVlpfqA= +k8s.io/apimachinery v0.23.14/go.mod h1:qd/bZ1ajQ8MklCd0DlIwLhjcs1kr7QurGOQUS59A7XE= +k8s.io/apiserver v0.23.14 h1:Ci2POk+ZAqEju/KdteVQD4kJKEFxMQ4ttKXQTpeW888= +k8s.io/apiserver v0.23.14/go.mod h1:gjuGlqHbtC8NKIiEswwh6gglJHbQgTtP2fVZOq8u+nQ= +k8s.io/cli-runtime v0.23.14/go.mod h1:1uLxnOWO7GRVIsyvSTMDgozrQUkldukBZPoFmfygz5Q= +k8s.io/client-go v0.23.14 h1:nwrCHBj6hXHehOg3lSwGZYo+T/acwfIL6tMWkT2u+mQ= +k8s.io/client-go v0.23.14/go.mod h1:nKdHtC7qNAkMP0seRU49pdP9tK0lobkM2n5Ljg4r+VI= +k8s.io/cloud-provider v0.23.14 h1:M6e3+cJNAOvyPUSjsNH4kLVqchcbsvJ0RJXhCiHR7og= +k8s.io/cloud-provider v0.23.14/go.mod h1:5X8oZsD5Q0u9uD1hwxClT2UVI7/eB/Kp1TflUHAfg84= +k8s.io/cluster-bootstrap v0.23.14/go.mod h1:RX2htmL8/bO/MDK6N4F58k6wB7LinfHli96klkr2BKg= +k8s.io/code-generator v0.23.14/go.mod h1:3pOEhV/pmJcwFtt3zfwaArTMflocYMgjYIgM0zUIjAs= +k8s.io/component-base v0.23.14 h1:ghITiT9qmYms+XjrYVM2re5leCT+LrZ35fx3wIeiYHE= +k8s.io/component-base v0.23.14/go.mod h1:sY0Bdtshi6Yab/KeVgkWKBqotIAuOGCKINBeFyazUeE= +k8s.io/component-helpers v0.23.14 h1:WEUfpxuighRwHG7F2DqVx98lBpSrFLvipRo63dCKvWQ= +k8s.io/component-helpers v0.23.14/go.mod h1:VzqGWNjq7L0O3Ivd/45R8DxrhhHxW6eMFjAWrpCpUtY= +k8s.io/controller-manager v0.23.14/go.mod h1:5NKgyx6MNg5YhYWBJpON7WrPoMIBYIgqBuS7Uu7RmH4= +k8s.io/cri-api v0.23.14/go.mod h1:WtUZS6AZ9GadZ3xXRbujziML9XcA1+5HBWPJe/AG0tU= +k8s.io/csi-translation-lib v0.23.14/go.mod h1:VPxHAWjv5jQklh/zSYRh3zf7r5lsHBgOjpykuVEImeQ= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= @@ -1144,25 +1146,25 @@ k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-aggregator v0.23.3/go.mod h1:pt5QJ3QaIdhZzNlUvN5wndbM0LNT4BvhszGkzy2QdFo= -k8s.io/kube-controller-manager v0.23.3/go.mod h1:e8m5dhjei67DlLZA/QTvenxiGyonG9UhgHtU1LMslJE= +k8s.io/kube-aggregator v0.23.14/go.mod h1:bblLuI9g/DgJcZtVa5x6CTC1MtGvJ7GX5FBFOf0mCvU= +k8s.io/kube-controller-manager v0.23.14/go.mod h1:srtedngV7XEEqYvmS49PPPQLArSFyhVHB4S1R93xnhU= k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 h1:E3J9oCLlaobFUqsjG9DfKbP2BmgwBL2p7pn0A3dG9W4= k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk= -k8s.io/kube-proxy v0.23.3/go.mod h1:XdvwqJkR9r0ddUAX4ruA4V22Kws3qzKvgL3rIq584Ko= -k8s.io/kube-scheduler v0.23.3/go.mod h1:/thFQoAMv9/olDOEYVSQbUohmkJJyIPUmpVu0UealSM= -k8s.io/kubectl v0.23.3 h1:gJsF7cahkWDPYlNvYKK+OrBZLAJUBzCym+Zsi+dfi1E= -k8s.io/kubectl v0.23.3/go.mod h1:VBeeXNgLhSabu4/k0O7Q0YujgnA3+CLTUE0RcmF73yY= -k8s.io/kubelet v0.23.3 h1:jYed8HoT0H2zXzf5Av+Ml8z5erN39uJfKh/yplYMgkg= -k8s.io/kubelet v0.23.3/go.mod h1:RZxGSCsiwoWJ9z6mVla+jhiLfCFIKC16yAS38D7GQSE= -k8s.io/kubernetes v1.23.3 h1:weuFJOkRP7+057uvhNUYbVTVCog/klquhbtKRD+UHUo= -k8s.io/kubernetes v1.23.3/go.mod h1:C0AB/I7M4Nu6d1ELyGdC8qrrHEc6J5l8CHUashza1Io= -k8s.io/legacy-cloud-providers v0.23.3/go.mod h1:s9vv59dUv4SU+HAm9C/YDdyw2OY9qmFYmcGEwr/ecDc= -k8s.io/metrics v0.23.3/go.mod h1:Ut8TvkbsO4oMVeUzaTArvPrcw9QRFLs2XNzUlORjdYE= +k8s.io/kube-proxy v0.23.14/go.mod h1:vl1BS3CWnkRjwsiUncL9ZteI1qdyhn+6W6GeBAQt27M= +k8s.io/kube-scheduler v0.23.14/go.mod h1:mhxqa0sV6OTdYAE7Fg5/QwdgPEE3pSYK89LWs5qm5GY= +k8s.io/kubectl v0.23.14 h1:1UuVZLdFaI0pX2kGEigu1VTlKqfkg2tPu3zG/YFaVHM= +k8s.io/kubectl v0.23.14/go.mod h1:a4hkiz1G+fe+K4Tp15Xn49qj/HlIbHnDBysRipRyh1Q= +k8s.io/kubelet v0.23.14 h1:cENAgyd+KhYchf/JRopKPUG0FafxrmcTaGP53LYoKSQ= +k8s.io/kubelet v0.23.14/go.mod h1:YshK+1lzYbGD4bFLMVg0jYQkxISz+fbokNsStcu4R/k= +k8s.io/kubernetes v1.23.14 h1:xqSVDhItGWCsCzZlnj2PHDkDAofaqvPHmKYW7kr8wUE= +k8s.io/kubernetes v1.23.14/go.mod h1:Z0W84JU7x94gywsN90lP3jNosay9t86a5/qTuaeyMk0= +k8s.io/legacy-cloud-providers v0.23.14/go.mod h1:6if2+guj6PmzTmXhwQ38yX88oh2Jznqjqu5jIyYaJww= +k8s.io/metrics v0.23.14/go.mod h1:OySm7Obgl95KjBOjoGtr3is3gj/uxBPKwS6SlnZB5rw= k8s.io/mount-utils v0.0.0-20230103133730-1df1a57439e2 h1:kfACKquxtsEA7XXDy+iC92lg/1stK0UtzAhf7R2Y8Fc= k8s.io/mount-utils v0.0.0-20230103133730-1df1a57439e2/go.mod h1:au99w4FWU5ZWelLb3Yx6kJc8RZ387IyWVM9tN65Yhxo= -k8s.io/pod-security-admission v0.23.3/go.mod h1:vULEGUgsujyrKBz3RRRZnvrJJt115gu0GICArDmgzqo= -k8s.io/sample-apiserver v0.23.3/go.mod h1:5yDZRMfFvp7/2BOXBwk0AFNsD00iyuXeEsWZSoLFeGw= +k8s.io/pod-security-admission v0.23.14/go.mod h1:HYKZp5EyDzZ79mcfoogbTQ6T7L9BWyxuLezsnb/iaL0= +k8s.io/sample-apiserver v0.23.14/go.mod h1:LqP1Sz+qqPLNJ6PjpGPUy3MQ+ai6j2QcXETLfaI1OEg= k8s.io/system-validators v1.6.0/go.mod h1:bPldcLgkIUK22ALflnsXk8pvkTEndYdNuaHH6gRrl0Q= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= @@ -1178,8 +1180,8 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8 rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.27 h1:KQOkVzXrLNb0EP6W0FD6u3CCPAwgXFYwZitbj7K0P0Y= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.27/go.mod h1:tq2nT0Kx7W+/f2JVE+zxYtUhdjuELJkVpNz+x/QN5R4= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.33 h1:LYqFq+6Cj2D0gFfrJvL7iElD4ET6ir3VDdhDdTK7rgc= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.33/go.mod h1:soWkSNf2tZC7aMibXEqVhCd73GOY5fJikn8qbdzemB0= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= sigs.k8s.io/kustomize/api v0.10.1/go.mod h1:2FigT1QN6xKdcnGS2Ppp1uIWrtWN28Ms8A3OZUZhwr8= diff --git a/vendor/k8s.io/api/apps/v1/generated.proto b/vendor/k8s.io/api/apps/v1/generated.proto index 6e5517d8..5633d727 100644 --- a/vendor/k8s.io/api/apps/v1/generated.proto +++ b/vendor/k8s.io/api/apps/v1/generated.proto @@ -748,6 +748,7 @@ message StatefulSetStatus { // Total number of available pods (ready for at least minReadySeconds) targeted by this statefulset. // This is a beta field and enabled/disabled by StatefulSetMinReadySeconds feature gate. + // +optional optional int32 availableReplicas = 11; } diff --git a/vendor/k8s.io/api/apps/v1/types.go b/vendor/k8s.io/api/apps/v1/types.go index 469b4729..c1e22032 100644 --- a/vendor/k8s.io/api/apps/v1/types.go +++ b/vendor/k8s.io/api/apps/v1/types.go @@ -272,6 +272,7 @@ type StatefulSetStatus struct { // Total number of available pods (ready for at least minReadySeconds) targeted by this statefulset. // This is a beta field and enabled/disabled by StatefulSetMinReadySeconds feature gate. + // +optional AvailableReplicas int32 `json:"availableReplicas" protobuf:"varint,11,opt,name=availableReplicas"` } diff --git a/vendor/k8s.io/api/apps/v1beta1/generated.proto b/vendor/k8s.io/api/apps/v1beta1/generated.proto index 9f9df98f..d94b623a 100644 --- a/vendor/k8s.io/api/apps/v1beta1/generated.proto +++ b/vendor/k8s.io/api/apps/v1beta1/generated.proto @@ -502,6 +502,7 @@ message StatefulSetStatus { // Total number of available pods (ready for at least minReadySeconds) targeted by this StatefulSet. // This is a beta field and enabled/disabled by StatefulSetMinReadySeconds feature gate. + // +optional optional int32 availableReplicas = 11; } diff --git a/vendor/k8s.io/api/apps/v1beta1/types.go b/vendor/k8s.io/api/apps/v1beta1/types.go index 832ef34f..8052ec1f 100644 --- a/vendor/k8s.io/api/apps/v1beta1/types.go +++ b/vendor/k8s.io/api/apps/v1beta1/types.go @@ -310,6 +310,7 @@ type StatefulSetStatus struct { // Total number of available pods (ready for at least minReadySeconds) targeted by this StatefulSet. // This is a beta field and enabled/disabled by StatefulSetMinReadySeconds feature gate. + // +optional AvailableReplicas int32 `json:"availableReplicas" protobuf:"varint,11,opt,name=availableReplicas"` } diff --git a/vendor/k8s.io/api/apps/v1beta2/generated.proto b/vendor/k8s.io/api/apps/v1beta2/generated.proto index 6d950586..87df285b 100644 --- a/vendor/k8s.io/api/apps/v1beta2/generated.proto +++ b/vendor/k8s.io/api/apps/v1beta2/generated.proto @@ -790,6 +790,7 @@ message StatefulSetStatus { // Total number of available pods (ready for at least minReadySeconds) targeted by this StatefulSet. // This is a beta field and enabled/disabled by StatefulSetMinReadySeconds feature gate. + // +optional optional int32 availableReplicas = 11; } diff --git a/vendor/k8s.io/api/apps/v1beta2/types.go b/vendor/k8s.io/api/apps/v1beta2/types.go index 332bc7ed..d983d0ce 100644 --- a/vendor/k8s.io/api/apps/v1beta2/types.go +++ b/vendor/k8s.io/api/apps/v1beta2/types.go @@ -320,6 +320,7 @@ type StatefulSetStatus struct { // Total number of available pods (ready for at least minReadySeconds) targeted by this StatefulSet. // This is a beta field and enabled/disabled by StatefulSetMinReadySeconds feature gate. + // +optional AvailableReplicas int32 `json:"availableReplicas" protobuf:"varint,11,opt,name=availableReplicas"` } diff --git a/vendor/k8s.io/api/batch/v1/types.go b/vendor/k8s.io/api/batch/v1/types.go index aec1cad8..13cebde3 100644 --- a/vendor/k8s.io/api/batch/v1/types.go +++ b/vendor/k8s.io/api/batch/v1/types.go @@ -289,10 +289,9 @@ type UncountedTerminatedPods struct { Failed []types.UID `json:"failed,omitempty" protobuf:"bytes,2,rep,name=failed,casttype=k8s.io/apimachinery/pkg/types.UID"` } -// +enum type JobConditionType string -// These are valid conditions of a job. +// These are built-in conditions of a job. const ( // JobSuspended means the job has been suspended. JobSuspended JobConditionType = "Suspended" diff --git a/vendor/k8s.io/api/certificates/v1/types.go b/vendor/k8s.io/api/certificates/v1/types.go index a3900e1d..6403d460 100644 --- a/vendor/k8s.io/api/certificates/v1/types.go +++ b/vendor/k8s.io/api/certificates/v1/types.go @@ -214,7 +214,6 @@ type CertificateSigningRequestStatus struct { } // RequestConditionType is the type of a CertificateSigningRequestCondition -// +enum type RequestConditionType string // Well-known condition types for certificate requests. diff --git a/vendor/k8s.io/api/core/v1/types.go b/vendor/k8s.io/api/core/v1/types.go index 80c5dd74..dcf83ecc 100644 --- a/vendor/k8s.io/api/core/v1/types.go +++ b/vendor/k8s.io/api/core/v1/types.go @@ -522,7 +522,6 @@ type PersistentVolumeClaimSpec struct { } // PersistentVolumeClaimConditionType is a valid value of PersistentVolumeClaimCondition.Type -// +enum type PersistentVolumeClaimConditionType string const ( @@ -2635,10 +2634,9 @@ const ( ) // PodConditionType is a valid value for PodCondition.Type -// +enum type PodConditionType string -// These are valid conditions of pod. +// These are built-in conditions of pod. An application may use a custom condition not listed here. const ( // ContainersReady indicates whether all containers in the pod are ready. ContainersReady PodConditionType = "ContainersReady" @@ -5055,11 +5053,10 @@ const ( NodeTerminated NodePhase = "Terminated" ) -// +enum type NodeConditionType string -// These are valid conditions of node. Currently, we don't have enough information to decide -// node condition. In the future, we will add more. The proposed set of conditions are: +// These are valid but not exhaustive conditions of node. A cloud provider may set a condition not listed here. +// The built-in set of conditions are: // NodeReachable, NodeLive, NodeReady, NodeSchedulable, NodeRunnable. const ( // NodeReady means kubelet is healthy and ready to accept pods. @@ -5094,10 +5091,9 @@ type NodeCondition struct { Message string `json:"message,omitempty" protobuf:"bytes,6,opt,name=message"` } -// +enum type NodeAddressType string -// These are valid address type of node. +// These are built-in addresses type of node. A cloud provider may set a type not listed here. const ( // NodeHostName identifies a name of the node. Although every node can be assumed // to have a NodeAddress of this type, its exact syntax and semantics are not @@ -5267,10 +5263,9 @@ const ( NamespaceTerminatingCause metav1.CauseType = "NamespaceTerminating" ) -// +enum type NamespaceConditionType string -// These are valid conditions of a namespace. +// These are built-in conditions of a namespace. const ( // NamespaceDeletionDiscoveryFailure contains information about namespace deleter errors during resource discovery. NamespaceDeletionDiscoveryFailure NamespaceConditionType = "NamespaceDeletionDiscoveryFailure" @@ -5758,8 +5753,8 @@ type EventList struct { // List holds a list of objects, which may not be known by the server. type List metav1.List -// LimitType is a type of object that is limited -// +enum +// LimitType is a type of object that is limited. It can be Pod, Container, PersistentVolumeClaim or +// a fully qualified resource name. type LimitType string const ( diff --git a/vendor/k8s.io/api/policy/v1beta1/generated.proto b/vendor/k8s.io/api/policy/v1beta1/generated.proto index 133ba049..8a2824b5 100644 --- a/vendor/k8s.io/api/policy/v1beta1/generated.proto +++ b/vendor/k8s.io/api/policy/v1beta1/generated.proto @@ -144,7 +144,6 @@ message PodDisruptionBudgetSpec { // A null selector selects no pods. // An empty selector ({}) also selects no pods, which differs from standard behavior of selecting all pods. // In policy/v1, an empty selector will select all pods in the namespace. - // +patchStrategy=replace // +optional optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 2; diff --git a/vendor/k8s.io/api/policy/v1beta1/types.go b/vendor/k8s.io/api/policy/v1beta1/types.go index 553cb316..486f9346 100644 --- a/vendor/k8s.io/api/policy/v1beta1/types.go +++ b/vendor/k8s.io/api/policy/v1beta1/types.go @@ -36,9 +36,8 @@ type PodDisruptionBudgetSpec struct { // A null selector selects no pods. // An empty selector ({}) also selects no pods, which differs from standard behavior of selecting all pods. // In policy/v1, an empty selector will select all pods in the namespace. - // +patchStrategy=replace // +optional - Selector *metav1.LabelSelector `json:"selector,omitempty" patchStrategy:"replace" protobuf:"bytes,2,opt,name=selector"` + Selector *metav1.LabelSelector `json:"selector,omitempty" protobuf:"bytes,2,opt,name=selector"` // An eviction is allowed if at most "maxUnavailable" pods selected by // "selector" are unavailable after the eviction, i.e. even in absence of diff --git a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/micro_time_proto.go b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/micro_time_proto.go index 6dd6d899..ab68181e 100644 --- a/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/micro_time_proto.go +++ b/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/micro_time_proto.go @@ -27,9 +27,12 @@ func (m *MicroTime) ProtoMicroTime() *Timestamp { if m == nil { return &Timestamp{} } + + // truncate precision to microseconds to match JSON marshaling/unmarshaling + truncatedNanoseconds := time.Duration(m.Time.Nanosecond()).Truncate(time.Microsecond) return &Timestamp{ Seconds: m.Time.Unix(), - Nanos: int32(m.Time.Nanosecond()), + Nanos: int32(truncatedNanoseconds), } } @@ -51,7 +54,10 @@ func (m *MicroTime) Unmarshal(data []byte) error { if err := p.Unmarshal(data); err != nil { return err } - m.Time = time.Unix(p.Seconds, int64(p.Nanos)).Local() + + // truncate precision to microseconds to match JSON marshaling/unmarshaling + truncatedNanoseconds := time.Duration(p.Nanos).Truncate(time.Microsecond) + m.Time = time.Unix(p.Seconds, int64(truncatedNanoseconds)).Local() return nil } diff --git a/vendor/k8s.io/apiserver/pkg/audit/union.go b/vendor/k8s.io/apiserver/pkg/audit/union.go index 39dd74f7..0766a920 100644 --- a/vendor/k8s.io/apiserver/pkg/audit/union.go +++ b/vendor/k8s.io/apiserver/pkg/audit/union.go @@ -48,6 +48,7 @@ func (u union) ProcessEvents(events ...*auditinternal.Event) bool { func (u union) Run(stopCh <-chan struct{}) error { var funcs []func() error for _, backend := range u.backends { + backend := backend funcs = append(funcs, func() error { return backend.Run(stopCh) }) diff --git a/vendor/k8s.io/client-go/kubernetes/clientset.go b/vendor/k8s.io/client-go/kubernetes/clientset.go index 3e512a7c..e46c0537 100644 --- a/vendor/k8s.io/client-go/kubernetes/clientset.go +++ b/vendor/k8s.io/client-go/kubernetes/clientset.go @@ -413,6 +413,10 @@ func (c *Clientset) Discovery() discovery.DiscoveryInterface { func NewForConfig(c *rest.Config) (*Clientset, error) { configShallowCopy := *c + if configShallowCopy.UserAgent == "" { + configShallowCopy.UserAgent = rest.DefaultKubernetesUserAgent() + } + // share the transport between all clients httpClient, err := rest.HTTPClientFor(&configShallowCopy) if err != nil { diff --git a/vendor/k8s.io/client-go/pkg/version/.gitattributes b/vendor/k8s.io/client-go/pkg/version/.gitattributes deleted file mode 100644 index 7e349eff..00000000 --- a/vendor/k8s.io/client-go/pkg/version/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -base.go export-subst diff --git a/vendor/k8s.io/client-go/plugin/pkg/client/auth/exec/exec.go b/vendor/k8s.io/client-go/plugin/pkg/client/auth/exec/exec.go index e405e3dc..66649a06 100644 --- a/vendor/k8s.io/client-go/plugin/pkg/client/auth/exec/exec.go +++ b/vendor/k8s.io/client-go/plugin/pkg/client/auth/exec/exec.go @@ -201,14 +201,18 @@ func newAuthenticator(c *cache, isTerminalFunc func(int) bool, config *api.ExecC now: time.Now, environ: os.Environ, - defaultDialer: defaultDialer, - connTracker: connTracker, + connTracker: connTracker, } for _, env := range config.Env { a.env = append(a.env, env.Name+"="+env.Value) } + // these functions are made comparable and stored in the cache so that repeated clientset + // construction with the same rest.Config results in a single TLS cache and Authenticator + a.getCert = &transport.GetCertHolder{GetCert: a.cert} + a.dial = &transport.DialHolder{Dial: defaultDialer.DialContext} + return c.put(key, a), nil } @@ -263,8 +267,6 @@ type Authenticator struct { now func() time.Time environ func() []string - // defaultDialer is used for clients which don't specify a custom dialer - defaultDialer *connrotation.Dialer // connTracker tracks all connections opened that we need to close when rotating a client certificate connTracker *connrotation.ConnectionTracker @@ -275,6 +277,12 @@ type Authenticator struct { mu sync.Mutex cachedCreds *credentials exp time.Time + + // getCert makes Authenticator.cert comparable to support TLS config caching + getCert *transport.GetCertHolder + // dial is used for clients which do not specify a custom dialer + // it is comparable to support TLS config caching + dial *transport.DialHolder } type credentials struct { @@ -302,18 +310,20 @@ func (a *Authenticator) UpdateTransportConfig(c *transport.Config) error { if c.TLS.GetCert != nil { return errors.New("can't add TLS certificate callback: transport.Config.TLS.GetCert already set") } - c.TLS.GetCert = a.cert + c.TLS.GetCert = a.getCert.GetCert + c.TLS.GetCertHolder = a.getCert // comparable for TLS config caching - var d *connrotation.Dialer if c.Dial != nil { // if c has a custom dialer, we have to wrap it - d = connrotation.NewDialerWithTracker(c.Dial, a.connTracker) + // TLS config caching is not supported for this config + d := connrotation.NewDialerWithTracker(c.Dial, a.connTracker) + c.Dial = d.DialContext + c.DialHolder = nil } else { - d = a.defaultDialer + c.Dial = a.dial.Dial + c.DialHolder = a.dial // comparable for TLS config caching } - c.Dial = d.DialContext - return nil } diff --git a/vendor/k8s.io/client-go/rest/request.go b/vendor/k8s.io/client-go/rest/request.go index 5cc9900b..2061fb54 100644 --- a/vendor/k8s.io/client-go/rest/request.go +++ b/vendor/k8s.io/client-go/rest/request.go @@ -82,6 +82,12 @@ func (r *RequestConstructionError) Error() string { var noBackoff = &NoBackoff{} +type requestRetryFunc func(maxRetries int) WithRetry + +func defaultRequestRetryFn(maxRetries int) WithRetry { + return &withRetry{maxRetries: maxRetries} +} + // Request allows for building up a request to a server in a chained fashion. // Any errors are stored until the end of your call, so you only have to // check once. @@ -93,6 +99,7 @@ type Request struct { rateLimiter flowcontrol.RateLimiter backoff BackoffManager timeout time.Duration + maxRetries int // generic components accessible via method setters verb string @@ -109,9 +116,10 @@ type Request struct { subresource string // output - err error - body io.Reader - retry WithRetry + err error + body io.Reader + + retryFn requestRetryFunc } // NewRequest creates a new request helper object for accessing runtime.Objects on a server. @@ -142,7 +150,8 @@ func NewRequest(c *RESTClient) *Request { backoff: backoff, timeout: timeout, pathPrefix: pathPrefix, - retry: &withRetry{maxRetries: 10}, + maxRetries: 10, + retryFn: defaultRequestRetryFn, warningHandler: c.warningHandler, } @@ -408,7 +417,10 @@ func (r *Request) Timeout(d time.Duration) *Request { // function is specifically called with a different value. // A zero maxRetries prevent it from doing retires and return an error immediately. func (r *Request) MaxRetries(maxRetries int) *Request { - r.retry.SetMaxRetries(maxRetries) + if maxRetries < 0 { + maxRetries = 0 + } + r.maxRetries = maxRetries return r } @@ -688,8 +700,10 @@ func (r *Request) Watch(ctx context.Context) (watch.Interface, error) { } return false } + var retryAfter *RetryAfter url := r.URL().String() + withRetry := r.retryFn(r.maxRetries) for { req, err := r.newHTTPRequest(ctx) if err != nil { @@ -724,9 +738,9 @@ func (r *Request) Watch(ctx context.Context) (watch.Interface, error) { defer readAndCloseResponseBody(resp) var retry bool - retryAfter, retry = r.retry.NextRetry(req, resp, err, isErrRetryableFunc) + retryAfter, retry = withRetry.NextRetry(req, resp, err, isErrRetryableFunc) if retry { - err := r.retry.BeforeNextRetry(ctx, r.backoff, retryAfter, url, r.body) + err := withRetry.BeforeNextRetry(ctx, r.backoff, retryAfter, url, r.body) if err == nil { return false, nil } @@ -817,6 +831,7 @@ func (r *Request) Stream(ctx context.Context) (io.ReadCloser, error) { } var retryAfter *RetryAfter + withRetry := r.retryFn(r.maxRetries) url := r.URL().String() for { req, err := r.newHTTPRequest(ctx) @@ -862,9 +877,9 @@ func (r *Request) Stream(ctx context.Context) (io.ReadCloser, error) { defer resp.Body.Close() var retry bool - retryAfter, retry = r.retry.NextRetry(req, resp, err, neverRetryError) + retryAfter, retry = withRetry.NextRetry(req, resp, err, neverRetryError) if retry { - err := r.retry.BeforeNextRetry(ctx, r.backoff, retryAfter, url, r.body) + err := withRetry.BeforeNextRetry(ctx, r.backoff, retryAfter, url, r.body) if err == nil { return false, nil } @@ -961,6 +976,7 @@ func (r *Request) request(ctx context.Context, fn func(*http.Request, *http.Resp // Right now we make about ten retry attempts if we get a Retry-After response. var retryAfter *RetryAfter + withRetry := r.retryFn(r.maxRetries) for { req, err := r.newHTTPRequest(ctx) if err != nil { @@ -997,7 +1013,7 @@ func (r *Request) request(ctx context.Context, fn func(*http.Request, *http.Resp } var retry bool - retryAfter, retry = r.retry.NextRetry(req, resp, err, func(req *http.Request, err error) bool { + retryAfter, retry = withRetry.NextRetry(req, resp, err, func(req *http.Request, err error) bool { // "Connection reset by peer" or "apiserver is shutting down" are usually a transient errors. // Thus in case of "GET" operations, we simply retry it. // We are not automatically retrying "write" operations, as they are not idempotent. @@ -1011,7 +1027,7 @@ func (r *Request) request(ctx context.Context, fn func(*http.Request, *http.Resp return false }) if retry { - err := r.retry.BeforeNextRetry(ctx, r.backoff, retryAfter, req.URL.String(), r.body) + err := withRetry.BeforeNextRetry(ctx, r.backoff, retryAfter, req.URL.String(), r.body) if err == nil { return false } diff --git a/vendor/k8s.io/client-go/tools/cache/thread_safe_store.go b/vendor/k8s.io/client-go/tools/cache/thread_safe_store.go index ea34e903..71d909d4 100644 --- a/vendor/k8s.io/client-go/tools/cache/thread_safe_store.go +++ b/vendor/k8s.io/client-go/tools/cache/thread_safe_store.go @@ -284,18 +284,15 @@ func (c *threadSafeMap) updateIndices(oldObj interface{}, newObj interface{}, ke c.indices[name] = index } + if len(indexValues) == 1 && len(oldIndexValues) == 1 && indexValues[0] == oldIndexValues[0] { + // We optimize for the most common case where indexFunc returns a single value which has not been changed + continue + } + for _, value := range oldIndexValues { - // We optimize for the most common case where index returns a single value. - if len(indexValues) == 1 && value == indexValues[0] { - continue - } c.deleteKeyFromIndex(key, value, index) } for _, value := range indexValues { - // We optimize for the most common case where index returns a single value. - if len(oldIndexValues) == 1 && value == oldIndexValues[0] { - continue - } c.addKeyToIndex(key, value, index) } } diff --git a/vendor/k8s.io/client-go/tools/clientcmd/auth_loaders.go b/vendor/k8s.io/client-go/tools/clientcmd/auth_loaders.go index 0e412776..5153a95a 100644 --- a/vendor/k8s.io/client-go/tools/clientcmd/auth_loaders.go +++ b/vendor/k8s.io/client-go/tools/clientcmd/auth_loaders.go @@ -51,10 +51,10 @@ func (a *PromptingAuthLoader) LoadAuth(path string) (*clientauth.Info, error) { // Prompt for user/pass and write a file if none exists. if _, err := os.Stat(path); os.IsNotExist(err) { authPtr, err := a.Prompt() - auth := *authPtr if err != nil { return nil, err } + auth := *authPtr data, err := json.Marshal(auth) if err != nil { return &auth, err diff --git a/vendor/k8s.io/client-go/transport/cache.go b/vendor/k8s.io/client-go/transport/cache.go index 5fe768ed..f4a864d0 100644 --- a/vendor/k8s.io/client-go/transport/cache.go +++ b/vendor/k8s.io/client-go/transport/cache.go @@ -17,6 +17,7 @@ limitations under the License. package transport import ( + "context" "fmt" "net" "net/http" @@ -50,6 +51,9 @@ type tlsCacheKey struct { serverName string nextProtos string disableCompression bool + // these functions are wrapped to allow them to be used as map keys + getCert *GetCertHolder + dial *DialHolder } func (t tlsCacheKey) String() string { @@ -57,7 +61,8 @@ func (t tlsCacheKey) String() string { if len(t.keyData) > 0 { keyText = "" } - return fmt.Sprintf("insecure:%v, caData:%#v, certData:%#v, keyData:%s, serverName:%s, disableCompression:%t", t.insecure, t.caData, t.certData, keyText, t.serverName, t.disableCompression) + return fmt.Sprintf("insecure:%v, caData:%#v, certData:%#v, keyData:%s, serverName:%s, disableCompression:%t, getCert:%p, dial:%p", + t.insecure, t.caData, t.certData, keyText, t.serverName, t.disableCompression, t.getCert, t.dial) } func (c *tlsTransportCache) get(config *Config) (http.RoundTripper, error) { @@ -87,8 +92,10 @@ func (c *tlsTransportCache) get(config *Config) (http.RoundTripper, error) { return http.DefaultTransport, nil } - dial := config.Dial - if dial == nil { + var dial func(ctx context.Context, network, address string) (net.Conn, error) + if config.Dial != nil { + dial = config.Dial + } else { dial = (&net.Dialer{ Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, @@ -133,10 +140,18 @@ func tlsConfigKey(c *Config) (tlsCacheKey, bool, error) { return tlsCacheKey{}, false, err } - if c.TLS.GetCert != nil || c.Dial != nil || c.Proxy != nil { + if c.Proxy != nil { // cannot determine equality for functions return tlsCacheKey{}, false, nil } + if c.Dial != nil && c.DialHolder == nil { + // cannot determine equality for dial function that doesn't have non-nil DialHolder set as well + return tlsCacheKey{}, false, nil + } + if c.TLS.GetCert != nil && c.TLS.GetCertHolder == nil { + // cannot determine equality for getCert function that doesn't have non-nil GetCertHolder set as well + return tlsCacheKey{}, false, nil + } k := tlsCacheKey{ insecure: c.TLS.Insecure, @@ -144,6 +159,8 @@ func tlsConfigKey(c *Config) (tlsCacheKey, bool, error) { serverName: c.TLS.ServerName, nextProtos: strings.Join(c.TLS.NextProtos, ","), disableCompression: c.DisableCompression, + getCert: c.TLS.GetCertHolder, + dial: c.DialHolder, } if c.TLS.ReloadTLSFiles { diff --git a/vendor/k8s.io/client-go/transport/config.go b/vendor/k8s.io/client-go/transport/config.go index 89de798f..fd853c0b 100644 --- a/vendor/k8s.io/client-go/transport/config.go +++ b/vendor/k8s.io/client-go/transport/config.go @@ -68,7 +68,11 @@ type Config struct { WrapTransport WrapperFunc // Dial specifies the dial function for creating unencrypted TCP connections. + // If specified, this transport will be non-cacheable unless DialHolder is also set. Dial func(ctx context.Context, network, address string) (net.Conn, error) + // DialHolder can be populated to make transport configs cacheable. + // If specified, DialHolder.Dial must be equal to Dial. + DialHolder *DialHolder // Proxy is the proxy func to be used for all requests made by this // transport. If Proxy is nil, http.ProxyFromEnvironment is used. If Proxy @@ -78,6 +82,11 @@ type Config struct { Proxy func(*http.Request) (*url.URL, error) } +// DialHolder is used to make the wrapped function comparable so that it can be used as a map key. +type DialHolder struct { + Dial func(ctx context.Context, network, address string) (net.Conn, error) +} + // ImpersonationConfig has all the available impersonation options type ImpersonationConfig struct { // UserName matches user.Info.GetName() @@ -143,5 +152,15 @@ type TLSConfig struct { // To use only http/1.1, set to ["http/1.1"]. NextProtos []string - GetCert func() (*tls.Certificate, error) // Callback that returns a TLS client certificate. CertData, CertFile, KeyData and KeyFile supercede this field. + // Callback that returns a TLS client certificate. CertData, CertFile, KeyData and KeyFile supercede this field. + // If specified, this transport is non-cacheable unless CertHolder is populated. + GetCert func() (*tls.Certificate, error) + // CertHolder can be populated to make transport configs that set GetCert cacheable. + // If set, CertHolder.GetCert must be equal to GetCert. + GetCertHolder *GetCertHolder +} + +// GetCertHolder is used to make the wrapped function comparable so that it can be used as a map key. +type GetCertHolder struct { + GetCert func() (*tls.Certificate, error) } diff --git a/vendor/k8s.io/client-go/transport/transport.go b/vendor/k8s.io/client-go/transport/transport.go index b4a7bfa6..eabfce72 100644 --- a/vendor/k8s.io/client-go/transport/transport.go +++ b/vendor/k8s.io/client-go/transport/transport.go @@ -24,6 +24,7 @@ import ( "fmt" "io/ioutil" "net/http" + "reflect" "sync" "time" @@ -39,6 +40,10 @@ func New(config *Config) (http.RoundTripper, error) { return nil, fmt.Errorf("using a custom transport with TLS certificate options or the insecure flag is not allowed") } + if !isValidHolders(config) { + return nil, fmt.Errorf("misconfigured holder for dialer or cert callback") + } + var ( rt http.RoundTripper err error @@ -56,6 +61,26 @@ func New(config *Config) (http.RoundTripper, error) { return HTTPWrappersForConfig(config, rt) } +func isValidHolders(config *Config) bool { + if config.TLS.GetCertHolder != nil { + if config.TLS.GetCertHolder.GetCert == nil || + config.TLS.GetCert == nil || + reflect.ValueOf(config.TLS.GetCertHolder.GetCert).Pointer() != reflect.ValueOf(config.TLS.GetCert).Pointer() { + return false + } + } + + if config.DialHolder != nil { + if config.DialHolder.Dial == nil || + config.Dial == nil || + reflect.ValueOf(config.DialHolder.Dial).Pointer() != reflect.ValueOf(config.Dial).Pointer() { + return false + } + } + + return true +} + // TLSConfigFor returns a tls.Config that will provide the transport level security defined // by the provided Config. Will return nil if no transport level security is requested. func TLSConfigFor(c *Config) (*tls.Config, error) { diff --git a/vendor/k8s.io/component-base/version/.gitattributes b/vendor/k8s.io/component-base/version/.gitattributes deleted file mode 100644 index 7e349eff..00000000 --- a/vendor/k8s.io/component-base/version/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -base.go export-subst diff --git a/vendor/k8s.io/kubernetes/pkg/api/v1/pod/util.go b/vendor/k8s.io/kubernetes/pkg/api/v1/pod/util.go index 9560121b..8bfc21a6 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/v1/pod/util.go +++ b/vendor/k8s.io/kubernetes/pkg/api/v1/pod/util.go @@ -301,12 +301,28 @@ func IsPodReady(pod *v1.Pod) bool { return IsPodReadyConditionTrue(pod.Status) } +// IsPodTerminal returns true if a pod is terminal, all containers are stopped and cannot ever regress. +func IsPodTerminal(pod *v1.Pod) bool { + return IsPodPhaseTerminal(pod.Status.Phase) +} + +// IsPhaseTerminal returns true if the pod's phase is terminal. +func IsPodPhaseTerminal(phase v1.PodPhase) bool { + return phase == v1.PodFailed || phase == v1.PodSucceeded +} + // IsPodReadyConditionTrue returns true if a pod is ready; false otherwise. func IsPodReadyConditionTrue(status v1.PodStatus) bool { condition := GetPodReadyCondition(status) return condition != nil && condition.Status == v1.ConditionTrue } +// IsContainersReadyConditionTrue returns true if a pod is ready; false otherwise. +func IsContainersReadyConditionTrue(status v1.PodStatus) bool { + condition := GetContainersReadyCondition(status) + return condition != nil && condition.Status == v1.ConditionTrue +} + // GetPodReadyCondition extracts the pod ready condition from the given status and returns that. // Returns nil if the condition is not present. func GetPodReadyCondition(status v1.PodStatus) *v1.PodCondition { @@ -314,6 +330,13 @@ func GetPodReadyCondition(status v1.PodStatus) *v1.PodCondition { return condition } +// GetContainersReadyCondition extracts the containers ready condition from the given status and returns that. +// Returns nil if the condition is not present. +func GetContainersReadyCondition(status v1.PodStatus) *v1.PodCondition { + _, condition := GetPodCondition(&status, v1.ContainersReady) + return condition +} + // GetPodCondition extracts the provided condition from the given status and returns that. // Returns nil and -1 if the condition is not present, and the index of the located condition. func GetPodCondition(status *v1.PodStatus, conditionType v1.PodConditionType) (int, *v1.PodCondition) { diff --git a/vendor/k8s.io/kubernetes/pkg/apis/apps/types.go b/vendor/k8s.io/kubernetes/pkg/apis/apps/types.go index 70a841c2..6076d4c7 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/apps/types.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/apps/types.go @@ -246,6 +246,7 @@ type StatefulSetStatus struct { // Total number of available pods (ready for at least minReadySeconds) targeted by this statefulset. // This is a beta field and requires enabling StatefulSetMinReadySeconds feature gate. + // +optional AvailableReplicas int32 } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/core/validation/events.go b/vendor/k8s.io/kubernetes/pkg/apis/core/validation/events.go index adb0177b..a01d825d 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/core/validation/events.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/core/validation/events.go @@ -95,7 +95,18 @@ func ValidateEventUpdate(newEvent, oldEvent *core.Event, requestVersion schema.G allErrs = append(allErrs, ValidateImmutableField(newEvent.Count, oldEvent.Count, field.NewPath("count"))...) allErrs = append(allErrs, ValidateImmutableField(newEvent.Reason, oldEvent.Reason, field.NewPath("reason"))...) allErrs = append(allErrs, ValidateImmutableField(newEvent.Type, oldEvent.Type, field.NewPath("type"))...) - allErrs = append(allErrs, ValidateImmutableField(newEvent.EventTime, oldEvent.EventTime, field.NewPath("eventTime"))...) + + // Disallow changes to eventTime greater than microsecond-level precision. + // Tolerating sub-microsecond changes is required to tolerate updates + // from clients that correctly truncate to microsecond-precision when serializing, + // or from clients built with incorrect nanosecond-precision protobuf serialization. + // See https://github.com/kubernetes/kubernetes/issues/111928 + newTruncated := newEvent.EventTime.Truncate(time.Microsecond).UTC() + oldTruncated := oldEvent.EventTime.Truncate(time.Microsecond).UTC() + if newTruncated != oldTruncated { + allErrs = append(allErrs, ValidateImmutableField(newEvent.EventTime, oldEvent.EventTime, field.NewPath("eventTime"))...) + } + allErrs = append(allErrs, ValidateImmutableField(newEvent.Action, oldEvent.Action, field.NewPath("action"))...) allErrs = append(allErrs, ValidateImmutableField(newEvent.Related, oldEvent.Related, field.NewPath("related"))...) allErrs = append(allErrs, ValidateImmutableField(newEvent.ReportingController, oldEvent.ReportingController, field.NewPath("reportingController"))...) diff --git a/vendor/k8s.io/kubernetes/pkg/controller/controller_utils.go b/vendor/k8s.io/kubernetes/pkg/controller/controller_utils.go index 62242617..15d21ecd 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/controller_utils.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/controller_utils.go @@ -1127,9 +1127,14 @@ func RemoveTaintOffNode(ctx context.Context, c clientset.Interface, nodeName str // PatchNodeTaints patches node's taints. func PatchNodeTaints(ctx context.Context, c clientset.Interface, nodeName string, oldNode *v1.Node, newNode *v1.Node) error { - oldData, err := json.Marshal(oldNode) + // Strip base diff node from RV to ensure that our Patch request will set RV to check for conflicts over .spec.taints. + // This is needed because .spec.taints does not specify patchMergeKey and patchStrategy and adding them is no longer an option for compatibility reasons. + // Using other Patch strategy works for adding new taints, however will not resolve problem with taint removal. + oldNodeNoRV := oldNode.DeepCopy() + oldNodeNoRV.ResourceVersion = "" + oldDataNoRV, err := json.Marshal(&oldNodeNoRV) if err != nil { - return fmt.Errorf("failed to marshal old node %#v for node %q: %v", oldNode, nodeName, err) + return fmt.Errorf("failed to marshal old node %#v for node %q: %v", oldNodeNoRV, nodeName, err) } newTaints := newNode.Spec.Taints @@ -1140,7 +1145,7 @@ func PatchNodeTaints(ctx context.Context, c clientset.Interface, nodeName string return fmt.Errorf("failed to marshal new node %#v for node %q: %v", newNodeClone, nodeName, err) } - patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, v1.Node{}) + patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldDataNoRV, newData, v1.Node{}) if err != nil { return fmt.Errorf("failed to create patch for node %q: %v", nodeName, err) } diff --git a/vendor/k8s.io/kubernetes/pkg/features/kube_features.go b/vendor/k8s.io/kubernetes/pkg/features/kube_features.go index bcc80f8f..566e0378 100644 --- a/vendor/k8s.io/kubernetes/pkg/features/kube_features.go +++ b/vendor/k8s.io/kubernetes/pkg/features/kube_features.go @@ -910,7 +910,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS ProcMountType: {Default: false, PreRelease: featuregate.Alpha}, TTLAfterFinished: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.25 IndexedJob: {Default: true, PreRelease: featuregate.Beta}, - JobTrackingWithFinalizers: {Default: true, PreRelease: featuregate.Beta}, + JobTrackingWithFinalizers: {Default: false, PreRelease: featuregate.Beta}, // Disabled due to #109485 JobReadyPods: {Default: false, PreRelease: featuregate.Alpha}, KubeletPodResources: {Default: true, PreRelease: featuregate.Beta}, LocalStorageCapacityIsolationFSQuotaMonitoring: {Default: false, PreRelease: featuregate.Alpha}, diff --git a/vendor/k8s.io/kubernetes/pkg/proxy/util/utils.go b/vendor/k8s.io/kubernetes/pkg/proxy/util/utils.go index 4100a1e8..88ae712f 100644 --- a/vendor/k8s.io/kubernetes/pkg/proxy/util/utils.go +++ b/vendor/k8s.io/kubernetes/pkg/proxy/util/utils.go @@ -97,7 +97,7 @@ func IsProxyableIP(ip string) error { } func isProxyableIP(ip net.IP) error { - if ip.IsLoopback() || ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast() || ip.IsInterfaceLocalMulticast() { + if !ip.IsGlobalUnicast() { return ErrAddressNotAllowed } return nil diff --git a/vendor/k8s.io/kubernetes/pkg/volume/util/subpath/subpath_linux.go b/vendor/k8s.io/kubernetes/pkg/volume/util/subpath/subpath_linux.go index 7da8ca10..2fcd47c2 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/util/subpath/subpath_linux.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/util/subpath/subpath_linux.go @@ -561,18 +561,23 @@ func doSafeOpen(pathname string, base string) (int, error) { // Follow the segments one by one using openat() to make // sure the user cannot change already existing directories into symlinks. for _, seg := range segments { + var deviceStat unix.Stat_t + currentPath = filepath.Join(currentPath, seg) if !mount.PathWithinBase(currentPath, base) { return -1, fmt.Errorf("path %s is outside of allowed base %s", currentPath, base) } + // Trigger auto mount if it's an auto-mounted directory, ignore error if not a directory. + // Notice the trailing slash is mandatory, see "automount" in openat(2) and open_by_handle_at(2). + unix.Fstatat(parentFD, seg+"/", &deviceStat, unix.AT_SYMLINK_NOFOLLOW) + klog.V(5).Infof("Opening path %s", currentPath) childFD, err = syscall.Openat(parentFD, seg, openFDFlags|unix.O_CLOEXEC, 0) if err != nil { return -1, fmt.Errorf("cannot open %s: %s", currentPath, err) } - var deviceStat unix.Stat_t err := unix.Fstat(childFD, &deviceStat) if err != nil { return -1, fmt.Errorf("error running fstat on %s with %v", currentPath, err) diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/framework.go b/vendor/k8s.io/kubernetes/test/e2e/framework/framework.go index 5d72e89f..6472b891 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/framework.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/framework.go @@ -248,6 +248,9 @@ func (f *Framework) BeforeEach() { ginkgo.By("Waiting for a default service account to be provisioned in namespace") err = WaitForDefaultServiceAccountInNamespace(f.ClientSet, namespace.Name) ExpectNoError(err) + ginkgo.By("Waiting for kube-root-ca.crt to be provisioned in namespace") + err = WaitForKubeRootCAInNamespace(f.ClientSet, namespace.Name) + ExpectNoError(err) } else { Logf("Skipping waiting for service account") } diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/nodes_util.go b/vendor/k8s.io/kubernetes/test/e2e/framework/nodes_util.go index 43fe34df..df38c2c2 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/nodes_util.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/nodes_util.go @@ -34,7 +34,7 @@ import ( e2essh "k8s.io/kubernetes/test/e2e/framework/ssh" ) -const etcdImage = "3.5.1-0" +const etcdImage = "3.5.5-0" // EtcdUpgrade upgrades etcd on GCE. func EtcdUpgrade(targetStorage, targetVersion string) error { diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/test_context.go b/vendor/k8s.io/kubernetes/test/e2e/framework/test_context.go index 43508106..4fa230b4 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/test_context.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/test_context.go @@ -316,7 +316,8 @@ func RegisterCommonFlags(flags *flag.FlagSet) { flags.BoolVar(&TestContext.DumpSystemdJournal, "dump-systemd-journal", false, "Whether to dump the full systemd journal.") flags.StringVar(&TestContext.ImageServiceEndpoint, "image-service-endpoint", "", "The image service endpoint of cluster VM instances.") flags.StringVar(&TestContext.DockershimCheckpointDir, "dockershim-checkpoint-dir", "/var/lib/dockershim/sandbox", "The directory for dockershim to store sandbox checkpoints.") - flags.StringVar(&TestContext.NonblockingTaints, "non-blocking-taints", `node-role.kubernetes.io/master`, "Nodes with taints in this comma-delimited list will not block the test framework from starting tests.") + // Expect the test suite to work with both the new and legacy non-blocking control plane taints by default + flags.StringVar(&TestContext.NonblockingTaints, "non-blocking-taints", `node-role.kubernetes.io/control-plane,node-role.kubernetes.io/master`, "Nodes with taints in this comma-delimited list will not block the test framework from starting tests. The default taint 'node-role.kubernetes.io/master' is DEPRECATED and will be removed from the list in a future release.") flags.BoolVar(&TestContext.ListImages, "list-images", false, "If true, will show list of images used for runnning tests.") flags.BoolVar(&TestContext.ListConformanceTests, "list-conformance-tests", false, "If true, will show list of conformance tests.") diff --git a/vendor/k8s.io/kubernetes/test/e2e/framework/util.go b/vendor/k8s.io/kubernetes/test/e2e/framework/util.go index 3f3602e9..137dcaa8 100644 --- a/vendor/k8s.io/kubernetes/test/e2e/framework/util.go +++ b/vendor/k8s.io/kubernetes/test/e2e/framework/util.go @@ -282,6 +282,32 @@ func WaitForNamespacesDeleted(c clientset.Interface, namespaces []string, timeou }) } +func waitForConfigMapInNamespace(c clientset.Interface, ns, name string, timeout time.Duration) error { + fieldSelector := fields.OneTermEqualSelector("metadata.name", name).String() + lw := &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (object runtime.Object, e error) { + options.FieldSelector = fieldSelector + return c.CoreV1().ConfigMaps(ns).List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (i watch.Interface, e error) { + options.FieldSelector = fieldSelector + return c.CoreV1().ConfigMaps(ns).Watch(context.TODO(), options) + }, + } + ctx, cancel := watchtools.ContextWithOptionalTimeout(context.Background(), timeout) + defer cancel() + _, err := watchtools.UntilWithSync(ctx, lw, &v1.ConfigMap{}, nil, func(event watch.Event) (bool, error) { + switch event.Type { + case watch.Deleted: + return false, apierrors.NewNotFound(schema.GroupResource{Resource: "configmaps"}, name) + case watch.Added, watch.Modified: + return true, nil + } + return false, nil + }) + return err +} + func waitForServiceAccountInNamespace(c clientset.Interface, ns, serviceAccountName string, timeout time.Duration) error { fieldSelector := fields.OneTermEqualSelector("metadata.name", serviceAccountName).String() lw := &cache.ListWatch{ @@ -296,24 +322,18 @@ func waitForServiceAccountInNamespace(c clientset.Interface, ns, serviceAccountN } ctx, cancel := watchtools.ContextWithOptionalTimeout(context.Background(), timeout) defer cancel() - _, err := watchtools.UntilWithSync(ctx, lw, &v1.ServiceAccount{}, nil, serviceAccountHasSecrets) + _, err := watchtools.UntilWithSync(ctx, lw, &v1.ServiceAccount{}, nil, func(event watch.Event) (bool, error) { + switch event.Type { + case watch.Deleted: + return false, apierrors.NewNotFound(schema.GroupResource{Resource: "serviceaccounts"}, serviceAccountName) + case watch.Added, watch.Modified: + return true, nil + } + return false, nil + }) return err } -// serviceAccountHasSecrets returns true if the service account has at least one secret, -// false if it does not, or an error. -func serviceAccountHasSecrets(event watch.Event) (bool, error) { - switch event.Type { - case watch.Deleted: - return false, apierrors.NewNotFound(schema.GroupResource{Resource: "serviceaccounts"}, "") - } - switch t := event.Object.(type) { - case *v1.ServiceAccount: - return len(t.Secrets) > 0, nil - } - return false, nil -} - // WaitForDefaultServiceAccountInNamespace waits for the default service account to be provisioned // the default service account is what is associated with pods when they do not specify a service account // as a result, pods are not able to be provisioned in a namespace until the service account is provisioned @@ -321,6 +341,13 @@ func WaitForDefaultServiceAccountInNamespace(c clientset.Interface, namespace st return waitForServiceAccountInNamespace(c, namespace, "default", ServiceAccountProvisionTimeout) } +// WaitForKubeRootCAInNamespace waits for the configmap kube-root-ca.crt containing the service account +// CA trust bundle to be provisioned in the specified namespace so that pods do not have to retry mounting +// the config map (which creates noise that hides other issues in the Kubelet). +func WaitForKubeRootCAInNamespace(c clientset.Interface, namespace string) error { + return waitForConfigMapInNamespace(c, namespace, "kube-root-ca.crt", ServiceAccountProvisionTimeout) +} + // CreateTestingNS should be used by every test, note that we append a common prefix to the provided test name. // Please see NewFramework instead of using this directly. func CreateTestingNS(baseName string, c clientset.Interface, labels map[string]string) (*v1.Namespace, error) { diff --git a/vendor/k8s.io/kubernetes/test/utils/image/manifest.go b/vendor/k8s.io/kubernetes/test/utils/image/manifest.go index bc8a38b9..4329a151 100644 --- a/vendor/k8s.io/kubernetes/test/utils/image/manifest.go +++ b/vendor/k8s.io/kubernetes/test/utils/image/manifest.go @@ -17,10 +17,13 @@ limitations under the License. package image import ( + "bufio" + "bytes" "crypto/sha256" "encoding/base64" "fmt" - "io/ioutil" + "io" + "net/http" "os" "regexp" "strings" @@ -73,9 +76,20 @@ func initReg() RegistryList { return registry } - fileContent, err := ioutil.ReadFile(repoList) - if err != nil { - panic(fmt.Errorf("Error reading '%v' file contents: %v", repoList, err)) + var fileContent []byte + var err error + if strings.HasPrefix(repoList, "https://") || strings.HasPrefix(repoList, "http://") { + var b bytes.Buffer + err = readFromURL(repoList, bufio.NewWriter(&b)) + if err != nil { + panic(fmt.Errorf("error reading '%v' url contents: %v", repoList, err)) + } + fileContent = b.Bytes() + } else { + fileContent, err = os.ReadFile(repoList) + if err != nil { + panic(fmt.Errorf("error reading '%v' file contents: %v", repoList, err)) + } } err = yaml.Unmarshal(fileContent, ®istry) @@ -85,6 +99,27 @@ func initReg() RegistryList { return registry } +// Essentially curl url | writer +func readFromURL(url string, writer io.Writer) error { + httpTransport := new(http.Transport) + httpTransport.Proxy = http.ProxyFromEnvironment + + c := &http.Client{Transport: httpTransport} + r, err := c.Get(url) + if err != nil { + return err + } + defer r.Body.Close() + if r.StatusCode >= 400 { + return fmt.Errorf("%v returned %d", url, r.StatusCode) + } + _, err = io.Copy(writer, r.Body) + if err != nil { + return err + } + return nil +} + var ( initRegistry = RegistryList{ GcAuthenticatedRegistry: "gcr.io/authenticated-image-pulling", @@ -198,7 +233,7 @@ const ( func initImageConfigs(list RegistryList) (map[int]Config, map[int]Config) { configs := map[int]Config{} - configs[Agnhost] = Config{list.PromoterE2eRegistry, "agnhost", "2.33"} + configs[Agnhost] = Config{list.PromoterE2eRegistry, "agnhost", "2.39"} configs[AgnhostPrivate] = Config{list.PrivateRegistry, "agnhost", "2.6"} configs[AuthenticatedAlpine] = Config{list.GcAuthenticatedRegistry, "alpine", "3.7"} configs[AuthenticatedWindowsNanoServer] = Config{list.GcAuthenticatedRegistry, "windows-nanoserver", "v1"} @@ -210,7 +245,7 @@ func initImageConfigs(list RegistryList) (map[int]Config, map[int]Config) { configs[CudaVectorAdd2] = Config{list.PromoterE2eRegistry, "cuda-vector-add", "2.2"} configs[DebianIptables] = Config{list.BuildImageRegistry, "debian-iptables", "bullseye-v1.1.0"} configs[EchoServer] = Config{list.PromoterE2eRegistry, "echoserver", "2.4"} - configs[Etcd] = Config{list.GcEtcdRegistry, "etcd", "3.5.1-0"} + configs[Etcd] = Config{list.GcEtcdRegistry, "etcd", "3.5.5-0"} configs[GlusterDynamicProvisioner] = Config{list.PromoterE2eRegistry, "glusterdynamic-provisioner", "v1.3"} configs[Httpd] = Config{list.PromoterE2eRegistry, "httpd", "2.4.38-2"} configs[HttpdNew] = Config{list.PromoterE2eRegistry, "httpd", "2.4.39-2"} diff --git a/vendor/modules.txt b/vendor/modules.txt index 94546713..7cb2ab83 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -466,7 +466,7 @@ gopkg.in/yaml.v2 # gopkg.in/yaml.v3 v3.0.1 ## explicit gopkg.in/yaml.v3 -# k8s.io/api v0.23.3 => k8s.io/api v0.23.3 +# k8s.io/api v0.23.14 => k8s.io/api v0.23.14 ## explicit; go 1.16 k8s.io/api/admission/v1 k8s.io/api/admission/v1beta1 @@ -515,7 +515,7 @@ k8s.io/api/scheduling/v1beta1 k8s.io/api/storage/v1 k8s.io/api/storage/v1alpha1 k8s.io/api/storage/v1beta1 -# k8s.io/apimachinery v0.23.3 => k8s.io/apimachinery v0.23.3 +# k8s.io/apimachinery v0.23.14 => k8s.io/apimachinery v0.23.14 ## explicit; go 1.16 k8s.io/apimachinery/pkg/api/equality k8s.io/apimachinery/pkg/api/errors @@ -571,7 +571,7 @@ k8s.io/apimachinery/pkg/watch k8s.io/apimachinery/third_party/forked/golang/json k8s.io/apimachinery/third_party/forked/golang/netutil k8s.io/apimachinery/third_party/forked/golang/reflect -# k8s.io/apiserver v0.23.3 => k8s.io/apiserver v0.23.3 +# k8s.io/apiserver v0.23.14 => k8s.io/apiserver v0.23.14 ## explicit; go 1.16 k8s.io/apiserver/pkg/admission k8s.io/apiserver/pkg/admission/configuration @@ -612,7 +612,7 @@ k8s.io/apiserver/pkg/util/feature k8s.io/apiserver/pkg/util/webhook k8s.io/apiserver/pkg/util/x509metrics k8s.io/apiserver/pkg/warning -# k8s.io/client-go v0.23.3 => k8s.io/client-go v0.23.3 +# k8s.io/client-go v0.23.14 => k8s.io/client-go v0.23.14 ## explicit; go 1.16 k8s.io/client-go/applyconfigurations/admissionregistration/v1 k8s.io/client-go/applyconfigurations/admissionregistration/v1beta1 @@ -852,10 +852,10 @@ k8s.io/client-go/util/homedir k8s.io/client-go/util/keyutil k8s.io/client-go/util/retry k8s.io/client-go/util/workqueue -# k8s.io/cloud-provider v0.23.3 => k8s.io/cloud-provider v0.23.3 +# k8s.io/cloud-provider v0.23.14 => k8s.io/cloud-provider v0.23.14 ## explicit; go 1.16 k8s.io/cloud-provider -# k8s.io/component-base v0.23.3 => k8s.io/component-base v0.23.3 +# k8s.io/component-base v0.23.14 => k8s.io/component-base v0.23.14 ## explicit; go 1.16 k8s.io/component-base/cli/flag k8s.io/component-base/config @@ -865,7 +865,7 @@ k8s.io/component-base/metrics/legacyregistry k8s.io/component-base/metrics/testutil k8s.io/component-base/traces k8s.io/component-base/version -# k8s.io/component-helpers v0.23.3 => k8s.io/component-helpers v0.23.3 +# k8s.io/component-helpers v0.23.14 => k8s.io/component-helpers v0.23.14 ## explicit; go 1.16 k8s.io/component-helpers/node/util/sysctl k8s.io/component-helpers/scheduling/corev1 @@ -882,14 +882,14 @@ k8s.io/klog/v2/internal/severity ## explicit; go 1.16 k8s.io/kube-openapi/pkg/schemaconv k8s.io/kube-openapi/pkg/util/proto -# k8s.io/kubectl v0.0.0 => k8s.io/kubectl v0.23.3 +# k8s.io/kubectl v0.0.0 => k8s.io/kubectl v0.23.14 ## explicit; go 1.16 k8s.io/kubectl/pkg/scale k8s.io/kubectl/pkg/util/podutils -# k8s.io/kubelet v0.0.0 => k8s.io/kubelet v0.23.3 +# k8s.io/kubelet v0.0.0 => k8s.io/kubelet v0.23.14 ## explicit; go 1.16 k8s.io/kubelet/pkg/apis/stats/v1alpha1 -# k8s.io/kubernetes v1.23.3 +# k8s.io/kubernetes v1.23.14 ## explicit; go 1.16 k8s.io/kubernetes/pkg/api/legacyscheme k8s.io/kubernetes/pkg/api/service @@ -952,7 +952,7 @@ k8s.io/kubernetes/test/e2e/storage/podlogs k8s.io/kubernetes/test/e2e/storage/utils k8s.io/kubernetes/test/utils k8s.io/kubernetes/test/utils/image -# k8s.io/mount-utils v0.23.3 => k8s.io/mount-utils v0.0.0-20230103133730-1df1a57439e2 +# k8s.io/mount-utils v0.23.14 => k8s.io/mount-utils v0.0.0-20230103133730-1df1a57439e2 ## explicit; go 1.19 k8s.io/mount-utils # k8s.io/utils v0.0.0-20221107191617-1a15be271d1d @@ -972,7 +972,7 @@ k8s.io/utils/nsenter k8s.io/utils/path k8s.io/utils/pointer k8s.io/utils/trace -# sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.27 +# sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.33 ## explicit; go 1.17 sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client sigs.k8s.io/apiserver-network-proxy/konnectivity-client/proto/client @@ -989,30 +989,30 @@ sigs.k8s.io/structured-merge-diff/v4/value # sigs.k8s.io/yaml v1.2.0 ## explicit; go 1.12 sigs.k8s.io/yaml -# k8s.io/api => k8s.io/api v0.23.3 -# k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.23.3 -# k8s.io/apimachinery => k8s.io/apimachinery v0.23.3 -# k8s.io/apiserver => k8s.io/apiserver v0.23.3 -# k8s.io/cli-runtime => k8s.io/cli-runtime v0.23.3 -# k8s.io/client-go => k8s.io/client-go v0.23.3 -# k8s.io/cloud-provider => k8s.io/cloud-provider v0.23.3 -# k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.23.3 -# k8s.io/code-generator => k8s.io/code-generator v0.23.3 -# k8s.io/component-base => k8s.io/component-base v0.23.3 -# k8s.io/component-helpers => k8s.io/component-helpers v0.23.3 -# k8s.io/controller-manager => k8s.io/controller-manager v0.23.3 -# k8s.io/cri-api => k8s.io/cri-api v0.23.3 -# k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.23.3 -# k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.23.3 -# k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.23.3 -# k8s.io/kube-proxy => k8s.io/kube-proxy v0.23.3 -# k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.23.3 -# k8s.io/kubectl => k8s.io/kubectl v0.23.3 -# k8s.io/kubelet => k8s.io/kubelet v0.23.3 -# k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.23.3 -# k8s.io/metrics => k8s.io/metrics v0.23.3 +# k8s.io/api => k8s.io/api v0.23.14 +# k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.23.14 +# k8s.io/apimachinery => k8s.io/apimachinery v0.23.14 +# k8s.io/apiserver => k8s.io/apiserver v0.23.14 +# k8s.io/cli-runtime => k8s.io/cli-runtime v0.23.14 +# k8s.io/client-go => k8s.io/client-go v0.23.14 +# k8s.io/cloud-provider => k8s.io/cloud-provider v0.23.14 +# k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.23.14 +# k8s.io/code-generator => k8s.io/code-generator v0.23.14 +# k8s.io/component-base => k8s.io/component-base v0.23.14 +# k8s.io/component-helpers => k8s.io/component-helpers v0.23.14 +# k8s.io/controller-manager => k8s.io/controller-manager v0.23.14 +# k8s.io/cri-api => k8s.io/cri-api v0.23.14 +# k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.23.14 +# k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.23.14 +# k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.23.14 +# k8s.io/kube-proxy => k8s.io/kube-proxy v0.23.14 +# k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.23.14 +# k8s.io/kubectl => k8s.io/kubectl v0.23.14 +# k8s.io/kubelet => k8s.io/kubelet v0.23.14 +# k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.23.14 +# k8s.io/metrics => k8s.io/metrics v0.23.14 # k8s.io/mount-utils => k8s.io/mount-utils v0.0.0-20230103133730-1df1a57439e2 -# k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.23.3 -# k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.23.3 -# k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.23.3 -# k8s.io/sample-controller => k8s.io/sample-controller v0.23.3 +# k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.23.14 +# k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.23.14 +# k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.23.14 +# k8s.io/sample-controller => k8s.io/sample-controller v0.23.14 diff --git a/vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/client.go b/vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/client.go index 6f247128..c55070ae 100644 --- a/vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/client.go +++ b/vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/client.go @@ -24,6 +24,7 @@ import ( "math/rand" "net" "sync" + "sync/atomic" "time" "google.golang.org/grpc" @@ -35,25 +36,101 @@ import ( type Tunnel interface { // Dial connects to the address on the named network, similar to // what net.Dial does. The only supported protocol is tcp. - DialContext(ctx context.Context, protocol, address string) (net.Conn, error) + DialContext(requestCtx context.Context, protocol, address string) (net.Conn, error) + // Done returns a channel that is closed when the tunnel is no longer serving any connections, + // and can no longer be used. + Done() <-chan struct{} } type dialResult struct { - err string + err *dialFailure connid int64 } +type pendingDial struct { + // resultCh is the channel to send the dial result to + resultCh chan<- dialResult + // cancelCh is the channel closed when resultCh no longer has a receiver + cancelCh <-chan struct{} +} + +// TODO: Replace with a generic implementation once it is safe to assume the client is built with go1.18+ +type pendingDialManager struct { + pendingDials map[int64]pendingDial + mutex sync.RWMutex +} + +func (p *pendingDialManager) add(dialID int64, pd pendingDial) { + p.mutex.Lock() + defer p.mutex.Unlock() + p.pendingDials[dialID] = pd +} + +func (p *pendingDialManager) remove(dialID int64) { + p.mutex.Lock() + defer p.mutex.Unlock() + delete(p.pendingDials, dialID) +} + +func (p *pendingDialManager) get(dialID int64) (pendingDial, bool) { + p.mutex.RLock() + defer p.mutex.RUnlock() + pd, ok := p.pendingDials[dialID] + return pd, ok +} + +// TODO: Replace with a generic implementation once it is safe to assume the client is built with go1.18+ +type connectionManager struct { + conns map[int64]*conn + mutex sync.RWMutex +} + +func (cm *connectionManager) add(connID int64, c *conn) { + cm.mutex.Lock() + defer cm.mutex.Unlock() + cm.conns[connID] = c +} + +func (cm *connectionManager) remove(connID int64) { + cm.mutex.Lock() + defer cm.mutex.Unlock() + delete(cm.conns, connID) +} + +func (cm *connectionManager) get(connID int64) (*conn, bool) { + cm.mutex.RLock() + defer cm.mutex.RUnlock() + c, ok := cm.conns[connID] + return c, ok +} + +func (cm *connectionManager) closeAll() { + cm.mutex.Lock() + defer cm.mutex.Unlock() + for _, conn := range cm.conns { + close(conn.readCh) + } +} + // grpcTunnel implements Tunnel type grpcTunnel struct { - stream client.ProxyService_ProxyClient - pendingDial map[int64]chan<- dialResult - conns map[int64]*conn - pendingDialLock sync.RWMutex - connsLock sync.RWMutex + stream client.ProxyService_ProxyClient + clientConn clientConn + pendingDial pendingDialManager + conns connectionManager // The tunnel will be closed if the caller fails to read via conn.Read() // more than readTimeoutSeconds after a packet has been received. readTimeoutSeconds int + + // The done channel is closed after the tunnel has cleaned up all connections and is no longer + // serving. + done chan struct{} + + // closing is an atomic bool represented as a 0 or 1, and set to true when the tunnel is being closed. + // closing should only be accessed through atomic methods. + // TODO: switch this to an atomic.Bool once the client is exclusively buit with go1.19+ + closing uint32 } type clientConn interface { @@ -66,37 +143,65 @@ var _ clientConn = &grpc.ClientConn{} // gRPC based proxy service. // Currently, a single tunnel supports a single connection, and the tunnel is closed when the connection is terminated // The Dial() method of the returned tunnel should only be called once -func CreateSingleUseGrpcTunnel(ctx context.Context, address string, opts ...grpc.DialOption) (Tunnel, error) { - c, err := grpc.DialContext(ctx, address, opts...) +// Deprecated 2022-06-07: use CreateSingleUseGrpcTunnelWithContext +func CreateSingleUseGrpcTunnel(tunnelCtx context.Context, address string, opts ...grpc.DialOption) (Tunnel, error) { + return CreateSingleUseGrpcTunnelWithContext(context.TODO(), tunnelCtx, address, opts...) +} + +// CreateSingleUseGrpcTunnelWithContext creates a Tunnel to dial to a remote server through a +// gRPC based proxy service. +// Currently, a single tunnel supports a single connection. +// The tunnel is normally closed when the connection is terminated. +// If createCtx is cancelled before tunnel creation, an error will be returned. +// If tunnelCtx is cancelled while the tunnel is still in use, the tunnel (and any in flight connections) will be closed. +// The Dial() method of the returned tunnel should only be called once +func CreateSingleUseGrpcTunnelWithContext(createCtx, tunnelCtx context.Context, address string, opts ...grpc.DialOption) (Tunnel, error) { + c, err := grpc.DialContext(createCtx, address, opts...) if err != nil { return nil, err } grpcClient := client.NewProxyServiceClient(c) - stream, err := grpcClient.Proxy(ctx) + stream, err := grpcClient.Proxy(tunnelCtx) if err != nil { + c.Close() return nil, err } - tunnel := &grpcTunnel{ - stream: stream, - pendingDial: make(map[int64]chan<- dialResult), - conns: make(map[int64]*conn), - readTimeoutSeconds: 10, - } + tunnel := newUnstartedTunnel(stream, c) - go tunnel.serve(c) + go tunnel.serve(tunnelCtx) return tunnel, nil } -func (t *grpcTunnel) serve(c clientConn) { - defer c.Close() +func newUnstartedTunnel(stream client.ProxyService_ProxyClient, c clientConn) *grpcTunnel { + return &grpcTunnel{ + stream: stream, + clientConn: c, + pendingDial: pendingDialManager{pendingDials: make(map[int64]pendingDial)}, + conns: connectionManager{conns: make(map[int64]*conn)}, + readTimeoutSeconds: 10, + done: make(chan struct{}), + } +} + +func (t *grpcTunnel) serve(tunnelCtx context.Context) { + defer func() { + t.clientConn.Close() + + // A connection in t.conns after serve() returns means + // we never received a CLOSE_RSP for it, so we need to + // close any channels remaining for these connections. + t.conns.closeAll() + + close(t.done) + }() for { pkt, err := t.stream.Recv() - if err == io.EOF { + if err == io.EOF || t.isClosing() { return } if err != nil || pkt == nil { @@ -109,25 +214,35 @@ func (t *grpcTunnel) serve(c clientConn) { switch pkt.Type { case client.PacketType_DIAL_RSP: resp := pkt.GetDialResponse() - t.pendingDialLock.RLock() - ch, ok := t.pendingDial[resp.Random] - t.pendingDialLock.RUnlock() + pendingDial, ok := t.pendingDial.get(resp.Random) if !ok { + // If the DIAL_RSP does not match a pending dial, it means one of two things: + // 1. There was a second DIAL_RSP for the connection request (this is very unlikely but possible) + // 2. grpcTunnel.DialContext() returned early due to a dial timeout or the client canceling the context + // + // In either scenario, we should return here and close the tunnel as it is no longer needed. klog.V(1).InfoS("DialResp not recognized; dropped", "connectionID", resp.ConnectID, "dialID", resp.Random) return - } else { - result := dialResult{ - err: resp.Error, - connid: resp.ConnectID, - } - select { - case ch <- result: - default: - klog.ErrorS(fmt.Errorf("blocked pending channel"), "Received second dial response for connection request", "connectionID", resp.ConnectID, "dialID", resp.Random) - // On multiple dial responses, avoid leaking serve goroutine. - return - } + } + + result := dialResult{connid: resp.ConnectID} + if resp.Error != "" { + result.err = &dialFailure{resp.Error, DialFailureEndpoint} + } + select { + // try to send to the result channel + case pendingDial.resultCh <- result: + // unblock if the cancel channel is closed + case <-pendingDial.cancelCh: + // Note: this condition can only be hit by a race condition where the + // DialContext() returns early (timeout) after the pendingDial is already + // fetched here, but before the result is sent. + klog.V(1).InfoS("Pending dial has been cancelled; dropped", "connectionID", resp.ConnectID, "dialID", resp.Random) + return + case <-tunnelCtx.Done(): + klog.V(1).InfoS("Tunnel has been closed; dropped", "connectionID", resp.ConnectID, "dialID", resp.Random) + return } if resp.Error != "" { @@ -135,62 +250,93 @@ func (t *grpcTunnel) serve(c clientConn) { return } + case client.PacketType_DIAL_CLS: + resp := pkt.GetCloseDial() + pendingDial, ok := t.pendingDial.get(resp.Random) + + if !ok { + // If the DIAL_CLS does not match a pending dial, it means one of two things: + // 1. There was a DIAL_CLS receieved after a DIAL_RSP (unlikely but possible) + // 2. grpcTunnel.DialContext() returned early due to a dial timeout or the client canceling the context + // + // In either scenario, we should return here and close the tunnel as it is no longer needed. + klog.V(1).InfoS("DIAL_CLS after dial finished", "dialID", resp.Random) + } else { + result := dialResult{ + err: &dialFailure{"dial closed", DialFailureDialClosed}, + } + select { + case pendingDial.resultCh <- result: + case <-pendingDial.cancelCh: + // Note: this condition can only be hit by a race condition where the + // DialContext() returns early (timeout) after the pendingDial is already + // fetched here, but before the result is sent. + case <-tunnelCtx.Done(): + } + } + return // Stop serving & close the tunnel. + case client.PacketType_DATA: resp := pkt.GetData() // TODO: flow control - t.connsLock.RLock() - conn, ok := t.conns[resp.ConnectID] - t.connsLock.RUnlock() + conn, ok := t.conns.get(resp.ConnectID) - if ok { - timer := time.NewTimer((time.Duration)(t.readTimeoutSeconds) * time.Second) - select { - case conn.readCh <- resp.Data: - timer.Stop() - case <-timer.C: - klog.ErrorS(fmt.Errorf("timeout"), "readTimeout has been reached, the grpc connection to the proxy server will be closed", "connectionID", conn.connID, "readTimeoutSeconds", t.readTimeoutSeconds) - return - } - } else { - klog.V(1).InfoS("connection not recognized", "connectionID", resp.ConnectID) + if !ok { + klog.V(1).InfoS("Connection not recognized", "connectionID", resp.ConnectID) + continue } + timer := time.NewTimer((time.Duration)(t.readTimeoutSeconds) * time.Second) + select { + case conn.readCh <- resp.Data: + timer.Stop() + case <-timer.C: + klog.ErrorS(fmt.Errorf("timeout"), "readTimeout has been reached, the grpc connection to the proxy server will be closed", "connectionID", conn.connID, "readTimeoutSeconds", t.readTimeoutSeconds) + return + case <-tunnelCtx.Done(): + klog.V(1).InfoS("Tunnel has been closed, the grpc connection to the proxy server will be closed", "connectionID", conn.connID) + } + case client.PacketType_CLOSE_RSP: resp := pkt.GetCloseResponse() - t.connsLock.RLock() - conn, ok := t.conns[resp.ConnectID] - t.connsLock.RUnlock() + conn, ok := t.conns.get(resp.ConnectID) - if ok { - close(conn.readCh) - conn.closeCh <- resp.Error - close(conn.closeCh) - t.connsLock.Lock() - delete(t.conns, resp.ConnectID) - t.connsLock.Unlock() - return + if !ok { + klog.V(1).InfoS("Connection not recognized", "connectionID", resp.ConnectID) + continue } - klog.V(1).InfoS("connection not recognized", "connectionID", resp.ConnectID) + close(conn.readCh) + conn.closeCh <- resp.Error + close(conn.closeCh) + t.conns.remove(resp.ConnectID) + return } } } // Dial connects to the address on the named network, similar to // what net.Dial does. The only supported protocol is tcp. -func (t *grpcTunnel) DialContext(ctx context.Context, protocol, address string) (net.Conn, error) { +func (t *grpcTunnel) DialContext(requestCtx context.Context, protocol, address string) (net.Conn, error) { + select { + case <-t.done: + return nil, errors.New("tunnel is closed") + default: // Tunnel is open, carry on. + } + if protocol != "tcp" { return nil, errors.New("protocol not supported") } random := rand.Int63() /* #nosec G404 */ - resCh := make(chan dialResult, 1) - t.pendingDialLock.Lock() - t.pendingDial[random] = resCh - t.pendingDialLock.Unlock() - defer func() { - t.pendingDialLock.Lock() - delete(t.pendingDial, random) - t.pendingDialLock.Unlock() - }() + + // This channel is closed once we're returning and no longer waiting on resultCh + cancelCh := make(chan struct{}) + defer close(cancelCh) + + // This channel MUST NOT be buffered. The sender needs to know when we are not receiving things, so they can abort. + resCh := make(chan dialResult) + + t.pendingDial.add(random, pendingDial{resultCh: resCh, cancelCh: cancelCh}) + defer t.pendingDial.remove(random) req := &client.Packet{ Type: client.PacketType_DIAL_REQ, @@ -211,24 +357,98 @@ func (t *grpcTunnel) DialContext(ctx context.Context, protocol, address string) klog.V(5).Infoln("DIAL_REQ sent to proxy server") - c := &conn{stream: t.stream, random: random} + c := &conn{ + stream: t.stream, + random: random, + closeTunnel: t.closeTunnel, + } select { case res := <-resCh: - if res.err != "" { - return nil, errors.New(res.err) + if res.err != nil { + return nil, res.err } c.connID = res.connid c.readCh = make(chan []byte, 10) c.closeCh = make(chan string, 1) - t.connsLock.Lock() - t.conns[res.connid] = c - t.connsLock.Unlock() + t.conns.add(res.connid, c) case <-time.After(30 * time.Second): - return nil, errors.New("dial timeout, backstop") - case <-ctx.Done(): - return nil, errors.New("dial timeout, context") + klog.V(5).InfoS("Timed out waiting for DialResp", "dialID", random) + go t.closeDial(random) + return nil, &dialFailure{"dial timeout, backstop", DialFailureTimeout} + case <-requestCtx.Done(): + klog.V(5).InfoS("Context canceled waiting for DialResp", "ctxErr", requestCtx.Err(), "dialID", random) + go t.closeDial(random) + return nil, &dialFailure{"dial timeout, context", DialFailureContext} + case <-t.done: + klog.V(5).InfoS("Tunnel closed while waiting for DialResp", "dialID", random) + return nil, &dialFailure{"tunnel closed", DialFailureTunnelClosed} } return c, nil } + +func (t *grpcTunnel) Done() <-chan struct{} { + return t.done +} + +// Send a best-effort DIAL_CLS request for the given dial ID. +func (t *grpcTunnel) closeDial(dialID int64) { + req := &client.Packet{ + Type: client.PacketType_DIAL_CLS, + Payload: &client.Packet_CloseDial{ + CloseDial: &client.CloseDial{ + Random: dialID, + }, + }, + } + if err := t.stream.Send(req); err != nil { + klog.V(5).InfoS("Failed to send DIAL_CLS", "err", err, "dialID", dialID) + } + t.closeTunnel() +} + +func (t *grpcTunnel) closeTunnel() { + atomic.StoreUint32(&t.closing, 1) + t.clientConn.Close() +} + +func (t *grpcTunnel) isClosing() bool { + return atomic.LoadUint32(&t.closing) != 0 +} + +func GetDialFailureReason(err error) (isDialFailure bool, reason DialFailureReason) { + var df *dialFailure + if errors.As(err, &df) { + return true, df.reason + } + return false, DialFailureUnknown +} + +type dialFailure struct { + msg string + reason DialFailureReason +} + +func (df *dialFailure) Error() string { + return df.msg +} + +type DialFailureReason string + +const ( + DialFailureUnknown DialFailureReason = "unknown" + // DialFailureTimeout indicates the hard 30 second timeout was hit. + DialFailureTimeout DialFailureReason = "timeout" + // DialFailureContext indicates that the context was cancelled or reached it's deadline before + // the dial response was returned. + DialFailureContext DialFailureReason = "context" + // DialFailureEndpoint indicates that the konnectivity-agent was unable to reach the backend endpoint. + DialFailureEndpoint DialFailureReason = "endpoint" + // DialFailureDialClosed indicates that the client received a CloseDial response, indicating the + // connection was closed before the dial could complete. + DialFailureDialClosed DialFailureReason = "dialclosed" + // DialFailureTunnelClosed indicates that the client connection was closed before the dial could + // complete. + DialFailureTunnelClosed DialFailureReason = "tunnelclosed" +) diff --git a/vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/conn.go b/vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/conn.go index cc6e66be..f76b1e37 100644 --- a/vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/conn.go +++ b/vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/conn.go @@ -30,6 +30,8 @@ import ( // successful delivery of CLOSE_REQ. const CloseTimeout = 10 * time.Second +var errConnCloseTimeout = errors.New("close timeout") + // conn is an implementation of net.Conn, where the data is transported // over an established tunnel defined by a gRPC service ProxyService. type conn struct { @@ -39,6 +41,9 @@ type conn struct { readCh chan []byte closeCh chan string rdata []byte + + // closeTunnel is an optional callback to close the underlying grpc connection. + closeTunnel func() } var _ net.Conn = &conn{} @@ -114,6 +119,10 @@ func (c *conn) SetWriteDeadline(t time.Time) error { // proxy service to notify remote to drop the connection. func (c *conn) Close() error { klog.V(4).Infoln("closing connection") + if c.closeTunnel != nil { + defer c.closeTunnel() + } + var req *client.Packet if c.connID != 0 { req = &client.Packet{ @@ -151,5 +160,5 @@ func (c *conn) Close() error { case <-time.After(CloseTimeout): } - return errors.New("close timeout") + return errConnCloseTimeout }