diff --git a/0001-fix-compile-options.patch b/0001-fix-compile-options.patch index d30d9150a19e90809ec1eccf140f50eb3a632a88..5daef9057c74a8420c6a8753909dd9088b39c369 100644 --- a/0001-fix-compile-options.patch +++ b/0001-fix-compile-options.patch @@ -1,7 +1,7 @@ -From 6f69a95a25dc6fb1b3d0e024cb28f5c83022dc58 Mon Sep 17 00:00:00 2001 +From d49390e67b2d3027c8c0ad799bf294a89d4d149f Mon Sep 17 00:00:00 2001 From: zhangxiaoyu -Date: Tue, 3 Jan 2023 14:19:44 +0800 -Subject: fix compile options +Date: Thu, 20 Jul 2023 17:27:05 +0800 +Subject: [PATCH] fix compile options Signed-off-by: zhangxiaoyu --- @@ -9,10 +9,10 @@ Signed-off-by: zhangxiaoyu 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hack/lib/golang.sh b/hack/lib/golang.sh -index 2865da28..ed64483e 100755 +index 232c17b3..c6cbce44 100755 --- a/hack/lib/golang.sh +++ b/hack/lib/golang.sh -@@ -709,6 +709,7 @@ kube::golang::build_binaries_for_platform() { +@@ -744,6 +744,7 @@ kube::golang::build_binaries_for_platform() { -installsuffix=static ${goflags:+"${goflags[@]}"} -gcflags="${gogcflags}" @@ -20,7 +20,7 @@ index 2865da28..ed64483e 100755 -asmflags="${goasmflags}" -ldflags="${goldflags}" -tags="${gotags:-}" -@@ -720,6 +721,7 @@ kube::golang::build_binaries_for_platform() { +@@ -755,6 +756,7 @@ kube::golang::build_binaries_for_platform() { build_args=( ${goflags:+"${goflags[@]}"} -gcflags="${gogcflags}" @@ -28,8 +28,8 @@ index 2865da28..ed64483e 100755 -asmflags="${goasmflags}" -ldflags="${goldflags}" -tags="${gotags:-}" -@@ -808,7 +810,7 @@ kube::golang::build_binaries() { - gogcflags="${gogcflags} -N -l" +@@ -844,7 +846,7 @@ kube::golang::build_binaries() { + goasmflags="" fi - goldflags="all=$(kube::version::ldflags) ${GOLDFLAGS:-}" diff --git a/0002-kubelet-support-exec-and-attach-websocket-protocol.patch b/0002-kubelet-support-exec-and-attach-websocket-protocol.patch index 9c16e4bb10194ae1e2354ba93f579aeb0b93c8b4..782e8693415f48a8ce41099501fca5fce99ff792 100644 --- a/0002-kubelet-support-exec-and-attach-websocket-protocol.patch +++ b/0002-kubelet-support-exec-and-attach-websocket-protocol.patch @@ -1,21 +1,21 @@ -From 2bdde6764d529d9f0633178b171aa193280d6ecb Mon Sep 17 00:00:00 2001 +From cb4f12375beffd61f3b2d666ca3f92d574ceb597 Mon Sep 17 00:00:00 2001 From: zhangxiaoyu Date: Tue, 3 Jan 2023 14:20:10 +0800 -Subject: kubelet support exec and attach websocket protocol +Subject: [PATCH] kubelet support exec and attach websocket protocol Signed-off-by: zhangxiaoyu --- - .../cri/streaming/remotecommand/proxy.go | 206 ++++++++++++++++++ + .../cri/streaming/remotecommand/proxy.go | 212 ++++++++++++++++++ pkg/kubelet/server/server.go | 43 +++- - 2 files changed, 241 insertions(+), 8 deletions(-) + 2 files changed, 247 insertions(+), 8 deletions(-) create mode 100644 pkg/kubelet/cri/streaming/remotecommand/proxy.go diff --git a/pkg/kubelet/cri/streaming/remotecommand/proxy.go b/pkg/kubelet/cri/streaming/remotecommand/proxy.go new file mode 100644 -index 00000000..f21629af +index 00000000..179d8183 --- /dev/null +++ b/pkg/kubelet/cri/streaming/remotecommand/proxy.go -@@ -0,0 +1,206 @@ +@@ -0,0 +1,212 @@ +package remotecommand + +import ( @@ -33,8 +33,8 @@ index 00000000..f21629af + "k8s.io/apimachinery/pkg/apis/meta/v1" + remotecommandconsts "k8s.io/apimachinery/pkg/util/remotecommand" + "k8s.io/apimachinery/pkg/util/runtime" ++ "k8s.io/client-go/util/exec" + "k8s.io/klog/v2" -+ "k8s.io/kubernetes/staging/src/k8s.io/client-go/util/exec" +) + +var ( @@ -147,6 +147,12 @@ index 00000000..f21629af + case <-frontendResizeToBackendComplete: + } + ++ select { ++ case <-backendToFrontendComplete: ++ case <-time.Tick(30 * time.Second): ++ klog.Errorf("Wait backend to frontend complete timeout") ++ } ++ + if errConnection != nil { + klog.Errorf("SpdyProxy: the connection disconnected: %v", errConnection) + if exitErr, ok := errConnection.(exec.ExitError); ok && exitErr.Exited() { @@ -223,10 +229,10 @@ index 00000000..f21629af + return len(p), nil +} diff --git a/pkg/kubelet/server/server.go b/pkg/kubelet/server/server.go -index 127192e0..cd11f807 100644 +index 84dbd545..73627d5b 100644 --- a/pkg/kubelet/server/server.go +++ b/pkg/kubelet/server/server.go -@@ -769,51 +769,78 @@ func proxyStream(w http.ResponseWriter, r *http.Request, url *url.URL) { +@@ -797,51 +797,78 @@ func proxyStream(w http.ResponseWriter, r *http.Request, url *url.URL) { // getAttach handles requests to attach to a container. func (s *Server) getAttach(request *restful.Request, response *restful.Response) { diff --git a/0005-Escape-terminal-special-characters-in-kubectl-112553.patch b/0003-Escape-terminal-special-characters-in-kubectl-112553.patch similarity index 95% rename from 0005-Escape-terminal-special-characters-in-kubectl-112553.patch rename to 0003-Escape-terminal-special-characters-in-kubectl-112553.patch index ee9b1ec6c95d07100c54966ab7402882a441b6c7..1ddb04bdd3da6f7f029a624a0868d6d8873eaa0d 100644 --- a/0005-Escape-terminal-special-characters-in-kubectl-112553.patch +++ b/0003-Escape-terminal-special-characters-in-kubectl-112553.patch @@ -1,7 +1,7 @@ -From ffa3e2336c5f4078c84f8c719c48673c7e5f7290 Mon Sep 17 00:00:00 2001 +From 98128bcf1bd9c9ea86c1c8d48c0b1acda4ec7e73 Mon Sep 17 00:00:00 2001 From: David Leadbeater Date: Mon, 31 Oct 2022 01:08:43 +1000 -Subject: Escape terminal special characters in kubectl (#112553) +Subject: [PATCH] Escape terminal special characters in kubectl (#112553) * Escape terminal special characters in kubectl @@ -116,10 +116,10 @@ index 00000000..5a59491e + return terminalEscaper.Replace(in) +} diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/get/customcolumn.go b/staging/src/k8s.io/kubectl/pkg/cmd/get/customcolumn.go -index f9f48176..64d6d6f1 100644 +index 2b205667..38024cfa 100644 --- a/staging/src/k8s.io/kubectl/pkg/cmd/get/customcolumn.go +++ b/staging/src/k8s.io/kubectl/pkg/cmd/get/customcolumn.go -@@ -250,7 +250,7 @@ func (s *CustomColumnsPrinter) printOneObject(obj runtime.Object, parsers []*jso +@@ -252,7 +252,7 @@ func (s *CustomColumnsPrinter) printOneObject(obj runtime.Object, parsers []*jso } for arrIx := range values { for valIx := range values[arrIx] { @@ -156,7 +156,7 @@ index e4fb17a8..de403142 100644 }, } diff --git a/staging/src/k8s.io/kubectl/pkg/describe/describe.go b/staging/src/k8s.io/kubectl/pkg/describe/describe.go -index 2a8bf9cc..ef8070f1 100644 +index 484ed09f..d3b65132 100644 --- a/staging/src/k8s.io/kubectl/pkg/describe/describe.go +++ b/staging/src/k8s.io/kubectl/pkg/describe/describe.go @@ -65,6 +65,7 @@ import ( @@ -184,10 +184,10 @@ index 2a8bf9cc..ef8070f1 100644 func (pw *prefixWriter) Flush() { diff --git a/staging/src/k8s.io/kubectl/pkg/describe/describe_test.go b/staging/src/k8s.io/kubectl/pkg/describe/describe_test.go -index 7314feb2..5d8f1a0b 100644 +index 5225ec2d..a3e2feba 100644 --- a/staging/src/k8s.io/kubectl/pkg/describe/describe_test.go +++ b/staging/src/k8s.io/kubectl/pkg/describe/describe_test.go -@@ -5322,3 +5322,22 @@ func TestControllerRef(t *testing.T) { +@@ -5520,3 +5520,22 @@ func TestControllerRef(t *testing.T) { t.Errorf("unexpected out: %s", out) } } diff --git a/0003-timeout-wait-backend-to-frontend-complete.patch b/0003-timeout-wait-backend-to-frontend-complete.patch deleted file mode 100644 index 5bb8ae163ee8c9783058719844fce6f3a1e8f2dc..0000000000000000000000000000000000000000 --- a/0003-timeout-wait-backend-to-frontend-complete.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 61834dbb52cc71a7e511f5b9af11b9799391ef1a Mon Sep 17 00:00:00 2001 -From: zhangxiaoyu -Date: Tue, 1 Nov 2022 15:34:16 +0800 -Subject: timeout wait backend to frontend complete - -Signed-off-by: zhangxiaoyu ---- - pkg/kubelet/cri/streaming/remotecommand/proxy.go | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/pkg/kubelet/cri/streaming/remotecommand/proxy.go b/pkg/kubelet/cri/streaming/remotecommand/proxy.go -index f21629af..296c6122 100644 ---- a/pkg/kubelet/cri/streaming/remotecommand/proxy.go -+++ b/pkg/kubelet/cri/streaming/remotecommand/proxy.go -@@ -129,6 +129,12 @@ func ProxyToWebSocket(w http.ResponseWriter, r *http.Request, url *url.URL, opts - case <-frontendResizeToBackendComplete: - } - -+ select { -+ case <-backendToFrontendComplete: -+ case <-time.Tick(30 * time.Second): -+ klog.Errorf("Wait backend to frontend complete timeout") -+ } -+ - if errConnection != nil { - klog.Errorf("SpdyProxy: the connection disconnected: %v", errConnection) - if exitErr, ok := errConnection.(exec.ExitError); ok && exitErr.Exited() { --- -2.25.1 - diff --git a/0004-Add-an-option-for-aggregator.patch b/0004-Add-an-option-for-aggregator.patch deleted file mode 100644 index 01e1bbb35c63af8d08d4a35f933e10c017689f85..0000000000000000000000000000000000000000 --- a/0004-Add-an-option-for-aggregator.patch +++ /dev/null @@ -1,284 +0,0 @@ -From 978dcb825f2808bd298bfbc6e9c91b1fd7859ba3 Mon Sep 17 00:00:00 2001 -From: Di Jin -Date: Thu, 1 Sep 2022 15:25:26 -0700 -Subject: Add an option for aggregator - ---- - cmd/kube-apiserver/app/aggregator.go | 9 ++- - cmd/kube-apiserver/app/options/options.go | 9 ++- - .../app/options/options_test.go | 5 +- - .../pkg/util/proxy/upgradeaware.go | 27 +++++++ - .../pkg/util/proxy/upgradeaware_test.go | 77 +++++++++++++++++++ - .../pkg/apiserver/apiserver.go | 7 ++ - .../pkg/apiserver/handler_proxy.go | 6 ++ - 7 files changed, 132 insertions(+), 8 deletions(-) - -diff --git a/cmd/kube-apiserver/app/aggregator.go b/cmd/kube-apiserver/app/aggregator.go -index 2466dcc2..9cf23362 100644 ---- a/cmd/kube-apiserver/app/aggregator.go -+++ b/cmd/kube-apiserver/app/aggregator.go -@@ -111,10 +111,11 @@ func createAggregatorConfig( - SharedInformerFactory: externalInformers, - }, - ExtraConfig: aggregatorapiserver.ExtraConfig{ -- ProxyClientCertFile: commandOptions.ProxyClientCertFile, -- ProxyClientKeyFile: commandOptions.ProxyClientKeyFile, -- ServiceResolver: serviceResolver, -- ProxyTransport: proxyTransport, -+ ProxyClientCertFile: commandOptions.ProxyClientCertFile, -+ ProxyClientKeyFile: commandOptions.ProxyClientKeyFile, -+ ServiceResolver: serviceResolver, -+ ProxyTransport: proxyTransport, -+ RejectForwardingRedirects: commandOptions.AggregatorRejectForwardingRedirects, - }, - } - -diff --git a/cmd/kube-apiserver/app/options/options.go b/cmd/kube-apiserver/app/options/options.go -index 9672b187..794d0d9f 100644 ---- a/cmd/kube-apiserver/app/options/options.go -+++ b/cmd/kube-apiserver/app/options/options.go -@@ -75,7 +75,8 @@ type ServerRunOptions struct { - ProxyClientCertFile string - ProxyClientKeyFile string - -- EnableAggregatorRouting bool -+ EnableAggregatorRouting bool -+ AggregatorRejectForwardingRedirects bool - - MasterCount int - EndpointReconcilerType string -@@ -131,7 +132,8 @@ func NewServerRunOptions() *ServerRunOptions { - }, - HTTPTimeout: time.Duration(5) * time.Second, - }, -- ServiceNodePortRange: kubeoptions.DefaultServiceNodePortRange, -+ ServiceNodePortRange: kubeoptions.DefaultServiceNodePortRange, -+ AggregatorRejectForwardingRedirects: true, - } - - // Overwrite the default for storage data format. -@@ -243,6 +245,9 @@ func (s *ServerRunOptions) Flags() (fss cliflag.NamedFlagSets) { - fs.BoolVar(&s.EnableAggregatorRouting, "enable-aggregator-routing", s.EnableAggregatorRouting, - "Turns on aggregator routing requests to endpoints IP rather than cluster IP.") - -+ fs.BoolVar(&s.AggregatorRejectForwardingRedirects, "aggregator-reject-forwarding-redirect", s.AggregatorRejectForwardingRedirects, -+ "Aggregator reject forwarding redirect response back to client.") -+ - fs.StringVar(&s.ServiceAccountSigningKeyFile, "service-account-signing-key-file", s.ServiceAccountSigningKeyFile, ""+ - "Path to the file that contains the current private key of the service account token issuer. The issuer will sign issued ID tokens with this private key.") - -diff --git a/cmd/kube-apiserver/app/options/options_test.go b/cmd/kube-apiserver/app/options/options_test.go -index 26eb6a95..90e1f045 100644 ---- a/cmd/kube-apiserver/app/options/options_test.go -+++ b/cmd/kube-apiserver/app/options/options_test.go -@@ -315,8 +315,9 @@ func TestAddFlags(t *testing.T) { - Traces: &apiserveroptions.TracingOptions{ - ConfigFile: "/var/run/kubernetes/tracing_config.yaml", - }, -- IdentityLeaseDurationSeconds: 3600, -- IdentityLeaseRenewIntervalSeconds: 10, -+ IdentityLeaseDurationSeconds: 3600, -+ IdentityLeaseRenewIntervalSeconds: 10, -+ AggregatorRejectForwardingRedirects: true, - } - - if !reflect.DeepEqual(expected, s) { -diff --git a/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go b/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go -index f56c17ca..a3a14241 100644 ---- a/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go -+++ b/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go -@@ -83,6 +83,8 @@ type UpgradeAwareHandler struct { - MaxBytesPerSec int64 - // Responder is passed errors that occur while setting up proxying. - Responder ErrorResponder -+ // Reject to forward redirect response -+ RejectForwardingRedirects bool - } - - const defaultFlushInterval = 200 * time.Millisecond -@@ -257,6 +259,31 @@ func (h *UpgradeAwareHandler) ServeHTTP(w http.ResponseWriter, req *http.Request - proxy.Transport = h.Transport - proxy.FlushInterval = h.FlushInterval - proxy.ErrorLog = log.New(noSuppressPanicError{}, "", log.LstdFlags) -+ if h.RejectForwardingRedirects { -+ oldModifyResponse := proxy.ModifyResponse -+ proxy.ModifyResponse = func(response *http.Response) error { -+ code := response.StatusCode -+ if code >= 300 && code <= 399 { -+ // close the original response -+ response.Body.Close() -+ msg := "the backend attempted to redirect this request, which is not permitted" -+ // replace the response -+ *response = http.Response{ -+ StatusCode: http.StatusBadGateway, -+ Status: fmt.Sprintf("%d %s", response.StatusCode, http.StatusText(response.StatusCode)), -+ Body: io.NopCloser(strings.NewReader(msg)), -+ ContentLength: int64(len(msg)), -+ } -+ } else { -+ if oldModifyResponse != nil { -+ if err := oldModifyResponse(response); err != nil { -+ return err -+ } -+ } -+ } -+ return nil -+ } -+ } - if h.Responder != nil { - // if an optional error interceptor/responder was provided wire it - // the custom responder might be used for providing a unified error reporting -diff --git a/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go b/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go -index f57b69a0..0d77fb11 100644 ---- a/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go -+++ b/staging/src/k8s.io/apimachinery/pkg/util/proxy/upgradeaware_test.go -@@ -704,6 +704,83 @@ func TestProxyUpgradeErrorResponse(t *testing.T) { - } - } - -+func TestRejectForwardingRedirectsOption(t *testing.T) { -+ originalBody := []byte(`some data`) -+ testCases := []struct { -+ name string -+ rejectForwardingRedirects bool -+ serverStatusCode int -+ expectStatusCode int -+ expectBody []byte -+ }{ -+ { -+ name: "reject redirection enabled in proxy, backend server sending 200 response", -+ rejectForwardingRedirects: true, -+ serverStatusCode: 200, -+ expectStatusCode: 200, -+ expectBody: originalBody, -+ }, -+ { -+ name: "reject redirection enabled in proxy, backend server sending 301 response", -+ rejectForwardingRedirects: true, -+ serverStatusCode: 301, -+ expectStatusCode: 502, -+ expectBody: []byte(`the backend attempted to redirect this request, which is not permitted`), -+ }, -+ { -+ name: "reject redirection disabled in proxy, backend server sending 200 response", -+ rejectForwardingRedirects: false, -+ serverStatusCode: 200, -+ expectStatusCode: 200, -+ expectBody: originalBody, -+ }, -+ { -+ name: "reject redirection disabled in proxy, backend server sending 301 response", -+ rejectForwardingRedirects: false, -+ serverStatusCode: 301, -+ expectStatusCode: 301, -+ expectBody: originalBody, -+ }, -+ } -+ for _, tc := range testCases { -+ t.Run(tc.name, func(t *testing.T) { -+ // Set up a backend server -+ backendServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -+ w.WriteHeader(tc.serverStatusCode) -+ w.Write(originalBody) -+ })) -+ defer backendServer.Close() -+ backendServerURL, _ := url.Parse(backendServer.URL) -+ -+ // Set up a proxy pointing to the backend -+ proxyHandler := NewUpgradeAwareHandler(backendServerURL, nil, false, false, &fakeResponder{t: t}) -+ proxyHandler.RejectForwardingRedirects = tc.rejectForwardingRedirects -+ proxy := httptest.NewServer(proxyHandler) -+ defer proxy.Close() -+ proxyURL, _ := url.Parse(proxy.URL) -+ -+ conn, err := net.Dial("tcp", proxyURL.Host) -+ require.NoError(t, err) -+ bufferedReader := bufio.NewReader(conn) -+ -+ req, _ := http.NewRequest("GET", proxyURL.String(), nil) -+ require.NoError(t, req.Write(conn)) -+ // Verify we get the correct response and message body content -+ resp, err := http.ReadResponse(bufferedReader, nil) -+ require.NoError(t, err) -+ assert.Equal(t, tc.expectStatusCode, resp.StatusCode) -+ data, err := ioutil.ReadAll(resp.Body) -+ require.NoError(t, err) -+ assert.Equal(t, tc.expectBody, data) -+ assert.Equal(t, int64(len(tc.expectBody)), resp.ContentLength) -+ resp.Body.Close() -+ -+ // clean up -+ conn.Close() -+ }) -+ } -+} -+ - func TestDefaultProxyTransport(t *testing.T) { - tests := []struct { - name, -diff --git a/staging/src/k8s.io/kube-aggregator/pkg/apiserver/apiserver.go b/staging/src/k8s.io/kube-aggregator/pkg/apiserver/apiserver.go -index e945fb48..133887e1 100644 ---- a/staging/src/k8s.io/kube-aggregator/pkg/apiserver/apiserver.go -+++ b/staging/src/k8s.io/kube-aggregator/pkg/apiserver/apiserver.go -@@ -87,6 +87,8 @@ type ExtraConfig struct { - - // Mechanism by which the Aggregator will resolve services. Required. - ServiceResolver ServiceResolver -+ -+ RejectForwardingRedirects bool - } - - // Config represents the configuration needed to create an APIAggregator. -@@ -156,6 +158,9 @@ type APIAggregator struct { - // egressSelector selects the proper egress dialer to communicate with the custom apiserver - // overwrites proxyTransport dialer if not nil - egressSelector *egressselector.EgressSelector -+ -+ // rejectForwardingRedirects is whether to allow to forward redirect response -+ rejectForwardingRedirects bool - } - - // Complete fills in any fields not set that are required to have valid data. It's mutating the receiver. -@@ -213,6 +218,7 @@ func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.Deleg - openAPIV3Config: c.GenericConfig.OpenAPIV3Config, - egressSelector: c.GenericConfig.EgressSelector, - proxyCurrentCertKeyContent: func() (bytes []byte, bytes2 []byte) { return nil, nil }, -+ rejectForwardingRedirects: c.ExtraConfig.RejectForwardingRedirects, - } - - // used later to filter the served resource by those that have expired. -@@ -443,6 +449,7 @@ func (s *APIAggregator) AddAPIService(apiService *v1.APIService) error { - proxyTransport: s.proxyTransport, - serviceResolver: s.serviceResolver, - egressSelector: s.egressSelector, -+ rejectForwardingRedirects: s.rejectForwardingRedirects, - } - proxyHandler.updateAPIService(apiService) - if s.openAPIAggregationController != nil { -diff --git a/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy.go b/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy.go -index 3a880b6b..e1282f2a 100644 ---- a/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy.go -+++ b/staging/src/k8s.io/kube-aggregator/pkg/apiserver/handler_proxy.go -@@ -68,6 +68,9 @@ type proxyHandler struct { - // egressSelector selects the proper egress dialer to communicate with the custom apiserver - // overwrites proxyTransport dialer if not nil - egressSelector *egressselector.EgressSelector -+ -+ // reject to forward redirect response -+ rejectForwardingRedirects bool - } - - type proxyHandlingInfo struct { -@@ -172,6 +175,9 @@ func (r *proxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { - } - - handler := proxy.NewUpgradeAwareHandler(location, proxyRoundTripper, true, upgrade, &responder{w: w}) -+ if r.rejectForwardingRedirects { -+ handler.RejectForwardingRedirects = true -+ } - utilflowcontrol.RequestDelegated(req.Context()) - handler.ServeHTTP(w, newReq) - } --- -2.25.1 - diff --git a/0006-Return-error-for-localhost-seccomp-type-with-no-loca.patch b/0004-Return-error-for-localhost-seccomp-type-with-no-loca.patch similarity index 47% rename from 0006-Return-error-for-localhost-seccomp-type-with-no-loca.patch rename to 0004-Return-error-for-localhost-seccomp-type-with-no-loca.patch index 308d8965211b28252f928e5dffa6a09c474234f3..7799506636077ee32d2643f17099cdc5c8866994 100644 --- a/0006-Return-error-for-localhost-seccomp-type-with-no-loca.patch +++ b/0004-Return-error-for-localhost-seccomp-type-with-no-loca.patch @@ -1,22 +1,20 @@ -From 73174f870735251e7d4240cdc36983d1bef7db5f Mon Sep 17 00:00:00 2001 +From 604ad21799c43d87456cc76d3e591487de0a5152 Mon Sep 17 00:00:00 2001 From: Craig Ingram Date: Fri, 24 Feb 2023 15:24:49 -0500 Subject: [PATCH] Return error for localhost seccomp type with no localhost profile defined --- - pkg/kubelet/kuberuntime/helpers.go | 66 ++-- - pkg/kubelet/kuberuntime/helpers_test.go | 350 ++++-------------- - .../kuberuntime_container_linux.go | 16 +- - .../kuberuntime_container_linux_test.go | 22 +- - pkg/kubelet/kuberuntime/security_context.go | 15 +- - 5 files changed, 153 insertions(+), 316 deletions(-) + pkg/kubelet/kuberuntime/helpers.go | 60 +++++----- + pkg/kubelet/kuberuntime/helpers_test.go | 120 +++++++++++++------- + pkg/kubelet/kuberuntime/security_context.go | 11 +- + 3 files changed, 121 insertions(+), 70 deletions(-) diff --git a/pkg/kubelet/kuberuntime/helpers.go b/pkg/kubelet/kuberuntime/helpers.go -index de289836a8b..6138fc958d7 100644 +index 9343b78335a..14ed0dd3bfb 100644 --- a/pkg/kubelet/kuberuntime/helpers.go +++ b/pkg/kubelet/kuberuntime/helpers.go -@@ -210,28 +210,32 @@ func toKubeRuntimeStatus(status *runtimeapi.RuntimeStatus) *kubecontainer.Runtim +@@ -210,32 +210,36 @@ func toKubeRuntimeStatus(status *runtimeapi.RuntimeStatus) *kubecontainer.Runtim return &kubecontainer.RuntimeStatus{Conditions: conditions} } @@ -32,12 +30,11 @@ index de289836a8b..6138fc958d7 100644 } if scmp.Type == v1.SeccompProfileTypeRuntimeDefault { - return v1.SeccompProfileRuntimeDefault -- } ++ return v1.SeccompProfileRuntimeDefault, nil + } - if scmp.Type == v1.SeccompProfileTypeLocalhost && scmp.LocalhostProfile != nil && len(*scmp.LocalhostProfile) > 0 { - fname := filepath.Join(profileRootPath, *scmp.LocalhostProfile) - return v1.SeccompLocalhostProfileNamePrefix + fname -+ return v1.SeccompProfileRuntimeDefault, nil -+ } + if scmp.Type == v1.SeccompProfileTypeLocalhost { + if scmp.LocalhostProfile != nil && len(*scmp.LocalhostProfile) > 0 { + fname := filepath.Join(profileRootPath, *scmp.LocalhostProfile) @@ -59,31 +56,13 @@ index de289836a8b..6138fc958d7 100644 + return "", nil } - func annotationProfile(profile, profileRootPath string) string { -@@ -244,7 +248,7 @@ func annotationProfile(profile, profileRootPath string) string { - } - func (m *kubeGenericRuntimeManager) getSeccompProfilePath(annotations map[string]string, containerName string, - podSecContext *v1.PodSecurityContext, containerSecContext *v1.SecurityContext, fallbackToRuntimeDefault bool) string { + podSecContext *v1.PodSecurityContext, containerSecContext *v1.SecurityContext, fallbackToRuntimeDefault bool) (string, error) { // container fields are applied first if containerSecContext != nil && containerSecContext.SeccompProfile != nil { return fieldProfile(containerSecContext.SeccompProfile, m.seccompProfileRoot, fallbackToRuntimeDefault) -@@ -253,7 +257,7 @@ func (m *kubeGenericRuntimeManager) getSeccompProfilePath(annotations map[string - // if container field does not exist, try container annotation (deprecated) - if containerName != "" { - if profile, ok := annotations[v1.SeccompContainerAnnotationKeyPrefix+containerName]; ok { -- return annotationProfile(profile, m.seccompProfileRoot) -+ return annotationProfile(profile, m.seccompProfileRoot), nil - } - } - -@@ -264,46 +268,50 @@ func (m *kubeGenericRuntimeManager) getSeccompProfilePath(annotations map[string - - // as last resort, try to apply pod annotation (deprecated) - if profile, ok := annotations[v1.SeccompPodAnnotationKey]; ok { -- return annotationProfile(profile, m.seccompProfileRoot) -+ return annotationProfile(profile, m.seccompProfileRoot), nil +@@ -247,42 +251,46 @@ func (m *kubeGenericRuntimeManager) getSeccompProfilePath(annotations map[string } if fallbackToRuntimeDefault { @@ -143,7 +122,7 @@ index de289836a8b..6138fc958d7 100644 // container fields are applied first if containerSecContext != nil && containerSecContext.SeccompProfile != nil { return fieldSeccompProfile(containerSecContext.SeccompProfile, m.seccompProfileRoot, fallbackToRuntimeDefault) -@@ -317,12 +325,12 @@ func (m *kubeGenericRuntimeManager) getSeccompProfile(annotations map[string]str +@@ -296,10 +304,10 @@ func (m *kubeGenericRuntimeManager) getSeccompProfile(annotations map[string]str if fallbackToRuntimeDefault { return &runtimeapi.SecurityProfile{ ProfileType: runtimeapi.SecurityProfile_RuntimeDefault, @@ -156,10 +135,8 @@ index de289836a8b..6138fc958d7 100644 - } + }, nil } - - func ipcNamespaceForPod(pod *v1.Pod) runtimeapi.NamespaceMode { diff --git a/pkg/kubelet/kuberuntime/helpers_test.go b/pkg/kubelet/kuberuntime/helpers_test.go -index 25065f30411..70ad7250ce2 100644 +index 83a8da8793a..5fbe640b44a 100644 --- a/pkg/kubelet/kuberuntime/helpers_test.go +++ b/pkg/kubelet/kuberuntime/helpers_test.go @@ -242,17 +242,18 @@ func TestFieldProfile(t *testing.T) { @@ -262,99 +239,7 @@ index 25065f30411..70ad7250ce2 100644 }{ { description: "no seccomp should return empty", -@@ -369,91 +382,6 @@ func TestGetSeccompProfilePath(t *testing.T) { - containerName: "container1", - expectedProfile: "", - }, -- { -- description: "annotations: pod runtime/default seccomp profile should return runtime/default", -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: v1.SeccompProfileRuntimeDefault, -- }, -- expectedProfile: "runtime/default", -- }, -- { -- description: "annotations: pod docker/default seccomp profile should return docker/default", -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: v1.DeprecatedSeccompProfileDockerDefault, -- }, -- expectedProfile: "docker/default", -- }, -- { -- description: "annotations: pod runtime/default seccomp profile with containerName should return runtime/default", -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: v1.SeccompProfileRuntimeDefault, -- }, -- containerName: "container1", -- expectedProfile: "runtime/default", -- }, -- { -- description: "annotations: pod docker/default seccomp profile with containerName should return docker/default", -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: v1.DeprecatedSeccompProfileDockerDefault, -- }, -- containerName: "container1", -- expectedProfile: "docker/default", -- }, -- { -- description: "annotations: pod unconfined seccomp profile should return unconfined", -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: v1.SeccompProfileNameUnconfined, -- }, -- expectedProfile: "unconfined", -- }, -- { -- description: "annotations: pod unconfined seccomp profile with containerName should return unconfined", -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: v1.SeccompProfileNameUnconfined, -- }, -- containerName: "container1", -- expectedProfile: "unconfined", -- }, -- { -- description: "annotations: pod localhost seccomp profile should return local profile path", -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: "localhost/chmod.json", -- }, -- expectedProfile: seccompLocalhostPath("chmod.json"), -- }, -- { -- description: "annotations: pod localhost seccomp profile with containerName should return local profile path", -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: "localhost/chmod.json", -- }, -- containerName: "container1", -- expectedProfile: seccompLocalhostPath("chmod.json"), -- }, -- { -- description: "annotations: container localhost seccomp profile with containerName should return local profile path", -- annotation: map[string]string{ -- v1.SeccompContainerAnnotationKeyPrefix + "container1": "localhost/chmod.json", -- }, -- containerName: "container1", -- expectedProfile: seccompLocalhostPath("chmod.json"), -- }, -- { -- description: "annotations: container localhost seccomp profile should override pod profile", -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: v1.SeccompProfileNameUnconfined, -- v1.SeccompContainerAnnotationKeyPrefix + "container1": "localhost/chmod.json", -- }, -- containerName: "container1", -- expectedProfile: seccompLocalhostPath("chmod.json"), -- }, -- { -- description: "annotations: container localhost seccomp profile with unmatched containerName should return empty", -- annotation: map[string]string{ -- v1.SeccompContainerAnnotationKeyPrefix + "container1": "localhost/chmod.json", -- }, -- containerName: "container2", -- expectedProfile: "", -- }, - { - description: "pod seccomp profile set to unconfined returns unconfined", - podSc: &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeUnconfined}}, -@@ -480,14 +408,14 @@ func TestGetSeccompProfilePath(t *testing.T) { +@@ -395,14 +408,14 @@ func TestGetSeccompProfilePath(t *testing.T) { expectedProfile: seccompLocalhostPath("filename"), }, { @@ -375,40 +260,7 @@ index 25065f30411..70ad7250ce2 100644 }, { description: "container seccomp profile set to SeccompProfileTypeLocalhost returns 'localhost/' + LocalhostProfile", -@@ -500,41 +428,16 @@ func TestGetSeccompProfilePath(t *testing.T) { - containerSc: &v1.SecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeRuntimeDefault}}, - expectedProfile: "runtime/default", - }, -- { -- description: "prioritise container field over container annotation, pod field and pod annotation", -- podSc: &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeLocalhost, LocalhostProfile: getLocal("field-pod-profile.json")}}, -- containerSc: &v1.SecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeLocalhost, LocalhostProfile: getLocal("field-cont-profile.json")}}, -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: "localhost/annota-pod-profile.json", -- v1.SeccompContainerAnnotationKeyPrefix + "container1": "localhost/annota-cont-profile.json", -- }, -- containerName: "container1", -- expectedProfile: seccompLocalhostPath("field-cont-profile.json"), -- }, -- { -- description: "prioritise container annotation over pod field", -- podSc: &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeLocalhost, LocalhostProfile: getLocal("field-pod-profile.json")}}, -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: "localhost/annota-pod-profile.json", -- v1.SeccompContainerAnnotationKeyPrefix + "container1": "localhost/annota-cont-profile.json", -- }, -- containerName: "container1", -- expectedProfile: seccompLocalhostPath("annota-cont-profile.json"), -- }, -- { -- description: "prioritise pod field over pod annotation", -- podSc: &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeLocalhost, LocalhostProfile: getLocal("field-pod-profile.json")}}, -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: "localhost/annota-pod-profile.json", -- }, -- containerName: "container1", -- expectedProfile: seccompLocalhostPath("field-pod-profile.json"), -- }, +@@ -418,8 +431,13 @@ func TestGetSeccompProfilePath(t *testing.T) { } for i, test := range tests { @@ -424,7 +276,7 @@ index 25065f30411..70ad7250ce2 100644 } } -@@ -549,6 +452,7 @@ func TestGetSeccompProfilePathDefaultSeccomp(t *testing.T) { +@@ -434,6 +452,7 @@ func TestGetSeccompProfilePathDefaultSeccomp(t *testing.T) { containerSc *v1.SecurityContext containerName string expectedProfile string @@ -432,99 +284,7 @@ index 25065f30411..70ad7250ce2 100644 }{ { description: "no seccomp should return runtime/default", -@@ -559,91 +463,6 @@ func TestGetSeccompProfilePathDefaultSeccomp(t *testing.T) { - containerName: "container1", - expectedProfile: v1.SeccompProfileRuntimeDefault, - }, -- { -- description: "annotations: pod runtime/default seccomp profile should return runtime/default", -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: v1.SeccompProfileRuntimeDefault, -- }, -- expectedProfile: v1.SeccompProfileRuntimeDefault, -- }, -- { -- description: "annotations: pod docker/default seccomp profile should return docker/default", -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: v1.DeprecatedSeccompProfileDockerDefault, -- }, -- expectedProfile: "docker/default", -- }, -- { -- description: "annotations: pod runtime/default seccomp profile with containerName should return runtime/default", -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: v1.SeccompProfileRuntimeDefault, -- }, -- containerName: "container1", -- expectedProfile: v1.SeccompProfileRuntimeDefault, -- }, -- { -- description: "annotations: pod docker/default seccomp profile with containerName should return docker/default", -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: v1.DeprecatedSeccompProfileDockerDefault, -- }, -- containerName: "container1", -- expectedProfile: "docker/default", -- }, -- { -- description: "annotations: pod unconfined seccomp profile should return unconfined", -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: v1.SeccompProfileNameUnconfined, -- }, -- expectedProfile: "unconfined", -- }, -- { -- description: "annotations: pod unconfined seccomp profile with containerName should return unconfined", -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: v1.SeccompProfileNameUnconfined, -- }, -- containerName: "container1", -- expectedProfile: "unconfined", -- }, -- { -- description: "annotations: pod localhost seccomp profile should return local profile path", -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: "localhost/chmod.json", -- }, -- expectedProfile: seccompLocalhostPath("chmod.json"), -- }, -- { -- description: "annotations: pod localhost seccomp profile with containerName should return local profile path", -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: "localhost/chmod.json", -- }, -- containerName: "container1", -- expectedProfile: seccompLocalhostPath("chmod.json"), -- }, -- { -- description: "annotations: container localhost seccomp profile with containerName should return local profile path", -- annotation: map[string]string{ -- v1.SeccompContainerAnnotationKeyPrefix + "container1": "localhost/chmod.json", -- }, -- containerName: "container1", -- expectedProfile: seccompLocalhostPath("chmod.json"), -- }, -- { -- description: "annotations: container localhost seccomp profile should override pod profile", -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: v1.SeccompProfileNameUnconfined, -- v1.SeccompContainerAnnotationKeyPrefix + "container1": "localhost/chmod.json", -- }, -- containerName: "container1", -- expectedProfile: seccompLocalhostPath("chmod.json"), -- }, -- { -- description: "annotations: container localhost seccomp profile with unmatched containerName should return runtime/default", -- annotation: map[string]string{ -- v1.SeccompContainerAnnotationKeyPrefix + "container1": "localhost/chmod.json", -- }, -- containerName: "container2", -- expectedProfile: v1.SeccompProfileRuntimeDefault, -- }, - { - description: "pod seccomp profile set to unconfined returns unconfined", - podSc: &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeUnconfined}}, -@@ -670,14 +489,14 @@ func TestGetSeccompProfilePathDefaultSeccomp(t *testing.T) { +@@ -470,14 +489,14 @@ func TestGetSeccompProfilePathDefaultSeccomp(t *testing.T) { expectedProfile: seccompLocalhostPath("filename"), }, { @@ -545,40 +305,7 @@ index 25065f30411..70ad7250ce2 100644 }, { description: "container seccomp profile set to SeccompProfileTypeLocalhost returns 'localhost/' + LocalhostProfile", -@@ -690,41 +509,16 @@ func TestGetSeccompProfilePathDefaultSeccomp(t *testing.T) { - containerSc: &v1.SecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeRuntimeDefault}}, - expectedProfile: "runtime/default", - }, -- { -- description: "prioritise container field over container annotation, pod field and pod annotation", -- podSc: &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeLocalhost, LocalhostProfile: getLocal("field-pod-profile.json")}}, -- containerSc: &v1.SecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeLocalhost, LocalhostProfile: getLocal("field-cont-profile.json")}}, -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: "localhost/annota-pod-profile.json", -- v1.SeccompContainerAnnotationKeyPrefix + "container1": "localhost/annota-cont-profile.json", -- }, -- containerName: "container1", -- expectedProfile: seccompLocalhostPath("field-cont-profile.json"), -- }, -- { -- description: "prioritise container annotation over pod field", -- podSc: &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeLocalhost, LocalhostProfile: getLocal("field-pod-profile.json")}}, -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: "localhost/annota-pod-profile.json", -- v1.SeccompContainerAnnotationKeyPrefix + "container1": "localhost/annota-cont-profile.json", -- }, -- containerName: "container1", -- expectedProfile: seccompLocalhostPath("annota-cont-profile.json"), -- }, -- { -- description: "prioritise pod field over pod annotation", -- podSc: &v1.PodSecurityContext{SeccompProfile: &v1.SeccompProfile{Type: v1.SeccompProfileTypeLocalhost, LocalhostProfile: getLocal("field-pod-profile.json")}}, -- annotation: map[string]string{ -- v1.SeccompPodAnnotationKey: "localhost/annota-pod-profile.json", -- }, -- containerName: "container1", -- expectedProfile: seccompLocalhostPath("field-pod-profile.json"), -- }, +@@ -493,8 +512,13 @@ func TestGetSeccompProfilePathDefaultSeccomp(t *testing.T) { } for i, test := range tests { @@ -594,7 +321,7 @@ index 25065f30411..70ad7250ce2 100644 } } -@@ -747,6 +541,7 @@ func TestGetSeccompProfile(t *testing.T) { +@@ -517,6 +541,7 @@ func TestGetSeccompProfile(t *testing.T) { containerSc *v1.SecurityContext containerName string expectedProfile *runtimeapi.SecurityProfile @@ -602,7 +329,7 @@ index 25065f30411..70ad7250ce2 100644 }{ { description: "no seccomp should return unconfined", -@@ -781,14 +576,14 @@ func TestGetSeccompProfile(t *testing.T) { +@@ -551,14 +576,14 @@ func TestGetSeccompProfile(t *testing.T) { }, }, { @@ -623,7 +350,7 @@ index 25065f30411..70ad7250ce2 100644 }, { description: "container seccomp profile set to SeccompProfileTypeLocalhost returns 'localhost/' + LocalhostProfile", -@@ -817,8 +612,13 @@ func TestGetSeccompProfile(t *testing.T) { +@@ -587,8 +612,13 @@ func TestGetSeccompProfile(t *testing.T) { } for i, test := range tests { @@ -639,7 +366,7 @@ index 25065f30411..70ad7250ce2 100644 } } -@@ -841,6 +641,7 @@ func TestGetSeccompProfileDefaultSeccomp(t *testing.T) { +@@ -611,6 +641,7 @@ func TestGetSeccompProfileDefaultSeccomp(t *testing.T) { containerSc *v1.SecurityContext containerName string expectedProfile *runtimeapi.SecurityProfile @@ -647,7 +374,7 @@ index 25065f30411..70ad7250ce2 100644 }{ { description: "no seccomp should return RuntimeDefault", -@@ -875,14 +676,14 @@ func TestGetSeccompProfileDefaultSeccomp(t *testing.T) { +@@ -645,14 +676,14 @@ func TestGetSeccompProfileDefaultSeccomp(t *testing.T) { }, }, { @@ -668,7 +395,7 @@ index 25065f30411..70ad7250ce2 100644 }, { description: "container seccomp profile set to SeccompProfileTypeLocalhost returns 'localhost/' + LocalhostProfile", -@@ -911,8 +712,13 @@ func TestGetSeccompProfileDefaultSeccomp(t *testing.T) { +@@ -681,8 +712,13 @@ func TestGetSeccompProfileDefaultSeccomp(t *testing.T) { } for i, test := range tests { @@ -684,149 +411,11 @@ index 25065f30411..70ad7250ce2 100644 } } -diff --git a/pkg/kubelet/kuberuntime/kuberuntime_container_linux.go b/pkg/kubelet/kuberuntime/kuberuntime_container_linux.go -index 25917803b1c..1e9a2377b51 100644 ---- a/pkg/kubelet/kuberuntime/kuberuntime_container_linux.go -+++ b/pkg/kubelet/kuberuntime/kuberuntime_container_linux.go -@@ -45,15 +45,23 @@ func (m *kubeGenericRuntimeManager) applyPlatformSpecificContainerConfig(config - libcontainercgroups.IsCgroup2UnifiedMode() { - enforceMemoryQoS = true - } -- config.Linux = m.generateLinuxContainerConfig(container, pod, uid, username, nsTarget, enforceMemoryQoS) -+ cl, err := m.generateLinuxContainerConfig(container, pod, uid, username, nsTarget, enforceMemoryQoS) -+ if err != nil { -+ return err -+ } -+ config.Linux = cl - return nil - } - - // generateLinuxContainerConfig generates linux container config for kubelet runtime v1. --func (m *kubeGenericRuntimeManager) generateLinuxContainerConfig(container *v1.Container, pod *v1.Pod, uid *int64, username string, nsTarget *kubecontainer.ContainerID, enforceMemoryQoS bool) *runtimeapi.LinuxContainerConfig { -+func (m *kubeGenericRuntimeManager) generateLinuxContainerConfig(container *v1.Container, pod *v1.Pod, uid *int64, username string, nsTarget *kubecontainer.ContainerID, enforceMemoryQoS bool) (*runtimeapi.LinuxContainerConfig, error) { -+ sc, err := m.determineEffectiveSecurityContext(pod, container, uid, username) -+ if err != nil { -+ return nil, err -+ } - lc := &runtimeapi.LinuxContainerConfig{ - Resources: &runtimeapi.LinuxContainerResources{}, -- SecurityContext: m.determineEffectiveSecurityContext(pod, container, uid, username), -+ SecurityContext: sc, - } - - if nsTarget != nil && lc.SecurityContext.NamespaceOptions.Pid == runtimeapi.NamespaceMode_CONTAINER { -@@ -124,7 +132,7 @@ func (m *kubeGenericRuntimeManager) generateLinuxContainerConfig(container *v1.C - } - } - -- return lc -+ return lc, nil - } - - // calculateLinuxResources will create the linuxContainerResources type based on the provided CPU and memory resource requests, limits -diff --git a/pkg/kubelet/kuberuntime/kuberuntime_container_linux_test.go b/pkg/kubelet/kuberuntime/kuberuntime_container_linux_test.go -index 29d0bbfc9b4..838ecf8c6f5 100644 ---- a/pkg/kubelet/kuberuntime/kuberuntime_container_linux_test.go -+++ b/pkg/kubelet/kuberuntime/kuberuntime_container_linux_test.go -@@ -47,6 +47,8 @@ func makeExpectedConfig(m *kubeGenericRuntimeManager, pod *v1.Pod, containerInde - restartCountUint32 := uint32(restartCount) - envs := make([]*runtimeapi.KeyValue, len(opts.Envs)) - -+ l, _ := m.generateLinuxContainerConfig(container, pod, new(int64), "", nil, enforceMemoryQoS) -+ - expectedConfig := &runtimeapi.ContainerConfig{ - Metadata: &runtimeapi.ContainerMetadata{ - Name: container.Name, -@@ -64,7 +66,7 @@ func makeExpectedConfig(m *kubeGenericRuntimeManager, pod *v1.Pod, containerInde - Stdin: container.Stdin, - StdinOnce: container.StdinOnce, - Tty: container.TTY, -- Linux: m.generateLinuxContainerConfig(container, pod, new(int64), "", nil, enforceMemoryQoS), -+ Linux: l, - Envs: envs, - } - return expectedConfig -@@ -215,7 +217,8 @@ func TestGenerateLinuxContainerConfigResources(t *testing.T) { - }, - } - -- linuxConfig := m.generateLinuxContainerConfig(&pod.Spec.Containers[0], pod, new(int64), "", nil, false) -+ linuxConfig, err := m.generateLinuxContainerConfig(&pod.Spec.Containers[0], pod, new(int64), "", nil, false) -+ assert.NoError(t, err) - assert.Equal(t, test.expected.CpuPeriod, linuxConfig.GetResources().CpuPeriod, test.name) - assert.Equal(t, test.expected.CpuQuota, linuxConfig.GetResources().CpuQuota, test.name) - assert.Equal(t, test.expected.CpuShares, linuxConfig.GetResources().CpuShares, test.name) -@@ -329,6 +332,8 @@ func TestGenerateContainerConfigWithMemoryQoSEnforced(t *testing.T) { - memoryLow int64 - memoryHigh int64 - } -+ l1, _ := m.generateLinuxContainerConfig(&pod1.Spec.Containers[0], pod1, new(int64), "", nil, true) -+ l2, _ := m.generateLinuxContainerConfig(&pod2.Spec.Containers[0], pod2, new(int64), "", nil, true) - tests := []struct { - name string - pod *v1.Pod -@@ -338,7 +343,7 @@ func TestGenerateContainerConfigWithMemoryQoSEnforced(t *testing.T) { - name: "Request128MBLimit256MB", - pod: pod1, - expected: &expectedResult{ -- m.generateLinuxContainerConfig(&pod1.Spec.Containers[0], pod1, new(int64), "", nil, true), -+ l1, - 128 * 1024 * 1024, - int64(float64(256*1024*1024) * m.memoryThrottlingFactor), - }, -@@ -347,7 +352,7 @@ func TestGenerateContainerConfigWithMemoryQoSEnforced(t *testing.T) { - name: "Request128MBWithoutLimit", - pod: pod2, - expected: &expectedResult{ -- m.generateLinuxContainerConfig(&pod2.Spec.Containers[0], pod2, new(int64), "", nil, true), -+ l2, - 128 * 1024 * 1024, - int64(pod2MemoryHigh), - }, -@@ -355,7 +360,8 @@ func TestGenerateContainerConfigWithMemoryQoSEnforced(t *testing.T) { - } - - for _, test := range tests { -- linuxConfig := m.generateLinuxContainerConfig(&test.pod.Spec.Containers[0], test.pod, new(int64), "", nil, true) -+ linuxConfig, err := m.generateLinuxContainerConfig(&test.pod.Spec.Containers[0], test.pod, new(int64), "", nil, true) -+ assert.NoError(t, err) - assert.Equal(t, test.expected.containerConfig, linuxConfig, test.name) - assert.Equal(t, linuxConfig.GetResources().GetUnified()["memory.min"], strconv.FormatInt(test.expected.memoryLow, 10), test.name) - assert.Equal(t, linuxConfig.GetResources().GetUnified()["memory.high"], strconv.FormatInt(test.expected.memoryHigh, 10), test.name) -@@ -578,7 +584,8 @@ func TestGenerateLinuxContainerConfigNamespaces(t *testing.T) { - }, - } { - t.Run(tc.name, func(t *testing.T) { -- got := m.generateLinuxContainerConfig(&tc.pod.Spec.Containers[0], tc.pod, nil, "", tc.target, false) -+ got, err := m.generateLinuxContainerConfig(&tc.pod.Spec.Containers[0], tc.pod, nil, "", tc.target, false) -+ assert.NoError(t, err) - if diff := cmp.Diff(tc.want, got.SecurityContext.NamespaceOptions); diff != "" { - t.Errorf("%v: diff (-want +got):\n%v", t.Name(), diff) - } -@@ -669,7 +676,8 @@ func TestGenerateLinuxContainerConfigSwap(t *testing.T) { - } { - t.Run(tc.name, func(t *testing.T) { - m.memorySwapBehavior = tc.swapSetting -- actual := m.generateLinuxContainerConfig(&tc.pod.Spec.Containers[0], tc.pod, nil, "", nil, false) -+ actual, err := m.generateLinuxContainerConfig(&tc.pod.Spec.Containers[0], tc.pod, nil, "", nil, false) -+ assert.NoError(t, err) - assert.Equal(t, tc.expected, actual.Resources.MemorySwapLimitInBytes, "memory swap config for %s", tc.name) - }) - } diff --git a/pkg/kubelet/kuberuntime/security_context.go b/pkg/kubelet/kuberuntime/security_context.go -index c9d33e44305..3b575c8e974 100644 +index 5e6f05b4e18..d933a710424 100644 --- a/pkg/kubelet/kuberuntime/security_context.go +++ b/pkg/kubelet/kuberuntime/security_context.go -@@ -24,7 +24,7 @@ import ( - ) - - // determineEffectiveSecurityContext gets container's security context from v1.Pod and v1.Container. --func (m *kubeGenericRuntimeManager) determineEffectiveSecurityContext(pod *v1.Pod, container *v1.Container, uid *int64, username string) *runtimeapi.LinuxContainerSecurityContext { -+func (m *kubeGenericRuntimeManager) determineEffectiveSecurityContext(pod *v1.Pod, container *v1.Container, uid *int64, username string) (*runtimeapi.LinuxContainerSecurityContext, error) { - effectiveSc := securitycontext.DetermineEffectiveSecurityContext(pod, container) - synthesized := convertToRuntimeSecurityContext(effectiveSc) - if synthesized == nil { -@@ -36,9 +36,16 @@ func (m *kubeGenericRuntimeManager) determineEffectiveSecurityContext(pod *v1.Po +@@ -37,9 +37,16 @@ func (m *kubeGenericRuntimeManager) determineEffectiveSecurityContext(pod *v1.Po // TODO: Deprecated, remove after we switch to Seccomp field // set SeccompProfilePath. @@ -845,15 +434,6 @@ index c9d33e44305..3b575c8e974 100644 // set ApparmorProfile. synthesized.ApparmorProfile = apparmor.GetProfileNameFromPodAnnotations(pod.Annotations, container.Name) -@@ -74,7 +81,7 @@ func (m *kubeGenericRuntimeManager) determineEffectiveSecurityContext(pod *v1.Po - synthesized.MaskedPaths = securitycontext.ConvertToRuntimeMaskedPaths(effectiveSc.ProcMount) - synthesized.ReadonlyPaths = securitycontext.ConvertToRuntimeReadonlyPaths(effectiveSc.ProcMount) - -- return synthesized -+ return synthesized, nil - } - - // convertToRuntimeSecurityContext converts v1.SecurityContext to runtimeapi.SecurityContext. -- 2.25.1 diff --git a/0007-Validate-etcd-paths.patch b/0005-Validate-etcd-paths.patch similarity index 55% rename from 0007-Validate-etcd-paths.patch rename to 0005-Validate-etcd-paths.patch index 24780bbcf42c0129eaa233f5096d48d9d1e789d3..c600d726ca1c6095080c389cac6bdec76edc46f0 100644 --- a/0007-Validate-etcd-paths.patch +++ b/0005-Validate-etcd-paths.patch @@ -1,21 +1,46 @@ -From 39a167e9012076eee63458d30e7c9f8da8eb8095 Mon Sep 17 00:00:00 2001 +From 6775c99cd008c457ce3eed401ac1c60c3812dbfa Mon Sep 17 00:00:00 2001 From: Tim Allclair Date: Mon, 10 Oct 2022 18:15:22 -0700 Subject: [PATCH] Validate etcd paths --- - .../apiserver/pkg/storage/etcd3/store.go | 139 +++++++--- - .../apiserver/pkg/storage/etcd3/store_test.go | 253 ++++++++++++------ - 2 files changed, 261 insertions(+), 131 deletions(-) + .../pkg/storage/etcd3/linearized_read_test.go | 5 +- + .../apiserver/pkg/storage/etcd3/store.go | 138 +++++++++++------ + .../apiserver/pkg/storage/etcd3/store_test.go | 140 ++++++++++++++---- + .../pkg/storage/testing/store_tests.go | 24 +-- + 4 files changed, 218 insertions(+), 89 deletions(-) +diff --git a/staging/src/k8s.io/apiserver/pkg/storage/etcd3/linearized_read_test.go b/staging/src/k8s.io/apiserver/pkg/storage/etcd3/linearized_read_test.go +index bb1b9df7818..7331c8245ad 100644 +--- a/staging/src/k8s.io/apiserver/pkg/storage/etcd3/linearized_read_test.go ++++ b/staging/src/k8s.io/apiserver/pkg/storage/etcd3/linearized_read_test.go +@@ -37,7 +37,8 @@ func TestLinearizedReadRevisionInvariant(t *testing.T) { + // [1] https://etcd.io/docs/v3.5/learning/api_guarantees/#isolation-level-and-consistency-of-replicas + ctx, store, etcdClient := testSetup(t) + +- key := "/testkey" ++ dir := "/testing" ++ key := dir + "/testkey" + out := &example.Pod{} + obj := &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo", SelfLink: "testlink"}} + +@@ -53,7 +54,7 @@ func TestLinearizedReadRevisionInvariant(t *testing.T) { + } + + list := &example.PodList{} +- if err := store.GetList(ctx, "/", storage.ListOptions{Predicate: storage.Everything, Recursive: true}, list); err != nil { ++ if err := store.GetList(ctx, dir, storage.ListOptions{Predicate: storage.Everything, Recursive: true}, list); err != nil { + t.Errorf("Unexpected List error: %v", err) + } + finalRevision := list.ResourceVersion diff --git a/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go b/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go -index 75a6c3b5..2069777c 100644 +index 163eb111bcb..b2e4c674687 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go -@@ -99,16 +99,21 @@ func New(c *clientv3.Client, codec runtime.Codec, newFunc func() runtime.Object, +@@ -98,16 +98,21 @@ func New(c *clientv3.Client, codec runtime.Codec, newFunc func() runtime.Object, func newStore(c *clientv3.Client, codec runtime.Codec, newFunc func() runtime.Object, prefix string, groupResource schema.GroupResource, transformer value.Transformer, pagingEnabled bool, leaseManagerConfig LeaseManagerConfig) *store { - versioner := APIObjectVersioner{} + versioner := storage.APIObjectVersioner{} + // for compatibility with etcd2 impl. + // no-op for default prefix of '/registry'. + // keeps compatibility with etcd2 impl for custom prefixes that don't start with '/' @@ -43,7 +68,7 @@ index 75a6c3b5..2069777c 100644 groupResource: groupResource, groupResourceString: groupResource.String(), watcher: newWatcher(c, codec, newFunc, versioner, transformer), -@@ -124,9 +129,12 @@ func (s *store) Versioner() storage.Versioner { +@@ -123,9 +128,12 @@ func (s *store) Versioner() storage.Versioner { // Get implements storage.Interface.Get. func (s *store) Get(ctx context.Context, key string, opts storage.GetOptions, out runtime.Object) error { @@ -58,7 +83,7 @@ index 75a6c3b5..2069777c 100644 metrics.RecordEtcdRequestLatency("get", getTypeName(out), startTime) if err != nil { return err -@@ -139,11 +147,11 @@ func (s *store) Get(ctx context.Context, key string, opts storage.GetOptions, ou +@@ -138,11 +146,11 @@ func (s *store) Get(ctx context.Context, key string, opts storage.GetOptions, ou if opts.IgnoreNotFound { return runtime.SetZeroValue(out) } @@ -72,7 +97,7 @@ index 75a6c3b5..2069777c 100644 if err != nil { return storage.NewInternalError(err.Error()) } -@@ -153,6 +161,11 @@ func (s *store) Get(ctx context.Context, key string, opts storage.GetOptions, ou +@@ -152,6 +160,10 @@ func (s *store) Get(ctx context.Context, key string, opts storage.GetOptions, ou // Create implements storage.Interface.Create. func (s *store) Create(ctx context.Context, key string, obj, out runtime.Object, ttl uint64) error { @@ -80,11 +105,10 @@ index 75a6c3b5..2069777c 100644 + if err != nil { + return err + } -+ - if version, err := s.versioner.ObjectResourceVersion(obj); err == nil && version != 0 { - return errors.New("resourceVersion should not be set on objects to be created") - } -@@ -163,30 +176,29 @@ func (s *store) Create(ctx context.Context, key string, obj, out runtime.Object, + trace := utiltrace.New("Create etcd3", + utiltrace.Field{"audit-id", endpointsrequest.GetAuditIDTruncated(ctx)}, + utiltrace.Field{"key", key}, +@@ -170,14 +182,13 @@ func (s *store) Create(ctx context.Context, key string, obj, out runtime.Object, if err != nil { return err } @@ -97,9 +121,10 @@ index 75a6c3b5..2069777c 100644 - newData, err := s.transformer.TransformToStorage(ctx, data, authenticatedDataString(key)) + newData, err := s.transformer.TransformToStorage(ctx, data, authenticatedDataString(preparedKey)) + trace.Step("TransformToStorage finished", utiltrace.Field{"err", err}) if err != nil { return storage.NewInternalError(err.Error()) - } +@@ -185,9 +196,9 @@ func (s *store) Create(ctx context.Context, key string, obj, out runtime.Object, startTime := time.Now() txnResp, err := s.client.KV.Txn(ctx).If( @@ -110,16 +135,17 @@ index 75a6c3b5..2069777c 100644 + clientv3.OpPut(preparedKey, string(newData), opts...), ).Commit() metrics.RecordEtcdRequestLatency("create", getTypeName(obj), startTime) - if err != nil { - return err + trace.Step("Txn call finished", utiltrace.Field{"err", err}) +@@ -196,7 +207,7 @@ func (s *store) Create(ctx context.Context, key string, obj, out runtime.Object, } + if !txnResp.Succeeded { - return storage.NewKeyExistsError(key, 0) + return storage.NewKeyExistsError(preparedKey, 0) } if out != nil { -@@ -200,12 +212,15 @@ func (s *store) Create(ctx context.Context, key string, obj, out runtime.Object, +@@ -212,12 +223,15 @@ func (s *store) Create(ctx context.Context, key string, obj, out runtime.Object, func (s *store) Delete( ctx context.Context, key string, out runtime.Object, preconditions *storage.Preconditions, validateDeletion storage.ValidateObjectFunc, cachedExistingObject runtime.Object) error { @@ -137,18 +163,18 @@ index 75a6c3b5..2069777c 100644 } func (s *store) conditionalDelete( -@@ -318,6 +333,10 @@ func (s *store) conditionalDelete( +@@ -330,6 +344,10 @@ func (s *store) conditionalDelete( func (s *store) GuaranteedUpdate( - ctx context.Context, key string, out runtime.Object, ignoreNotFound bool, + ctx context.Context, key string, destination runtime.Object, ignoreNotFound bool, preconditions *storage.Preconditions, tryUpdate storage.UpdateFunc, cachedExistingObject runtime.Object) error { + preparedKey, err := s.prepareKey(key) + if err != nil { + return err + } - trace := utiltrace.New("GuaranteedUpdate etcd3", utiltrace.Field{"type", getTypeName(out)}) - defer trace.LogIfLong(500 * time.Millisecond) - -@@ -325,16 +344,15 @@ func (s *store) GuaranteedUpdate( + trace := utiltrace.New("GuaranteedUpdate etcd3", + utiltrace.Field{"audit-id", endpointsrequest.GetAuditIDTruncated(ctx)}, + utiltrace.Field{"key", key}, +@@ -340,16 +358,15 @@ func (s *store) GuaranteedUpdate( if err != nil { return fmt.Errorf("unable to convert output object to pointer: %v", err) } @@ -158,7 +184,7 @@ index 75a6c3b5..2069777c 100644 startTime := time.Now() - getResp, err := s.client.KV.Get(ctx, key) + getResp, err := s.client.KV.Get(ctx, preparedKey) - metrics.RecordEtcdRequestLatency("get", getTypeName(out), startTime) + metrics.RecordEtcdRequestLatency("get", getTypeName(destination), startTime) if err != nil { return nil, err } @@ -167,7 +193,7 @@ index 75a6c3b5..2069777c 100644 } var origState *objState -@@ -350,9 +368,9 @@ func (s *store) GuaranteedUpdate( +@@ -365,9 +382,9 @@ func (s *store) GuaranteedUpdate( } trace.Step("initial value restored") @@ -179,7 +205,7 @@ index 75a6c3b5..2069777c 100644 // If our data is already up to date, return the error if origStateIsCurrent { return err -@@ -435,11 +453,11 @@ func (s *store) GuaranteedUpdate( +@@ -453,11 +470,11 @@ func (s *store) GuaranteedUpdate( startTime := time.Now() txnResp, err := s.client.KV.Txn(ctx).If( @@ -192,9 +218,9 @@ index 75a6c3b5..2069777c 100644 - clientv3.OpGet(key), + clientv3.OpGet(preparedKey), ).Commit() - metrics.RecordEtcdRequestLatency("update", getTypeName(out), startTime) - if err != nil { -@@ -448,8 +466,8 @@ func (s *store) GuaranteedUpdate( + metrics.RecordEtcdRequestLatency("update", getTypeName(destination), startTime) + trace.Step("Txn call finished", utiltrace.Field{"err", err}) +@@ -467,8 +484,8 @@ func (s *store) GuaranteedUpdate( trace.Step("Transaction committed") if !txnResp.Succeeded { getResp := (*clientv3.GetResponse)(txnResp.Responses[0].GetResponseRange()) @@ -205,7 +231,7 @@ index 75a6c3b5..2069777c 100644 if err != nil { return err } -@@ -481,18 +499,21 @@ func getNewItemFunc(listObj runtime.Object, v reflect.Value) func() runtime.Obje +@@ -502,18 +519,21 @@ func getNewItemFunc(listObj runtime.Object, v reflect.Value) func() runtime.Obje } func (s *store) Count(key string) (int64, error) { @@ -232,7 +258,7 @@ index 75a6c3b5..2069777c 100644 if err != nil { return 0, err } -@@ -561,6 +582,10 @@ func encodeContinue(key, keyPrefix string, resourceVersion int64) (string, error +@@ -522,6 +542,10 @@ func (s *store) Count(key string) (int64, error) { // GetList implements storage.Interface. func (s *store) GetList(ctx context.Context, key string, opts storage.ListOptions, listObj runtime.Object) error { @@ -243,7 +269,7 @@ index 75a6c3b5..2069777c 100644 recursive := opts.Recursive resourceVersion := opts.ResourceVersion match := opts.ResourceVersionMatch -@@ -580,16 +605,15 @@ func (s *store) GetList(ctx context.Context, key string, opts storage.ListOption +@@ -542,16 +566,15 @@ func (s *store) GetList(ctx context.Context, key string, opts storage.ListOption if err != nil || v.Kind() != reflect.Slice { return fmt.Errorf("need ptr to slice: %v", err) } @@ -263,7 +289,7 @@ index 75a6c3b5..2069777c 100644 // set the appropriate clientv3 options to filter the returned data set var limitOption *clientv3.OpOption -@@ -626,7 +650,7 @@ func (s *store) GetList(ctx context.Context, key string, opts storage.ListOption +@@ -590,7 +613,7 @@ func (s *store) GetList(ctx context.Context, key string, opts storage.ListOption rangeEnd := clientv3.GetPrefixRangeEnd(keyPrefix) options = append(options, clientv3.WithRange(rangeEnd)) @@ -272,7 +298,7 @@ index 75a6c3b5..2069777c 100644 // If continueRV > 0, the LIST request needs a specific resource version. // continueRV==0 is invalid. -@@ -693,7 +717,7 @@ func (s *store) GetList(ctx context.Context, key string, opts storage.ListOption +@@ -657,7 +680,7 @@ func (s *store) GetList(ctx context.Context, key string, opts storage.ListOption }() for { startTime := time.Now() @@ -281,7 +307,7 @@ index 75a6c3b5..2069777c 100644 if recursive { metrics.RecordEtcdRequestLatency("list", getTypeName(listPtr), startTime) } else { -@@ -765,7 +789,7 @@ func (s *store) GetList(ctx context.Context, key string, opts storage.ListOption +@@ -729,7 +752,7 @@ func (s *store) GetList(ctx context.Context, key string, opts storage.ListOption } *limitOption = clientv3.WithLimit(limit) } @@ -290,7 +316,7 @@ index 75a6c3b5..2069777c 100644 if withRev == 0 { withRev = returnedRV options = append(options, clientv3.WithRev(withRev)) -@@ -830,12 +854,15 @@ func growSlice(v reflect.Value, maxCapacity int, sizes ...int) { +@@ -794,12 +817,15 @@ func growSlice(v reflect.Value, maxCapacity int, sizes ...int) { // Watch implements storage.Interface.Watch. func (s *store) Watch(ctx context.Context, key string, opts storage.ListOptions) (watch.Interface, error) { @@ -308,7 +334,7 @@ index 75a6c3b5..2069777c 100644 } func (s *store) getState(ctx context.Context, getResp *clientv3.GetResponse, key string, v reflect.Value, ignoreNotFound bool) (*objState, error) { -@@ -947,6 +974,30 @@ func (s *store) validateMinimumResourceVersion(minimumResourceVersion string, ac +@@ -911,6 +937,30 @@ func (s *store) validateMinimumResourceVersion(minimumResourceVersion string, ac return nil } @@ -340,10 +366,10 @@ index 75a6c3b5..2069777c 100644 // On success, objPtr would be set to the object. func decode(codec runtime.Codec, versioner storage.Versioner, value []byte, objPtr runtime.Object, rev int64) error { diff --git a/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go b/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go -index fedbcce3..65a73c21 100644 +index 84ee65a1fac..2f0dfe6e588 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go -@@ -64,6 +64,7 @@ var scheme = runtime.NewScheme() +@@ -54,6 +54,7 @@ var scheme = runtime.NewScheme() var codecs = serializer.NewCodecFactory(scheme) const defaultTestPrefix = "test!" @@ -351,49 +377,7 @@ index fedbcce3..65a73c21 100644 func init() { metav1.AddToGroupVersion(scheme, metav1.SchemeGroupVersion) -@@ -260,12 +261,12 @@ func TestGet(t *testing.T) { - rv: strconv.FormatInt(math.MaxInt64, 10), - }, { // test get on non-existing item with ignoreNotFound=false - name: "get non-existing", -- key: "/non-existing", -+ key: basePath + "/non-existing", - ignoreNotFound: false, - expectNotFoundErr: true, - }, { // test get on non-existing item with ignoreNotFound=true - name: "get non-existing, ignore not found", -- key: "/non-existing", -+ key: basePath + "/non-existing", - ignoreNotFound: true, - expectNotFoundErr: false, - expectedOut: &example.Pod{}, -@@ -671,7 +672,7 @@ func TestGetListNonRecursive(t *testing.T) { - - func TestGuaranteedUpdate(t *testing.T) { - ctx, store, etcdClient := testSetup(t) -- key := "/testkey" -+ key := basePath + "/testkey" - - tests := []struct { - name string -@@ -685,7 +686,7 @@ func TestGuaranteedUpdate(t *testing.T) { - hasSelfLink bool - }{{ - name: "non-existing key, ignoreNotFound=false", -- key: "/non-existing", -+ key: basePath + "/non-existing", - ignoreNotFound: false, - precondition: nil, - expectNotFoundErr: true, -@@ -693,7 +694,7 @@ func TestGuaranteedUpdate(t *testing.T) { - expectNoUpdate: false, - }, { - name: "non-existing key, ignoreNotFound=true", -- key: "/non-existing", -+ key: basePath + "/non-existing", - ignoreNotFound: true, - precondition: nil, - expectNotFoundErr: false, -@@ -1044,13 +1045,13 @@ func TestTransformationFailure(t *testing.T) { +@@ -446,13 +447,13 @@ func TestTransformationFailure(t *testing.T) { obj *example.Pod storedObj *example.Pod }{{ @@ -409,7 +393,7 @@ index fedbcce3..65a73c21 100644 obj: &example.Pod{ ObjectMeta: metav1.ObjectMeta{Name: "baz"}, Spec: storagetesting.DeepEqualSafePodSpec(), -@@ -1082,7 +1083,7 @@ func TestTransformationFailure(t *testing.T) { +@@ -484,7 +485,7 @@ func TestTransformationFailure(t *testing.T) { Predicate: storage.Everything, Recursive: true, } @@ -418,358 +402,8 @@ index fedbcce3..65a73c21 100644 t.Errorf("Unexpected error %v", err) } -@@ -1144,30 +1145,30 @@ func TestList(t *testing.T) { - storedObj *example.Pod - }{ - { -- key: "/one-level/test", -+ key: basePath + "/one-level/test", - obj: &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}, - }, - { -- key: "/two-level/1/test", -+ key: basePath + "/two-level/1/test", - obj: &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}, - }, - { -- key: "/two-level/2/test", -+ key: basePath + "/two-level/2/test", - obj: &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "bar"}}, - }, - { -- key: "/z-level/3/test", -+ key: basePath + "/z-level/3/test", - obj: &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "fourth"}}, - }, - { -- key: "/z-level/3/test-2", -+ key: basePath + "/z-level/3/test-2", - obj: &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "bar"}}, - }, - } - - // we want to figure out the resourceVersion before we create anything - initialList := &example.PodList{} -- if err := store.GetList(ctx, "/", storage.ListOptions{Predicate: storage.Everything, Recursive: true}, initialList); err != nil { -+ if err := store.GetList(ctx, basePath, storage.ListOptions{Predicate: storage.Everything, Recursive: true}, initialList); err != nil { - t.Errorf("Unexpected List error: %v", err) - } - initialRV := initialList.ResourceVersion -@@ -1186,7 +1187,7 @@ func TestList(t *testing.T) { - Predicate: storage.Everything, - Recursive: true, - } -- if err := store.GetList(ctx, "/two-level", storageOpts, list); err != nil { -+ if err := store.GetList(ctx, basePath+"/two-level", storageOpts, list); err != nil { - t.Errorf("Unexpected error: %v", err) - } - continueRV, _ := strconv.Atoi(list.ResourceVersion) -@@ -1216,14 +1217,14 @@ func TestList(t *testing.T) { - }{ - { - name: "rejects invalid resource version", -- prefix: "/", -+ prefix: basePath, - pred: storage.Everything, - rv: "abc", - expectError: true, - }, - { - name: "rejects resource version and continue token", -- prefix: "/", -+ prefix: basePath, - pred: storage.SelectionPredicate{ - Label: labels.Everything(), - Field: fields.Everything(), -@@ -1235,26 +1236,26 @@ func TestList(t *testing.T) { - }, - { - name: "rejects resource version set too high", -- prefix: "/", -+ prefix: basePath, - rv: strconv.FormatInt(math.MaxInt64, 10), - expectRVTooLarge: true, - }, - { - name: "test List on existing key", -- prefix: "/one-level/", -+ prefix: basePath + "/one-level/", - pred: storage.Everything, - expectedOut: []*example.Pod{preset[0].storedObj}, - }, - { - name: "test List on existing key with resource version set to 0", -- prefix: "/one-level/", -+ prefix: basePath + "/one-level/", - pred: storage.Everything, - expectedOut: []*example.Pod{preset[0].storedObj}, - rv: "0", - }, - { - name: "test List on existing key with resource version set before first write, match=Exact", -- prefix: "/one-level/", -+ prefix: basePath + "/one-level/", - pred: storage.Everything, - expectedOut: []*example.Pod{}, - rv: initialRV, -@@ -1263,7 +1264,7 @@ func TestList(t *testing.T) { - }, - { - name: "test List on existing key with resource version set to 0, match=NotOlderThan", -- prefix: "/one-level/", -+ prefix: basePath + "/one-level/", - pred: storage.Everything, - expectedOut: []*example.Pod{preset[0].storedObj}, - rv: "0", -@@ -1271,7 +1272,7 @@ func TestList(t *testing.T) { - }, - { - name: "test List on existing key with resource version set to 0, match=Invalid", -- prefix: "/one-level/", -+ prefix: basePath + "/one-level/", - pred: storage.Everything, - rv: "0", - rvMatch: "Invalid", -@@ -1279,7 +1280,7 @@ func TestList(t *testing.T) { - }, - { - name: "test List on existing key with resource version set before first write, match=NotOlderThan", -- prefix: "/one-level/", -+ prefix: basePath + "/one-level/", - pred: storage.Everything, - expectedOut: []*example.Pod{preset[0].storedObj}, - rv: initialRV, -@@ -1287,7 +1288,7 @@ func TestList(t *testing.T) { - }, - { - name: "test List on existing key with resource version set before first write, match=Invalid", -- prefix: "/one-level/", -+ prefix: basePath + "/one-level/", - pred: storage.Everything, - rv: initialRV, - rvMatch: "Invalid", -@@ -1295,14 +1296,14 @@ func TestList(t *testing.T) { - }, - { - name: "test List on existing key with resource version set to current resource version", -- prefix: "/one-level/", -+ prefix: basePath + "/one-level/", - pred: storage.Everything, - expectedOut: []*example.Pod{preset[0].storedObj}, - rv: list.ResourceVersion, - }, - { - name: "test List on existing key with resource version set to current resource version, match=Exact", -- prefix: "/one-level/", -+ prefix: basePath + "/one-level/", - pred: storage.Everything, - expectedOut: []*example.Pod{preset[0].storedObj}, - rv: list.ResourceVersion, -@@ -1311,7 +1312,7 @@ func TestList(t *testing.T) { - }, - { - name: "test List on existing key with resource version set to current resource version, match=NotOlderThan", -- prefix: "/one-level/", -+ prefix: basePath + "/one-level/", - pred: storage.Everything, - expectedOut: []*example.Pod{preset[0].storedObj}, - rv: list.ResourceVersion, -@@ -1319,13 +1320,13 @@ func TestList(t *testing.T) { - }, - { - name: "test List on non-existing key", -- prefix: "/non-existing/", -+ prefix: basePath + "/non-existing/", - pred: storage.Everything, - expectedOut: nil, - }, - { - name: "test List with pod name matching", -- prefix: "/one-level/", -+ prefix: basePath + "/one-level/", - pred: storage.SelectionPredicate{ - Label: labels.Everything(), - Field: fields.ParseSelectorOrDie("metadata.name!=foo"), -@@ -1334,7 +1335,7 @@ func TestList(t *testing.T) { - }, - { - name: "test List with limit", -- prefix: "/two-level/", -+ prefix: basePath + "/two-level/", - pred: storage.SelectionPredicate{ - Label: labels.Everything(), - Field: fields.Everything(), -@@ -1346,7 +1347,7 @@ func TestList(t *testing.T) { - }, - { - name: "test List with limit at current resource version", -- prefix: "/two-level/", -+ prefix: basePath + "/two-level/", - pred: storage.SelectionPredicate{ - Label: labels.Everything(), - Field: fields.Everything(), -@@ -1360,7 +1361,7 @@ func TestList(t *testing.T) { - }, - { - name: "test List with limit at current resource version and match=Exact", -- prefix: "/two-level/", -+ prefix: basePath + "/two-level/", - pred: storage.SelectionPredicate{ - Label: labels.Everything(), - Field: fields.Everything(), -@@ -1375,7 +1376,7 @@ func TestList(t *testing.T) { - }, - { - name: "test List with limit at resource version 0", -- prefix: "/two-level/", -+ prefix: basePath + "/two-level/", - pred: storage.SelectionPredicate{ - Label: labels.Everything(), - Field: fields.Everything(), -@@ -1389,7 +1390,7 @@ func TestList(t *testing.T) { - }, - { - name: "test List with limit at resource version 0 match=NotOlderThan", -- prefix: "/two-level/", -+ prefix: basePath + "/two-level/", - pred: storage.SelectionPredicate{ - Label: labels.Everything(), - Field: fields.Everything(), -@@ -1404,7 +1405,7 @@ func TestList(t *testing.T) { - }, - { - name: "test List with limit at resource version before first write and match=Exact", -- prefix: "/two-level/", -+ prefix: basePath + "/two-level/", - pred: storage.SelectionPredicate{ - Label: labels.Everything(), - Field: fields.Everything(), -@@ -1419,7 +1420,7 @@ func TestList(t *testing.T) { - { - name: "test List with limit when paging disabled", - disablePaging: true, -- prefix: "/two-level/", -+ prefix: basePath + "/two-level/", - pred: storage.SelectionPredicate{ - Label: labels.Everything(), - Field: fields.Everything(), -@@ -1430,7 +1431,7 @@ func TestList(t *testing.T) { - }, - { - name: "test List with pregenerated continue token", -- prefix: "/two-level/", -+ prefix: basePath + "/two-level/", - pred: storage.SelectionPredicate{ - Label: labels.Everything(), - Field: fields.Everything(), -@@ -1441,7 +1442,7 @@ func TestList(t *testing.T) { - }, - { - name: "ignores resource version 0 for List with pregenerated continue token", -- prefix: "/two-level/", -+ prefix: basePath + "/two-level/", - pred: storage.SelectionPredicate{ - Label: labels.Everything(), - Field: fields.Everything(), -@@ -1453,13 +1454,13 @@ func TestList(t *testing.T) { - }, - { - name: "test List with multiple levels of directories and expect flattened result", -- prefix: "/two-level/", -+ prefix: basePath + "/two-level/", - pred: storage.Everything, - expectedOut: []*example.Pod{preset[1].storedObj, preset[2].storedObj}, - }, - { - name: "test List with filter returning only one item, ensure only a single page returned", -- prefix: "/", -+ prefix: basePath, - pred: storage.SelectionPredicate{ - Field: fields.OneTermEqualSelector("metadata.name", "fourth"), - Label: labels.Everything(), -@@ -1470,7 +1471,7 @@ func TestList(t *testing.T) { - }, - { - name: "test List with filter returning only one item, covers the entire list", -- prefix: "/", -+ prefix: basePath, - pred: storage.SelectionPredicate{ - Field: fields.OneTermEqualSelector("metadata.name", "fourth"), - Label: labels.Everything(), -@@ -1481,7 +1482,7 @@ func TestList(t *testing.T) { - }, - { - name: "test List with filter returning only one item, covers the entire list, with resource version 0", -- prefix: "/", -+ prefix: basePath, - pred: storage.SelectionPredicate{ - Field: fields.OneTermEqualSelector("metadata.name", "fourth"), - Label: labels.Everything(), -@@ -1493,7 +1494,7 @@ func TestList(t *testing.T) { - }, - { - name: "test List with filter returning two items, more pages possible", -- prefix: "/", -+ prefix: basePath, - pred: storage.SelectionPredicate{ - Field: fields.OneTermEqualSelector("metadata.name", "foo"), - Label: labels.Everything(), -@@ -1504,7 +1505,7 @@ func TestList(t *testing.T) { - }, - { - name: "filter returns two items split across multiple pages", -- prefix: "/", -+ prefix: basePath, - pred: storage.SelectionPredicate{ - Field: fields.OneTermEqualSelector("metadata.name", "bar"), - Label: labels.Everything(), -@@ -1514,7 +1515,7 @@ func TestList(t *testing.T) { - }, - { - name: "filter returns one item for last page, ends on last item, not full", -- prefix: "/", -+ prefix: basePath, - pred: storage.SelectionPredicate{ - Field: fields.OneTermEqualSelector("metadata.name", "bar"), - Label: labels.Everything(), -@@ -1525,7 +1526,7 @@ func TestList(t *testing.T) { - }, - { - name: "filter returns one item for last page, starts on last item, full", -- prefix: "/", -+ prefix: basePath, - pred: storage.SelectionPredicate{ - Field: fields.OneTermEqualSelector("metadata.name", "bar"), - Label: labels.Everything(), -@@ -1536,7 +1537,7 @@ func TestList(t *testing.T) { - }, - { - name: "filter returns one item for last page, starts on last item, partial page", -- prefix: "/", -+ prefix: basePath, - pred: storage.SelectionPredicate{ - Field: fields.OneTermEqualSelector("metadata.name", "bar"), - Label: labels.Everything(), -@@ -1547,7 +1548,7 @@ func TestList(t *testing.T) { - }, - { - name: "filter returns two items, page size equal to total list size", -- prefix: "/", -+ prefix: basePath, - pred: storage.SelectionPredicate{ - Field: fields.OneTermEqualSelector("metadata.name", "bar"), - Label: labels.Everything(), -@@ -1557,7 +1558,7 @@ func TestList(t *testing.T) { - }, - { - name: "filter returns one item, page size equal to total list size", -- prefix: "/", -+ prefix: basePath, - pred: storage.SelectionPredicate{ - Field: fields.OneTermEqualSelector("metadata.name", "fourth"), - Label: labels.Everything(), -@@ -1636,7 +1637,7 @@ func TestListContinuation(t *testing.T) { - ctx := context.Background() +@@ -531,7 +532,7 @@ func TestListContinuation(t *testing.T) { + etcdClient.KV = recorder // Setup storage with the following structure: - // / @@ -777,7 +411,7 @@ index fedbcce3..65a73c21 100644 // - one-level/ // | - test // | -@@ -1653,15 +1654,15 @@ func TestListContinuation(t *testing.T) { +@@ -548,15 +549,15 @@ func TestListContinuation(t *testing.T) { storedObj *example.Pod }{ { @@ -796,7 +430,7 @@ index fedbcce3..65a73c21 100644 obj: &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "bar"}}, }, } -@@ -1693,7 +1694,7 @@ func TestListContinuation(t *testing.T) { +@@ -588,7 +589,7 @@ func TestListContinuation(t *testing.T) { Predicate: pred(1, ""), Recursive: true, } @@ -805,7 +439,7 @@ index fedbcce3..65a73c21 100644 t.Fatalf("Unable to get initial list: %v", err) } if len(out.Continue) == 0 { -@@ -1718,13 +1719,13 @@ func TestListContinuation(t *testing.T) { +@@ -613,13 +614,13 @@ func TestListContinuation(t *testing.T) { Predicate: pred(0, continueFromSecondItem), Recursive: true, } @@ -816,12 +450,12 @@ index fedbcce3..65a73c21 100644 if len(out.Continue) != 0 { t.Fatalf("Unexpected continuation token set") } -- key, rv, err := decodeContinue(continueFromSecondItem, "/") -+ key, rv, err := decodeContinue(continueFromSecondItem, basePath) +- key, rv, err := storage.DecodeContinue(continueFromSecondItem, "/") ++ key, rv, err := storage.DecodeContinue(continueFromSecondItem, basePath) t.Logf("continue token was %d %s %v", rv, key, err) - expectNoDiff(t, "incorrect second page", []example.Pod{*preset[1].storedObj, *preset[2].storedObj}, out.Items) + storagetesting.ExpectNoDiff(t, "incorrect second page", []example.Pod{*preset[1].storedObj, *preset[2].storedObj}, out.Items) if transformer.reads != 2 { -@@ -1743,7 +1744,7 @@ func TestListContinuation(t *testing.T) { +@@ -638,7 +639,7 @@ func TestListContinuation(t *testing.T) { Predicate: pred(1, continueFromSecondItem), Recursive: true, } @@ -830,7 +464,7 @@ index fedbcce3..65a73c21 100644 t.Fatalf("Unable to get second page: %v", err) } if len(out.Continue) == 0 { -@@ -1767,7 +1768,7 @@ func TestListContinuation(t *testing.T) { +@@ -662,7 +663,7 @@ func TestListContinuation(t *testing.T) { Predicate: pred(1, continueFromThirdItem), Recursive: true, } @@ -839,7 +473,7 @@ index fedbcce3..65a73c21 100644 t.Fatalf("Unable to get second page: %v", err) } if len(out.Continue) != 0 { -@@ -1796,7 +1797,7 @@ func TestListPaginationRareObject(t *testing.T) { +@@ -688,7 +689,7 @@ func TestListPaginationRareObject(t *testing.T) { podCount := 1000 var pods []*example.Pod for i := 0; i < podCount; i++ { @@ -848,7 +482,7 @@ index fedbcce3..65a73c21 100644 obj := &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: fmt.Sprintf("pod-%d", i)}} storedObj := &example.Pod{} err := store.Create(ctx, key, obj, storedObj, 0) -@@ -1819,7 +1820,7 @@ func TestListPaginationRareObject(t *testing.T) { +@@ -711,7 +712,7 @@ func TestListPaginationRareObject(t *testing.T) { }, Recursive: true, } @@ -857,30 +491,7 @@ index fedbcce3..65a73c21 100644 t.Fatalf("Unable to get initial list: %v", err) } if len(out.Continue) != 0 { -@@ -1874,26 +1875,26 @@ func TestListContinuationWithFilter(t *testing.T) { - storedObj *example.Pod - }{ - { -- key: "/1", -+ key: basePath + "/1", - obj: &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}, - }, - { -- key: "/2", -+ key: basePath + "/2", - obj: &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "bar"}}, // this should not match - }, - { -- key: "/3", -+ key: basePath + "/3", - obj: &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}, - }, - { -- key: "/4", -+ key: basePath + "/4", - obj: &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}, - }, - } +@@ -782,7 +783,7 @@ func TestListContinuationWithFilter(t *testing.T) { for i, ps := range preset { preset[i].storedObj = &example.Pod{} @@ -889,7 +500,7 @@ index fedbcce3..65a73c21 100644 if err != nil { t.Fatalf("Set failed: %v", err) } -@@ -1921,7 +1922,7 @@ func TestListContinuationWithFilter(t *testing.T) { +@@ -810,7 +811,7 @@ func TestListContinuationWithFilter(t *testing.T) { Predicate: pred(2, ""), Recursive: true, } @@ -898,7 +509,7 @@ index fedbcce3..65a73c21 100644 t.Errorf("Unable to get initial list: %v", err) } if len(out.Continue) == 0 { -@@ -1953,7 +1954,7 @@ func TestListContinuationWithFilter(t *testing.T) { +@@ -842,7 +843,7 @@ func TestListContinuationWithFilter(t *testing.T) { Predicate: pred(2, cont), Recursive: true, } @@ -907,8 +518,8 @@ index fedbcce3..65a73c21 100644 t.Errorf("Unable to get second page: %v", err) } if len(out.Continue) != 0 { -@@ -1977,7 +1978,7 @@ func TestListInconsistentContinuation(t *testing.T) { - ctx := context.Background() +@@ -863,7 +864,7 @@ func TestListInconsistentContinuation(t *testing.T) { + ctx, store, client := testSetup(t) // Setup storage with the following structure: - // / @@ -916,7 +527,7 @@ index fedbcce3..65a73c21 100644 // - one-level/ // | - test // | -@@ -1994,15 +1995,15 @@ func TestListInconsistentContinuation(t *testing.T) { +@@ -880,15 +881,15 @@ func TestListInconsistentContinuation(t *testing.T) { storedObj *example.Pod }{ { @@ -935,7 +546,7 @@ index fedbcce3..65a73c21 100644 obj: &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "bar"}}, }, } -@@ -2034,7 +2035,7 @@ func TestListInconsistentContinuation(t *testing.T) { +@@ -920,7 +921,7 @@ func TestListInconsistentContinuation(t *testing.T) { Predicate: pred(1, ""), Recursive: true, } @@ -944,7 +555,7 @@ index fedbcce3..65a73c21 100644 t.Fatalf("Unable to get initial list: %v", err) } if len(out.Continue) == 0 { -@@ -2078,7 +2079,7 @@ func TestListInconsistentContinuation(t *testing.T) { +@@ -964,7 +965,7 @@ func TestListInconsistentContinuation(t *testing.T) { Predicate: pred(0, continueFromSecondItem), Recursive: true, } @@ -953,7 +564,7 @@ index fedbcce3..65a73c21 100644 if err == nil { t.Fatalf("unexpected no error") } -@@ -2100,7 +2101,7 @@ func TestListInconsistentContinuation(t *testing.T) { +@@ -986,7 +987,7 @@ func TestListInconsistentContinuation(t *testing.T) { Predicate: pred(1, inconsistentContinueFromSecondItem), Recursive: true, } @@ -962,7 +573,7 @@ index fedbcce3..65a73c21 100644 t.Fatalf("Unable to get second page: %v", err) } if len(out.Continue) == 0 { -@@ -2117,7 +2118,7 @@ func TestListInconsistentContinuation(t *testing.T) { +@@ -1005,7 +1006,7 @@ func TestListInconsistentContinuation(t *testing.T) { Predicate: pred(1, continueFromThirdItem), Recursive: true, } @@ -971,18 +582,9 @@ index fedbcce3..65a73c21 100644 t.Fatalf("Unable to get second page: %v", err) } if len(out.Continue) != 0 { -@@ -2150,7 +2151,7 @@ func testSetup(t *testing.T) (context.Context, *store, *clientv3.Client) { - // keys and stored objects. - func testPropogateStore(ctx context.Context, t *testing.T, store *store, obj *example.Pod) (string, *example.Pod) { - // Setup store with a key and grab the output for returning. -- key := "/testkey" -+ key := basePath + "/testkey" - return key, testPropogateStoreWithKey(ctx, t, store, key, obj) - } +@@ -1127,9 +1128,9 @@ func testSetup(t *testing.T, opts ...setupOption) (context.Context, *store, *cli -@@ -2177,9 +2178,9 @@ func TestPrefix(t *testing.T) { - codec := apitesting.TestCodec(codecs, examplev1.SchemeGroupVersion) - transformer := &prefixTransformer{prefix: []byte(defaultTestPrefix)} + func TestPrefix(t *testing.T) { testcases := map[string]string{ - "custom/prefix": "/custom/prefix", - "/custom//prefix//": "/custom/prefix", @@ -992,8 +594,8 @@ index fedbcce3..65a73c21 100644 + "/registry": "/registry/", } for configuredPrefix, effectivePrefix := range testcases { - store := newStore(client, codec, nil, configuredPrefix, schema.GroupResource{Resource: "widgets"}, transformer, true, newTestLeaseManagerConfig()) -@@ -2375,7 +2376,7 @@ func TestConsistentList(t *testing.T) { + _, store, _ := testSetup(t, withPrefix(configuredPrefix)) +@@ -1302,7 +1303,7 @@ func TestConsistentList(t *testing.T) { Predicate: predicate, Recursive: true, } @@ -1002,7 +604,7 @@ index fedbcce3..65a73c21 100644 t.Fatalf("failed to list objects: %v", err) } -@@ -2388,7 +2389,7 @@ func TestConsistentList(t *testing.T) { +@@ -1315,7 +1316,7 @@ func TestConsistentList(t *testing.T) { } result2 := example.PodList{} @@ -1011,7 +613,7 @@ index fedbcce3..65a73c21 100644 t.Fatalf("failed to list objects: %v", err) } -@@ -2398,7 +2399,7 @@ func TestConsistentList(t *testing.T) { +@@ -1325,7 +1326,7 @@ func TestConsistentList(t *testing.T) { options.ResourceVersionMatch = metav1.ResourceVersionMatchNotOlderThan result3 := example.PodList{} @@ -1020,7 +622,7 @@ index fedbcce3..65a73c21 100644 t.Fatalf("failed to list objects: %v", err) } -@@ -2406,7 +2407,7 @@ func TestConsistentList(t *testing.T) { +@@ -1333,7 +1334,7 @@ func TestConsistentList(t *testing.T) { options.ResourceVersionMatch = metav1.ResourceVersionMatchExact result4 := example.PodList{} @@ -1029,26 +631,7 @@ index fedbcce3..65a73c21 100644 t.Fatalf("failed to list objects: %v", err) } -@@ -2467,15 +2468,15 @@ func TestLeaseMaxObjectCount(t *testing.T) { - expectAttachedCount int64 - }{ - { -- key: "testkey1", -+ key: basePath + "/testkey1", - expectAttachedCount: 1, - }, - { -- key: "testkey2", -+ key: basePath + "/testkey2", - expectAttachedCount: 2, - }, - { -- key: "testkey3", -+ key: basePath + "testkey3", - // We assume each time has 1 object attached to the lease - // so after granting a new lease, the recorded count is set to 1 - expectAttachedCount: 1, -@@ -2503,3 +2504,81 @@ func expectNoDiff(t *testing.T, msg string, expected, got interface{}) { +@@ -1384,3 +1385,78 @@ func TestLeaseMaxObjectCount(t *testing.T) { } } } @@ -1085,10 +668,7 @@ index fedbcce3..65a73c21 100644 + pathPrefix = "/first/second" + expectPrefix = pathPrefix + "/" + ) -+ client := testserver.RunEtcd(t, nil) -+ codec := apitesting.TestCodec(codecs, examplev1.SchemeGroupVersion) -+ store := newStore(client, codec, newPod, pathPrefix, schema.GroupResource{Resource: "pods"}, -+ &prefixTransformer{prefix: []byte(defaultTestPrefix)}, true, newTestLeaseManagerConfig()) ++ _, store, _ := testSetup(t, withPrefix(pathPrefix)) + + for _, key := range validKeys { + k, err := store.prepareKey(key) @@ -1130,3 +710,97 @@ index fedbcce3..65a73c21 100644 + _, countErr := store.Count(invalidKey) + expectInvalidKey("Count", countErr) +} +diff --git a/staging/src/k8s.io/apiserver/pkg/storage/testing/store_tests.go b/staging/src/k8s.io/apiserver/pkg/storage/testing/store_tests.go +index c83ee833ee6..df7078f6bd9 100644 +--- a/staging/src/k8s.io/apiserver/pkg/storage/testing/store_tests.go ++++ b/staging/src/k8s.io/apiserver/pkg/storage/testing/store_tests.go +@@ -42,6 +42,8 @@ import ( + + type KeyValidation func(ctx context.Context, t *testing.T, key string) + ++const basePath = "/keybase" ++ + func RunTestCreate(ctx context.Context, t *testing.T, store storage.Interface, validation KeyValidation) { + key := "/testkey" + out := &example.Pod{} +@@ -445,11 +447,11 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface) { + Predicate: storage.Everything, + Recursive: true, + } +- if err := store.GetList(ctx, "/two-level", storageOpts, list); err != nil { ++ if err := store.GetList(ctx, basePath+"/two-level", storageOpts, list); err != nil { + t.Errorf("Unexpected error: %v", err) + } + continueRV, _ := strconv.Atoi(list.ResourceVersion) +- secondContinuation, err := storage.EncodeContinue("/two-level/2", "/two-level/", int64(continueRV)) ++ secondContinuation, err := storage.EncodeContinue(basePath+"/two-level/2", basePath+"/two-level/", int64(continueRV)) + if err != nil { + t.Fatal(err) + } +@@ -827,7 +829,7 @@ func RunTestList(ctx context.Context, t *testing.T, store storage.Interface) { + Predicate: tt.pred, + Recursive: true, + } +- err = store.GetList(ctx, tt.prefix, storageOpts, out) ++ err = store.GetList(ctx, basePath+tt.prefix, storageOpts, out) + if tt.expectRVTooLarge { + if err == nil || !storage.IsTooLargeResourceVersion(err) { + t.Fatalf("expecting resource version too high error, but get: %s", err) +@@ -926,7 +928,7 @@ func RunTestListWithoutPaging(ctx context.Context, t *testing.T, store storage.I + Recursive: true, + } + +- if err := store.GetList(ctx, tt.prefix, storageOpts, out); err != nil { ++ if err := store.GetList(ctx, basePath+tt.prefix, storageOpts, out); err != nil { + t.Fatalf("GetList failed: %v", err) + return + } +@@ -952,7 +954,7 @@ func RunTestListWithoutPaging(ctx context.Context, t *testing.T, store storage.I + // from before any were created along with the full set of objects that were persisted + func seedMultiLevelData(ctx context.Context, store storage.Interface) (string, []*example.Pod, error) { + // Setup storage with the following structure: +- // / ++ // /keybase/ + // - one-level/ + // | - test + // | +@@ -975,30 +977,30 @@ func seedMultiLevelData(ctx context.Context, store storage.Interface) (string, [ + storedObj *example.Pod + }{ + { +- key: "/one-level/test", ++ key: basePath + "/one-level/test", + obj: &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}, + }, + { +- key: "/two-level/1/test", ++ key: basePath + "/two-level/1/test", + obj: &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}, + }, + { +- key: "/two-level/2/test", ++ key: basePath + "/two-level/2/test", + obj: &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "bar"}}, + }, + { +- key: "/z-level/3/test", ++ key: basePath + "/z-level/3/test", + obj: &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "fourth"}}, + }, + { +- key: "/z-level/3/test-2", ++ key: basePath + "/z-level/3/test-2", + obj: &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "bar"}}, + }, + } + + // we want to figure out the resourceVersion before we create anything + initialList := &example.PodList{} +- if err := store.GetList(ctx, "/", storage.ListOptions{Predicate: storage.Everything, Recursive: true}, initialList); err != nil { ++ if err := store.GetList(ctx, basePath, storage.ListOptions{Predicate: storage.Everything, Recursive: true}, initialList); err != nil { + return "", nil, fmt.Errorf("failed to determine starting resourceVersion: %w", err) + } + initialRV := initialList.ResourceVersion +-- +2.25.1 + diff --git a/0008-fix-node-address-validation.patch b/0006-fix-node-address-validation.patch similarity index 99% rename from 0008-fix-node-address-validation.patch rename to 0006-fix-node-address-validation.patch index 057bbe01a9519e67f8a580a77a12e2226f68f1b0..540447ecdfc13fdf665afa47938e39d48b70d73d 100644 --- a/0008-fix-node-address-validation.patch +++ b/0006-fix-node-address-validation.patch @@ -1,4 +1,4 @@ -From 78d552efe620879599509ff0f9b04b8764e1878f Mon Sep 17 00:00:00 2001 +From f85027fcc12d02f79a0649115bdbaf7c9d8aab17 Mon Sep 17 00:00:00 2001 From: Andrew Sy Kim Date: Mon, 7 Nov 2022 10:22:44 -0500 Subject: [PATCH] fix node address validation diff --git a/0009-Add-ephemeralcontainer-to-imagepolicy-securityaccoun.patch b/0007-Add-ephemeralcontainer-to-imagepolicy-securityaccoun.patch similarity index 96% rename from 0009-Add-ephemeralcontainer-to-imagepolicy-securityaccoun.patch rename to 0007-Add-ephemeralcontainer-to-imagepolicy-securityaccoun.patch index 869d1ae379b7d3740e8c355ec14c15c792e019fc..f781cb3866a71fa2a4b636a80fc86e72fe193188 100644 --- a/0009-Add-ephemeralcontainer-to-imagepolicy-securityaccoun.patch +++ b/0007-Add-ephemeralcontainer-to-imagepolicy-securityaccoun.patch @@ -1,4 +1,4 @@ -From f754a4dee31455a0d7fc0f51cb85348af9ea5e1f Mon Sep 17 00:00:00 2001 +From 8781d503a08ff8a1a29179c80252470ac77b3bd5 Mon Sep 17 00:00:00 2001 From: Rita Zhang Date: Tue, 30 May 2023 20:35:33 +0000 Subject: [PATCH] Add ephemeralcontainer to imagepolicy securityaccount @@ -334,10 +334,10 @@ index d1f81d51950..a9188462fb9 100644 err = wh.Validate(context.TODO(), attr, nil) if tt.wantAllowed { diff --git a/plugin/pkg/admission/serviceaccount/admission.go b/plugin/pkg/admission/serviceaccount/admission.go -index 035d54ea8ea..f6e25f3c19d 100644 +index 769a115aef5..c844a051c24 100644 --- a/plugin/pkg/admission/serviceaccount/admission.go +++ b/plugin/pkg/admission/serviceaccount/admission.go -@@ -100,7 +100,7 @@ var _ = genericadmissioninitializer.WantsExternalKubeInformerFactory(&Plugin{}) +@@ -99,7 +99,7 @@ var _ = genericadmissioninitializer.WantsExternalKubeInformerFactory(&Plugin{}) // 5. If MountServiceAccountToken is true, it adds a VolumeMount with the pod's ServiceAccount's api token secret to containers func NewServiceAccount() *Plugin { return &Plugin{ @@ -346,7 +346,7 @@ index 035d54ea8ea..f6e25f3c19d 100644 // TODO: enable this once we've swept secret usage to account for adding secret references to service accounts LimitSecretReferences: false, // Auto mount service account API token secrets -@@ -140,7 +140,10 @@ func (s *Plugin) Admit(ctx context.Context, a admission.Attributes, o admission. +@@ -139,7 +139,10 @@ func (s *Plugin) Admit(ctx context.Context, a admission.Attributes, o admission. if shouldIgnore(a) { return nil } @@ -358,7 +358,7 @@ index 035d54ea8ea..f6e25f3c19d 100644 pod := a.GetObject().(*api.Pod) // Don't modify the spec of mirror pods. -@@ -157,7 +160,7 @@ func (s *Plugin) Admit(ctx context.Context, a admission.Attributes, o admission. +@@ -156,7 +159,7 @@ func (s *Plugin) Admit(ctx context.Context, a admission.Attributes, o admission. serviceAccount, err := s.getServiceAccount(a.GetNamespace(), pod.Spec.ServiceAccountName) if err != nil { @@ -367,7 +367,7 @@ index 035d54ea8ea..f6e25f3c19d 100644 } if s.MountServiceAccountToken && shouldAutomount(serviceAccount, pod) { s.mountServiceAccountToken(serviceAccount, pod) -@@ -180,6 +183,15 @@ func (s *Plugin) Validate(ctx context.Context, a admission.Attributes, o admissi +@@ -179,6 +182,15 @@ func (s *Plugin) Validate(ctx context.Context, a admission.Attributes, o admissi pod := a.GetObject().(*api.Pod) @@ -383,7 +383,7 @@ index 035d54ea8ea..f6e25f3c19d 100644 // Mirror pods have restrictions on what they can reference if _, isMirrorPod := pod.Annotations[api.MirrorPodAnnotationKey]; isMirrorPod { if len(pod.Spec.ServiceAccountName) != 0 { -@@ -205,6 +217,10 @@ func (s *Plugin) Validate(ctx context.Context, a admission.Attributes, o admissi +@@ -204,6 +216,10 @@ func (s *Plugin) Validate(ctx context.Context, a admission.Attributes, o admissi return nil } @@ -394,7 +394,7 @@ index 035d54ea8ea..f6e25f3c19d 100644 // Ensure the referenced service account exists serviceAccount, err := s.getServiceAccount(a.GetNamespace(), pod.Spec.ServiceAccountName) if err != nil { -@@ -221,10 +237,7 @@ func (s *Plugin) Validate(ctx context.Context, a admission.Attributes, o admissi +@@ -220,10 +236,7 @@ func (s *Plugin) Validate(ctx context.Context, a admission.Attributes, o admissi } func shouldIgnore(a admission.Attributes) bool { @@ -406,7 +406,7 @@ index 035d54ea8ea..f6e25f3c19d 100644 return true } obj := a.GetObject() -@@ -350,6 +363,36 @@ func (s *Plugin) limitSecretReferences(serviceAccount *corev1.ServiceAccount, po +@@ -349,6 +362,36 @@ func (s *Plugin) limitSecretReferences(serviceAccount *corev1.ServiceAccount, po return nil } @@ -444,10 +444,10 @@ index 035d54ea8ea..f6e25f3c19d 100644 // Find the volume and volume name for the ServiceAccountTokenSecret if it already exists tokenVolumeName := "" diff --git a/plugin/pkg/admission/serviceaccount/admission_test.go b/plugin/pkg/admission/serviceaccount/admission_test.go -index ca43abf9c3f..f5359253985 100644 +index d50f321a8be..bf15f870d75 100644 --- a/plugin/pkg/admission/serviceaccount/admission_test.go +++ b/plugin/pkg/admission/serviceaccount/admission_test.go -@@ -545,6 +545,34 @@ func TestAllowsReferencedSecret(t *testing.T) { +@@ -544,6 +544,34 @@ func TestAllowsReferencedSecret(t *testing.T) { if err := admissiontesting.WithReinvocationTesting(t, admit).Admit(context.TODO(), attrs, nil); err != nil { t.Errorf("Unexpected error: %v", err) } @@ -482,7 +482,7 @@ index ca43abf9c3f..f5359253985 100644 } func TestRejectsUnreferencedSecretVolumes(t *testing.T) { -@@ -622,6 +650,66 @@ func TestRejectsUnreferencedSecretVolumes(t *testing.T) { +@@ -621,6 +649,66 @@ func TestRejectsUnreferencedSecretVolumes(t *testing.T) { if err := admissiontesting.WithReinvocationTesting(t, admit).Admit(context.TODO(), attrs, nil); err == nil || !strings.Contains(err.Error(), "with envVar") { t.Errorf("Unexpected error: %v", err) } diff --git a/kubernetes.spec b/kubernetes.spec index e892a12c94298e32590432e0d8cfe68a101d533d..1b7aece8654c5cb10b3f2812d6fbac2127cdd847 100644 --- a/kubernetes.spec +++ b/kubernetes.spec @@ -2,12 +2,12 @@ %global _buildshell /bin/bash Name: kubernetes -Version: 1.24.0 -Release: 5 +Version: 1.25.3 +Release: 1 Summary: Container cluster management License: ASL 2.0 URL: https://k8s.io/kubernetes -Source0: https://github.com/kubernetes/kubernetes/archive/v1.24.0.tar.gz +Source0: https://github.com/kubernetes/kubernetes/archive/v1.25.3.tar.gz Source1: kube-proxy.service Source2: kube-apiserver.service Source3: kube-scheduler.service @@ -26,13 +26,11 @@ Source15: kubernetes.conf Patch0001: 0001-fix-compile-options.patch Patch0002: 0002-kubelet-support-exec-and-attach-websocket-protocol.patch -Patch0003: 0003-timeout-wait-backend-to-frontend-complete.patch -Patch0004: 0004-Add-an-option-for-aggregator.patch -Patch0005: 0005-Escape-terminal-special-characters-in-kubectl-112553.patch -Patch0006: 0006-Return-error-for-localhost-seccomp-type-with-no-loca.patch -Patch0007: 0007-Validate-etcd-paths.patch -Patch0008: 0008-fix-node-address-validation.patch -Patch0009: 0009-Add-ephemeralcontainer-to-imagepolicy-securityaccoun.patch +Patch0003: 0003-Escape-terminal-special-characters-in-kubectl-112553.patch +Patch0004: 0004-Return-error-for-localhost-seccomp-type-with-no-loca.patch +Patch0005: 0005-Validate-etcd-paths.patch +Patch0006: 0006-fix-node-address-validation.patch +Patch0007: 0007-Add-ephemeralcontainer-to-imagepolicy-securityaccoun.patch %description Container cluster management. @@ -264,6 +262,12 @@ getent passwd kube >/dev/null || useradd -r -g kube -d / -s /sbin/nologin \ %systemd_postun kubelet kube-proxy %changelog +* Fri Jul 21 2023 zhangxiaoyu - 1.25.3-1 +- Type:update +- CVE:NA +- SUG:NA +- DESC:update to 1.25.3 + * Tue Jul 04 2023 zhangxiaoyu - 1.24.0-5 - Type:bugfix - CVE:NA diff --git a/v1.24.0.tar.gz b/v1.25.3.tar.gz similarity index 74% rename from v1.24.0.tar.gz rename to v1.25.3.tar.gz index 01592a654173df732602114361a4867096e0c490..9d90c7e56b63734dc57933ad11f5c298a5addb3b 100644 Binary files a/v1.24.0.tar.gz and b/v1.25.3.tar.gz differ