diff --git a/api/swagger-spec/v1.json b/api/swagger-spec/v1.json index d26aba890f5..d15c23a0445 100644 --- a/api/swagger-spec/v1.json +++ b/api/swagger-spec/v1.json @@ -5957,6 +5957,36 @@ "consumes": [ "*/*" ] + }, + { + "type": "string", + "method": "POST", + "summary": "connect POST requests to exec of Pod", + "nickname": "connectPostPodExec", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] } ] }, @@ -6044,6 +6074,36 @@ "consumes": [ "*/*" ] + }, + { + "type": "string", + "method": "POST", + "summary": "connect POST requests to portforward of Pod", + "nickname": "connectPostPodPortforward", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] } ] }, diff --git a/api/swagger-spec/v1beta3.json b/api/swagger-spec/v1beta3.json index b563fc43743..4318d0535d0 100644 --- a/api/swagger-spec/v1beta3.json +++ b/api/swagger-spec/v1beta3.json @@ -5957,6 +5957,36 @@ "consumes": [ "*/*" ] + }, + { + "type": "string", + "method": "POST", + "summary": "connect POST requests to exec of Pod", + "nickname": "connectPostPodExec", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] } ] }, @@ -6044,6 +6074,36 @@ "consumes": [ "*/*" ] + }, + { + "type": "string", + "method": "POST", + "summary": "connect POST requests to portforward of Pod", + "nickname": "connectPostPodPortforward", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] } ] }, diff --git a/pkg/registry/pod/etcd/etcd.go b/pkg/registry/pod/etcd/etcd.go index 9b86bfd75c2..10066f6712e 100644 --- a/pkg/registry/pod/etcd/etcd.go +++ b/pkg/registry/pod/etcd/etcd.go @@ -280,7 +280,8 @@ func (r *ProxyREST) Connect(ctx api.Context, id string, opts runtime.Object) (re return genericrest.NewUpgradeAwareProxyHandler(location, nil, false), nil } -var upgradeableMethods = []string{"GET"} +// Support both GET and POST methods. Over time, we want to move all clients to start using POST and then stop supporting GET. +var upgradeableMethods = []string{"GET", "POST"} // ExecREST implements the exec subresource for a Pod type ExecREST struct { diff --git a/pkg/registry/pod/rest.go b/pkg/registry/pod/rest.go index a4a10741e6f..d35e8302eda 100644 --- a/pkg/registry/pod/rest.go +++ b/pkg/registry/pod/rest.go @@ -249,7 +249,7 @@ func ExecLocation(getter ResourceGetter, connInfo client.ConnectionInfoGetter, c nodeHost := pod.Spec.NodeName if len(nodeHost) == 0 { // If pod has not been assigned a host, return an empty location - return nil, nil, fmt.Errorf("pod %s does not have a host assigned", name) + return nil, nil, errors.NewBadRequest(fmt.Sprintf("pod %s does not have a host assigned", name)) } nodeScheme, nodePort, nodeTransport, err := connInfo.GetConnectionInfo(nodeHost) if err != nil { diff --git a/test/integration/auth_test.go b/test/integration/auth_test.go index 6e4dcb31096..a0371f147ef 100644 --- a/test/integration/auth_test.go +++ b/test/integration/auth_test.go @@ -275,6 +275,16 @@ func getTestRequests() []struct { {"POST", timeoutPath("pods", api.NamespaceDefault, ""), aPod, code201}, {"PUT", timeoutPath("pods", api.NamespaceDefault, "a"), aPod, code200}, {"GET", path("pods", api.NamespaceDefault, "a"), "", code200}, + // GET and POST for /exec should return Bad Request (400) since the pod has not been assigned a node yet. + {"GET", path("pods", api.NamespaceDefault, "a") + "/exec", "", code400}, + {"POST", path("pods", api.NamespaceDefault, "a") + "/exec", "", code400}, + // PUT for /exec should return Method Not Allowed (405). + {"PUT", path("pods", api.NamespaceDefault, "a") + "/exec", "", code405}, + // GET and POST for /portforward should return Bad Request (400) since the pod has not been assigned a node yet. + {"GET", path("pods", api.NamespaceDefault, "a") + "/portforward", "", code400}, + {"POST", path("pods", api.NamespaceDefault, "a") + "/portforward", "", code400}, + // PUT for /portforward should return Method Not Allowed (405). + {"PUT", path("pods", api.NamespaceDefault, "a") + "/portforward", "", code405}, {"PATCH", path("pods", api.NamespaceDefault, "a"), "{%v}", code200}, {"DELETE", timeoutPath("pods", api.NamespaceDefault, "a"), deleteNow, code200},