Merge pull request #66807 from caesarxuchao/remove-connectrequest

Automatic merge from submit-queue (batch tested with PRs 66196, 67016, 66807, 67023). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Make admission webhooks conversion convert CONNECT body correctly

Fix #59759.

1. Make apiserver pass connectRequest.Options directly to the admission layer. All other information in rest.ConnectRequest is present in admission attributes.
2. Make the scope.Kind of pod/attach, pod/exec, pod/portforward, node/proxy, service/proxy to their respective options Kind, instead of the parent Kind.

I've tested it locally, the conversion is working correctly for "kubectl attach". I'll add e2e tests.

I'll keep this to myself until I add the tests, but cc @mikedanese @liggitt RE. https://github.com/kubernetes/kubernetes/pull/66633.
pull/8/head
Kubernetes Submit Queue 2018-08-07 11:44:10 -07:00 committed by GitHub
commit d1636b8019
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 303 additions and 256 deletions

View File

@ -4188,7 +4188,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Pod",
"kind": "PodAttachOptions",
"version": "v1"
}
},
@ -4221,7 +4221,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Pod",
"kind": "PodAttachOptions",
"version": "v1"
}
},
@ -4236,7 +4236,7 @@
{
"uniqueItems": true,
"type": "string",
"description": "name of the Pod",
"description": "name of the PodAttachOptions",
"name": "name",
"in": "path",
"required": true
@ -4477,7 +4477,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Pod",
"kind": "PodExecOptions",
"version": "v1"
}
},
@ -4510,7 +4510,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Pod",
"kind": "PodExecOptions",
"version": "v1"
}
},
@ -4532,7 +4532,7 @@
{
"uniqueItems": true,
"type": "string",
"description": "name of the Pod",
"description": "name of the PodExecOptions",
"name": "name",
"in": "path",
"required": true
@ -4717,7 +4717,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Pod",
"kind": "PodPortForwardOptions",
"version": "v1"
}
},
@ -4750,7 +4750,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Pod",
"kind": "PodPortForwardOptions",
"version": "v1"
}
},
@ -4758,7 +4758,7 @@
{
"uniqueItems": true,
"type": "string",
"description": "name of the Pod",
"description": "name of the PodPortForwardOptions",
"name": "name",
"in": "path",
"required": true
@ -4810,7 +4810,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Pod",
"kind": "PodProxyOptions",
"version": "v1"
}
},
@ -4843,7 +4843,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Pod",
"kind": "PodProxyOptions",
"version": "v1"
}
},
@ -4876,7 +4876,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Pod",
"kind": "PodProxyOptions",
"version": "v1"
}
},
@ -4909,7 +4909,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Pod",
"kind": "PodProxyOptions",
"version": "v1"
}
},
@ -4942,7 +4942,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Pod",
"kind": "PodProxyOptions",
"version": "v1"
}
},
@ -4975,7 +4975,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Pod",
"kind": "PodProxyOptions",
"version": "v1"
}
},
@ -5008,7 +5008,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Pod",
"kind": "PodProxyOptions",
"version": "v1"
}
},
@ -5016,7 +5016,7 @@
{
"uniqueItems": true,
"type": "string",
"description": "name of the Pod",
"description": "name of the PodProxyOptions",
"name": "name",
"in": "path",
"required": true
@ -5068,7 +5068,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Pod",
"kind": "PodProxyOptions",
"version": "v1"
}
},
@ -5101,7 +5101,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Pod",
"kind": "PodProxyOptions",
"version": "v1"
}
},
@ -5134,7 +5134,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Pod",
"kind": "PodProxyOptions",
"version": "v1"
}
},
@ -5167,7 +5167,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Pod",
"kind": "PodProxyOptions",
"version": "v1"
}
},
@ -5200,7 +5200,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Pod",
"kind": "PodProxyOptions",
"version": "v1"
}
},
@ -5233,7 +5233,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Pod",
"kind": "PodProxyOptions",
"version": "v1"
}
},
@ -5266,7 +5266,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Pod",
"kind": "PodProxyOptions",
"version": "v1"
}
},
@ -5274,7 +5274,7 @@
{
"uniqueItems": true,
"type": "string",
"description": "name of the Pod",
"description": "name of the PodProxyOptions",
"name": "name",
"in": "path",
"required": true
@ -8995,7 +8995,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Service",
"kind": "ServiceProxyOptions",
"version": "v1"
}
},
@ -9028,7 +9028,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Service",
"kind": "ServiceProxyOptions",
"version": "v1"
}
},
@ -9061,7 +9061,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Service",
"kind": "ServiceProxyOptions",
"version": "v1"
}
},
@ -9094,7 +9094,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Service",
"kind": "ServiceProxyOptions",
"version": "v1"
}
},
@ -9127,7 +9127,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Service",
"kind": "ServiceProxyOptions",
"version": "v1"
}
},
@ -9160,7 +9160,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Service",
"kind": "ServiceProxyOptions",
"version": "v1"
}
},
@ -9193,7 +9193,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Service",
"kind": "ServiceProxyOptions",
"version": "v1"
}
},
@ -9201,7 +9201,7 @@
{
"uniqueItems": true,
"type": "string",
"description": "name of the Service",
"description": "name of the ServiceProxyOptions",
"name": "name",
"in": "path",
"required": true
@ -9253,7 +9253,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Service",
"kind": "ServiceProxyOptions",
"version": "v1"
}
},
@ -9286,7 +9286,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Service",
"kind": "ServiceProxyOptions",
"version": "v1"
}
},
@ -9319,7 +9319,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Service",
"kind": "ServiceProxyOptions",
"version": "v1"
}
},
@ -9352,7 +9352,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Service",
"kind": "ServiceProxyOptions",
"version": "v1"
}
},
@ -9385,7 +9385,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Service",
"kind": "ServiceProxyOptions",
"version": "v1"
}
},
@ -9418,7 +9418,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Service",
"kind": "ServiceProxyOptions",
"version": "v1"
}
},
@ -9451,7 +9451,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Service",
"kind": "ServiceProxyOptions",
"version": "v1"
}
},
@ -9459,7 +9459,7 @@
{
"uniqueItems": true,
"type": "string",
"description": "name of the Service",
"description": "name of the ServiceProxyOptions",
"name": "name",
"in": "path",
"required": true
@ -10651,7 +10651,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Node",
"kind": "NodeProxyOptions",
"version": "v1"
}
},
@ -10684,7 +10684,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Node",
"kind": "NodeProxyOptions",
"version": "v1"
}
},
@ -10717,7 +10717,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Node",
"kind": "NodeProxyOptions",
"version": "v1"
}
},
@ -10750,7 +10750,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Node",
"kind": "NodeProxyOptions",
"version": "v1"
}
},
@ -10783,7 +10783,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Node",
"kind": "NodeProxyOptions",
"version": "v1"
}
},
@ -10816,7 +10816,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Node",
"kind": "NodeProxyOptions",
"version": "v1"
}
},
@ -10849,7 +10849,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Node",
"kind": "NodeProxyOptions",
"version": "v1"
}
},
@ -10857,7 +10857,7 @@
{
"uniqueItems": true,
"type": "string",
"description": "name of the Node",
"description": "name of the NodeProxyOptions",
"name": "name",
"in": "path",
"required": true
@ -10901,7 +10901,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Node",
"kind": "NodeProxyOptions",
"version": "v1"
}
},
@ -10934,7 +10934,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Node",
"kind": "NodeProxyOptions",
"version": "v1"
}
},
@ -10967,7 +10967,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Node",
"kind": "NodeProxyOptions",
"version": "v1"
}
},
@ -11000,7 +11000,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Node",
"kind": "NodeProxyOptions",
"version": "v1"
}
},
@ -11033,7 +11033,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Node",
"kind": "NodeProxyOptions",
"version": "v1"
}
},
@ -11066,7 +11066,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Node",
"kind": "NodeProxyOptions",
"version": "v1"
}
},
@ -11099,7 +11099,7 @@
"x-kubernetes-action": "connect",
"x-kubernetes-group-version-kind": {
"group": "",
"kind": "Node",
"kind": "NodeProxyOptions",
"version": "v1"
}
},
@ -11107,7 +11107,7 @@
{
"uniqueItems": true,
"type": "string",
"description": "name of the Node",
"description": "name of the NodeProxyOptions",
"name": "name",
"in": "path",
"required": true

View File

@ -5704,7 +5704,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Node",
"description": "name of the NodeProxyOptions",
"required": true,
"allowMultiple": false
}
@ -5734,7 +5734,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Node",
"description": "name of the NodeProxyOptions",
"required": true,
"allowMultiple": false
}
@ -5764,7 +5764,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Node",
"description": "name of the NodeProxyOptions",
"required": true,
"allowMultiple": false
}
@ -5794,7 +5794,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Node",
"description": "name of the NodeProxyOptions",
"required": true,
"allowMultiple": false
}
@ -5824,7 +5824,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Node",
"description": "name of the NodeProxyOptions",
"required": true,
"allowMultiple": false
}
@ -5854,7 +5854,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Node",
"description": "name of the NodeProxyOptions",
"required": true,
"allowMultiple": false
}
@ -5884,7 +5884,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Node",
"description": "name of the NodeProxyOptions",
"required": true,
"allowMultiple": false
}
@ -5920,7 +5920,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Node",
"description": "name of the NodeProxyOptions",
"required": true,
"allowMultiple": false
},
@ -5958,7 +5958,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Node",
"description": "name of the NodeProxyOptions",
"required": true,
"allowMultiple": false
},
@ -5996,7 +5996,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Node",
"description": "name of the NodeProxyOptions",
"required": true,
"allowMultiple": false
},
@ -6034,7 +6034,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Node",
"description": "name of the NodeProxyOptions",
"required": true,
"allowMultiple": false
},
@ -6072,7 +6072,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Node",
"description": "name of the NodeProxyOptions",
"required": true,
"allowMultiple": false
},
@ -6110,7 +6110,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Node",
"description": "name of the NodeProxyOptions",
"required": true,
"allowMultiple": false
},
@ -6148,7 +6148,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Node",
"description": "name of the NodeProxyOptions",
"required": true,
"allowMultiple": false
},
@ -9371,7 +9371,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Pod",
"description": "name of the PodAttachOptions",
"required": true,
"allowMultiple": false
}
@ -9441,7 +9441,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Pod",
"description": "name of the PodAttachOptions",
"required": true,
"allowMultiple": false
}
@ -9667,7 +9667,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Pod",
"description": "name of the PodExecOptions",
"required": true,
"allowMultiple": false
}
@ -9745,7 +9745,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Pod",
"description": "name of the PodExecOptions",
"required": true,
"allowMultiple": false
}
@ -9899,7 +9899,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Pod",
"description": "name of the PodPortForwardOptions",
"required": true,
"allowMultiple": false
}
@ -9937,7 +9937,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Pod",
"description": "name of the PodPortForwardOptions",
"required": true,
"allowMultiple": false
}
@ -9981,7 +9981,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Pod",
"description": "name of the PodProxyOptions",
"required": true,
"allowMultiple": false
}
@ -10019,7 +10019,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Pod",
"description": "name of the PodProxyOptions",
"required": true,
"allowMultiple": false
}
@ -10057,7 +10057,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Pod",
"description": "name of the PodProxyOptions",
"required": true,
"allowMultiple": false
}
@ -10095,7 +10095,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Pod",
"description": "name of the PodProxyOptions",
"required": true,
"allowMultiple": false
}
@ -10133,7 +10133,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Pod",
"description": "name of the PodProxyOptions",
"required": true,
"allowMultiple": false
}
@ -10171,7 +10171,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Pod",
"description": "name of the PodProxyOptions",
"required": true,
"allowMultiple": false
}
@ -10209,7 +10209,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Pod",
"description": "name of the PodProxyOptions",
"required": true,
"allowMultiple": false
}
@ -10253,7 +10253,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Pod",
"description": "name of the PodProxyOptions",
"required": true,
"allowMultiple": false
},
@ -10299,7 +10299,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Pod",
"description": "name of the PodProxyOptions",
"required": true,
"allowMultiple": false
},
@ -10345,7 +10345,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Pod",
"description": "name of the PodProxyOptions",
"required": true,
"allowMultiple": false
},
@ -10391,7 +10391,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Pod",
"description": "name of the PodProxyOptions",
"required": true,
"allowMultiple": false
},
@ -10437,7 +10437,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Pod",
"description": "name of the PodProxyOptions",
"required": true,
"allowMultiple": false
},
@ -10483,7 +10483,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Pod",
"description": "name of the PodProxyOptions",
"required": true,
"allowMultiple": false
},
@ -10529,7 +10529,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Pod",
"description": "name of the PodProxyOptions",
"required": true,
"allowMultiple": false
},
@ -17068,7 +17068,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"description": "name of the ServiceProxyOptions",
"required": true,
"allowMultiple": false
}
@ -17106,7 +17106,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"description": "name of the ServiceProxyOptions",
"required": true,
"allowMultiple": false
}
@ -17144,7 +17144,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"description": "name of the ServiceProxyOptions",
"required": true,
"allowMultiple": false
}
@ -17182,7 +17182,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"description": "name of the ServiceProxyOptions",
"required": true,
"allowMultiple": false
}
@ -17220,7 +17220,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"description": "name of the ServiceProxyOptions",
"required": true,
"allowMultiple": false
}
@ -17258,7 +17258,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"description": "name of the ServiceProxyOptions",
"required": true,
"allowMultiple": false
}
@ -17296,7 +17296,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"description": "name of the ServiceProxyOptions",
"required": true,
"allowMultiple": false
}
@ -17340,7 +17340,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"description": "name of the ServiceProxyOptions",
"required": true,
"allowMultiple": false
},
@ -17386,7 +17386,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"description": "name of the ServiceProxyOptions",
"required": true,
"allowMultiple": false
},
@ -17432,7 +17432,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"description": "name of the ServiceProxyOptions",
"required": true,
"allowMultiple": false
},
@ -17478,7 +17478,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"description": "name of the ServiceProxyOptions",
"required": true,
"allowMultiple": false
},
@ -17524,7 +17524,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"description": "name of the ServiceProxyOptions",
"required": true,
"allowMultiple": false
},
@ -17570,7 +17570,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"description": "name of the ServiceProxyOptions",
"required": true,
"allowMultiple": false
},
@ -17616,7 +17616,7 @@
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the Service",
"description": "name of the ServiceProxyOptions",
"required": true,
"allowMultiple": false
},

View File

@ -8617,7 +8617,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Pod</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the PodAttachOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -8762,7 +8762,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Pod</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the PodAttachOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -9189,7 +9189,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Pod</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the PodExecOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -9342,7 +9342,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Pod</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the PodExecOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -9633,7 +9633,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Pod</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the PodPortForwardOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -9746,7 +9746,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Pod</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the PodPortForwardOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -9859,7 +9859,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Pod</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the PodProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -9972,7 +9972,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Pod</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the PodProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -10085,7 +10085,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Pod</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the PodProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -10198,7 +10198,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Pod</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the PodProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -10311,7 +10311,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Pod</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the PodProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -10424,7 +10424,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Pod</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the PodProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -10545,7 +10545,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Pod</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the PodProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -10666,7 +10666,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Pod</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the PodProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -10787,7 +10787,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Pod</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the PodProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -10908,7 +10908,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Pod</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the PodProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -18695,7 +18695,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Service</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the ServiceProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -18808,7 +18808,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Service</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the ServiceProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -18921,7 +18921,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Service</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the ServiceProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -19034,7 +19034,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Service</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the ServiceProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -19147,7 +19147,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Service</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the ServiceProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -19260,7 +19260,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Service</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the ServiceProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -19381,7 +19381,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Service</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the ServiceProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -19502,7 +19502,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Service</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the ServiceProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -19623,7 +19623,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Service</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the ServiceProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -19744,7 +19744,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Service</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the ServiceProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -22252,7 +22252,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Node</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the NodeProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -22357,7 +22357,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Node</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the NodeProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -22462,7 +22462,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Node</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the NodeProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -22567,7 +22567,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Node</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the NodeProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -22672,7 +22672,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Node</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the NodeProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -22777,7 +22777,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Node</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the NodeProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -22890,7 +22890,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Node</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the NodeProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -23003,7 +23003,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Node</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the NodeProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -23116,7 +23116,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Node</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the NodeProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
@ -23229,7 +23229,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">PathParameter</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the Node</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">name of the NodeProxyOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>

View File

@ -45,9 +45,9 @@ var _ = rest.Connecter(&ProxyREST{})
var proxyMethods = []string{"GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"}
// New returns an empty service resource
// New returns an empty nodeProxyOptions object.
func (r *ProxyREST) New() runtime.Object {
return &api.Node{}
return &api.NodeProxyOptions{}
}
// ConnectMethods returns the list of HTTP methods that can be proxied

View File

@ -46,9 +46,9 @@ var _ = rest.Connecter(&ProxyREST{})
var proxyMethods = []string{"GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"}
// New returns an empty pod resource
// New returns an empty podProxyOptions object.
func (r *ProxyREST) New() runtime.Object {
return &api.Pod{}
return &api.PodProxyOptions{}
}
// ConnectMethods returns the list of HTTP methods that can be proxied
@ -88,9 +88,9 @@ type AttachREST struct {
// Implement Connecter
var _ = rest.Connecter(&AttachREST{})
// New creates a new Pod object
// New creates a new podAttachOptions object.
func (r *AttachREST) New() runtime.Object {
return &api.Pod{}
return &api.PodAttachOptions{}
}
// Connect returns a handler for the pod exec proxy
@ -125,9 +125,9 @@ type ExecREST struct {
// Implement Connecter
var _ = rest.Connecter(&ExecREST{})
// New creates a new Pod object
// New creates a new podExecOptions object.
func (r *ExecREST) New() runtime.Object {
return &api.Pod{}
return &api.PodExecOptions{}
}
// Connect returns a handler for the pod exec proxy
@ -162,9 +162,9 @@ type PortForwardREST struct {
// Implement Connecter
var _ = rest.Connecter(&PortForwardREST{})
// New returns an empty pod object
// New returns an empty podPortForwardOptions object
func (r *PortForwardREST) New() runtime.Object {
return &api.Pod{}
return &api.PodPortForwardOptions{}
}
// NewConnectOptions returns the versioned object that represents the

View File

@ -43,7 +43,7 @@ var proxyMethods = []string{"GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OP
// New returns an empty service resource
func (r *ProxyREST) New() runtime.Object {
return &api.Service{}
return &api.ServiceProxyOptions{}
}
// ConnectMethods returns the list of HTTP methods that can be proxied

View File

@ -14,10 +14,8 @@ go_library(
"//pkg/apis/core:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/kubeapiserver/admission:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library",
],
)
@ -31,7 +29,6 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library",
"//staging/src/k8s.io/client-go/testing:go_default_library",
],
)

View File

@ -20,10 +20,8 @@ import (
"fmt"
"io"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/registry/rest"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
@ -94,15 +92,15 @@ func NewDenyExecOnPrivileged() *DenyExec {
// Validate makes an admission decision based on the request attributes
func (d *DenyExec) Validate(a admission.Attributes) (err error) {
connectRequest, ok := a.GetObject().(*rest.ConnectRequest)
if !ok {
return errors.NewBadRequest("a connect request was received, but could not convert the request object.")
path := a.GetResource().Resource
if subresource := a.GetSubresource(); subresource != "" {
path = path + "/" + subresource
}
// Only handle exec or attach requests on pods
if connectRequest.ResourcePath != "pods/exec" && connectRequest.ResourcePath != "pods/attach" {
if path != "pods/exec" && path != "pods/attach" {
return nil
}
pod, err := d.client.Core().Pods(a.GetNamespace()).Get(connectRequest.Name, metav1.GetOptions{})
pod, err := d.client.Core().Pods(a.GetNamespace()).Get(a.GetName(), metav1.GetOptions{})
if err != nil {
return admission.NewForbidden(a, err)
}

View File

@ -22,7 +22,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/registry/rest"
core "k8s.io/client-go/testing"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
@ -122,8 +121,7 @@ func testAdmission(t *testing.T, pod *api.Pod, handler *DenyExec, shouldAccept b
// pods/exec
{
req := &rest.ConnectRequest{Name: pod.Name, ResourcePath: "pods/exec"}
err := handler.Validate(admission.NewAttributesRecord(req, nil, api.Kind("Pod").WithVersion("version"), "test", "name", api.Resource("pods").WithVersion("version"), "exec", admission.Connect, false, nil))
err := handler.Validate(admission.NewAttributesRecord(nil, nil, api.Kind("Pod").WithVersion("version"), "test", pod.Name, api.Resource("pods").WithVersion("version"), "exec", admission.Connect, false, nil))
if shouldAccept && err != nil {
t.Errorf("Unexpected error returned from admission handler: %v", err)
}
@ -134,8 +132,7 @@ func testAdmission(t *testing.T, pod *api.Pod, handler *DenyExec, shouldAccept b
// pods/attach
{
req := &rest.ConnectRequest{Name: pod.Name, ResourcePath: "pods/attach"}
err := handler.Validate(admission.NewAttributesRecord(req, nil, api.Kind("Pod").WithVersion("version"), "test", "name", api.Resource("pods").WithVersion("version"), "attach", admission.Connect, false, nil))
err := handler.Validate(admission.NewAttributesRecord(nil, nil, api.Kind("Pod").WithVersion("version"), "test", pod.Name, api.Resource("pods").WithVersion("version"), "attach", admission.Connect, false, nil))
if shouldAccept && err != nil {
t.Errorf("Unexpected error returned from admission handler: %v", err)
}

View File

@ -120,22 +120,17 @@ func ConnectResource(connecter rest.Connecter, scope RequestScope, admit admissi
return
}
if admit != nil && admit.Handles(admission.Connect) {
connectRequest := &rest.ConnectRequest{
Name: name,
Options: opts,
ResourcePath: restPath,
}
userInfo, _ := request.UserFrom(ctx)
// TODO: remove the mutating admission here as soon as we have ported all plugin that handle CONNECT
if mutatingAdmission, ok := admit.(admission.MutationInterface); ok {
err = mutatingAdmission.Admit(admission.NewAttributesRecord(connectRequest, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Connect, false, userInfo))
err = mutatingAdmission.Admit(admission.NewAttributesRecord(opts, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Connect, false, userInfo))
if err != nil {
scope.err(err, w, req)
return
}
}
if validatingAdmission, ok := admit.(admission.ValidationInterface); ok {
err = validatingAdmission.Validate(admission.NewAttributesRecord(connectRequest, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Connect, false, userInfo))
err = validatingAdmission.Validate(admission.NewAttributesRecord(opts, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Connect, false, userInfo))
if err != nil {
scope.err(err, w, req)
return

View File

@ -29,7 +29,6 @@ go_library(
"rest.go",
"table.go",
"update.go",
"zz_generated.deepcopy.go",
],
importmap = "k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/registry/rest",
importpath = "k8s.io/apiserver/pkg/registry/rest",

View File

@ -334,19 +334,3 @@ type StorageMetadata interface {
// it is not nil. Only the type of the return object matters, the value will be ignored.
ProducesObject(verb string) interface{}
}
// +k8s:deepcopy-gen=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ConnectRequest is an object passed to admission control for Connect operations
type ConnectRequest struct {
// Name is the name of the object on which the connect request was made
Name string
// Options is the options object passed to the connect request. See the NewConnectOptions method on Connecter
Options runtime.Object
// ResourcePath is the path for the resource in the REST server (ie. "pods/proxy")
ResourcePath string
}
func (obj *ConnectRequest) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind }

View File

@ -1,52 +0,0 @@
// +build !ignore_autogenerated
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by deepcopy-gen. DO NOT EDIT.
package rest
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ConnectRequest) DeepCopyInto(out *ConnectRequest) {
*out = *in
if in.Options != nil {
out.Options = in.Options.DeepCopyObject()
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConnectRequest.
func (in *ConnectRequest) DeepCopy() *ConnectRequest {
if in == nil {
return nil
}
out := new(ConnectRequest)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ConnectRequest) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}

View File

@ -52,21 +52,23 @@ const (
roleBindingName = "webhook-auth-reader"
// The webhook configuration names should not be reused between test instances.
crWebhookConfigName = "e2e-test-webhook-config-cr"
webhookConfigName = "e2e-test-webhook-config"
mutatingWebhookConfigName = "e2e-test-mutating-webhook-config"
podMutatingWebhookConfigName = "e2e-test-mutating-webhook-pod"
crMutatingWebhookConfigName = "e2e-test-mutating-webhook-config-cr"
webhookFailClosedConfigName = "e2e-test-webhook-fail-closed"
webhookForWebhooksConfigName = "e2e-test-webhook-for-webhooks-config"
removableValidatingHookName = "e2e-test-should-be-removable-validating-webhook-config"
removableMutatingHookName = "e2e-test-should-be-removable-mutating-webhook-config"
crdWebhookConfigName = "e2e-test-webhook-config-crd"
crWebhookConfigName = "e2e-test-webhook-config-cr"
webhookConfigName = "e2e-test-webhook-config"
attachingPodWebhookConfigName = "e2e-test-webhook-config-attaching-pod"
mutatingWebhookConfigName = "e2e-test-mutating-webhook-config"
podMutatingWebhookConfigName = "e2e-test-mutating-webhook-pod"
crMutatingWebhookConfigName = "e2e-test-mutating-webhook-config-cr"
webhookFailClosedConfigName = "e2e-test-webhook-fail-closed"
webhookForWebhooksConfigName = "e2e-test-webhook-for-webhooks-config"
removableValidatingHookName = "e2e-test-should-be-removable-validating-webhook-config"
removableMutatingHookName = "e2e-test-should-be-removable-mutating-webhook-config"
crdWebhookConfigName = "e2e-test-webhook-config-crd"
skipNamespaceLabelKey = "skip-webhook-admission"
skipNamespaceLabelValue = "yes"
skippedNamespaceName = "exempted-namesapce"
disallowedPodName = "disallowed-pod"
toBeAttachedPodName = "to-be-attached-pod"
hangingPodName = "hanging-pod"
disallowedConfigMapName = "disallowed-configmap"
allowedConfigMapName = "allowed-configmap"
@ -117,6 +119,12 @@ var _ = SIGDescribe("AdmissionWebhook", func() {
testWebhook(f)
})
It("Should be able to deny attaching pod", func() {
webhookCleanup := registerWebhookForAttachingPod(f, context)
defer webhookCleanup()
testAttachingPodWebhook(f)
})
It("Should be able to deny custom resource creation", func() {
testcrd, err := framework.CreateTestCRD(f)
if err != nil {
@ -405,6 +413,53 @@ func registerWebhook(f *framework.Framework, context *certContext) func() {
}
}
func registerWebhookForAttachingPod(f *framework.Framework, context *certContext) func() {
client := f.ClientSet
By("Registering the webhook via the AdmissionRegistration API")
namespace := f.Namespace.Name
configName := attachingPodWebhookConfigName
// A webhook that cannot talk to server, with fail-open policy
failOpenHook := failingWebhook(namespace, "fail-open.k8s.io")
policyIgnore := v1beta1.Ignore
failOpenHook.FailurePolicy = &policyIgnore
_, err := client.AdmissionregistrationV1beta1().ValidatingWebhookConfigurations().Create(&v1beta1.ValidatingWebhookConfiguration{
ObjectMeta: metav1.ObjectMeta{
Name: configName,
},
Webhooks: []v1beta1.Webhook{
{
Name: "deny-attaching-pod.k8s.io",
Rules: []v1beta1.RuleWithOperations{{
Operations: []v1beta1.OperationType{v1beta1.Connect},
Rule: v1beta1.Rule{
APIGroups: []string{""},
APIVersions: []string{"v1"},
Resources: []string{"pods/attach"},
},
}},
ClientConfig: v1beta1.WebhookClientConfig{
Service: &v1beta1.ServiceReference{
Namespace: namespace,
Name: serviceName,
Path: strPtr("/pods/attach"),
},
CABundle: context.signingCert,
},
},
},
})
framework.ExpectNoError(err, "registering webhook config %s with namespace %s", configName, namespace)
// The webhook configuration is honored in 10s.
time.Sleep(10 * time.Second)
return func() {
client.AdmissionregistrationV1beta1().ValidatingWebhookConfigurations().Delete(configName, nil)
}
}
func registerMutatingWebhookForConfigMap(f *framework.Framework, context *certContext) func() {
client := f.ClientSet
By("Registering the mutating configmap webhook via the AdmissionRegistration API")
@ -642,6 +697,21 @@ func testWebhook(f *framework.Framework) {
Expect(err).To(BeNil())
}
func testAttachingPodWebhook(f *framework.Framework) {
By("create a pod")
client := f.ClientSet
pod := toBeAttachedPod(f)
_, err := client.CoreV1().Pods(f.Namespace.Name).Create(pod)
Expect(err).To(BeNil())
By("'kubectl attach' the pod, should be denied by the webhook")
_, err = framework.NewKubectlCommand("attach", fmt.Sprintf("--namespace=%v", f.Namespace.Name), pod.Name, "-i", "-c=container1").Exec()
Expect(err).NotTo(BeNil())
if e, a := "attaching to pod 'to-be-attached-pod' is not allowed", err.Error(); !strings.Contains(a, e) {
framework.Failf("unexpected 'kubectl attach' error message. expected to contain %q, got %q", e, a)
}
}
// failingWebhook returns a webhook with rule of create configmaps,
// but with an invalid client config so that server cannot communicate with it
func failingWebhook(namespace, name string) v1beta1.Webhook {
@ -930,6 +1000,22 @@ func hangingPod(f *framework.Framework) *v1.Pod {
}
}
func toBeAttachedPod(f *framework.Framework) *v1.Pod {
return &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: toBeAttachedPodName,
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "container1",
Image: imageutils.GetPauseImageName(),
},
},
},
}
}
func nonCompliantConfigMap(f *framework.Framework) *v1.ConfigMap {
return &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{

View File

@ -1 +1 @@
1.12v1
1.12v2

View File

@ -60,7 +60,7 @@ func serve(w http.ResponseWriter, r *http.Request, admit admitFunc) {
return
}
glog.V(2).Info(fmt.Sprintf("handling request: %v", body))
glog.V(2).Info(fmt.Sprintf("handling request: %s", body))
// The AdmissionReview that was sent to the webhook
requestedAdmissionReview := v1beta1.AdmissionReview{}
@ -99,6 +99,10 @@ func servePods(w http.ResponseWriter, r *http.Request) {
serve(w, r, admitPods)
}
func serveAttachingPods(w http.ResponseWriter, r *http.Request) {
serve(w, r, denySpecificAttachment)
}
func serveMutatePods(w http.ResponseWriter, r *http.Request) {
serve(w, r, mutatePods)
}
@ -130,6 +134,7 @@ func main() {
http.HandleFunc("/always-deny", serveAlwaysDeny)
http.HandleFunc("/pods", servePods)
http.HandleFunc("/pods/attach", serveAttachingPods)
http.HandleFunc("/mutating-pods", serveMutatePods)
http.HandleFunc("/configmaps", serveConfigmaps)
http.HandleFunc("/mutating-configmaps", serveMutateConfigmaps)

View File

@ -101,3 +101,41 @@ func mutatePods(ar v1beta1.AdmissionReview) *v1beta1.AdmissionResponse {
}
return &reviewResponse
}
// denySpecificAttachment denies `kubectl attach to-be-attached-pod -i -c=container1"
// or equivalent client requests.
func denySpecificAttachment(ar v1beta1.AdmissionReview) *v1beta1.AdmissionResponse {
glog.V(2).Info("handling attaching pods")
if ar.Request.Name != "to-be-attached-pod" {
return &v1beta1.AdmissionResponse{Allowed: true}
}
podResource := metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}
if e, a := podResource, ar.Request.Resource; e != a {
err := fmt.Errorf("expect resource to be %s, got %s", e, a)
glog.Error(err)
return toAdmissionResponse(err)
}
if e, a := "attach", ar.Request.SubResource; e != a {
err := fmt.Errorf("expect subresource to be %s, got %s", e, a)
glog.Error(err)
return toAdmissionResponse(err)
}
raw := ar.Request.Object.Raw
podAttachOptions := corev1.PodAttachOptions{}
deserializer := codecs.UniversalDeserializer()
if _, _, err := deserializer.Decode(raw, nil, &podAttachOptions); err != nil {
glog.Error(err)
return toAdmissionResponse(err)
}
glog.V(2).Info(fmt.Sprintf("podAttachOptions=%#v\n", podAttachOptions))
if !podAttachOptions.Stdin || podAttachOptions.Container != "container1" {
return &v1beta1.AdmissionResponse{Allowed: true}
}
return &v1beta1.AdmissionResponse{
Allowed: false,
Result: &metav1.Status{
Message: "attaching to pod 'to-be-attached-pod' is not allowed",
},
}
}

View File

@ -49,7 +49,7 @@ func (i *ImageConfig) SetVersion(version string) {
}
var (
AdmissionWebhook = ImageConfig{e2eRegistry, "webhook", "1.12v1", false}
AdmissionWebhook = ImageConfig{e2eRegistry, "webhook", "1.12v2", false}
APIServer = ImageConfig{e2eRegistry, "sample-apiserver", "1.0", false}
AppArmorLoader = ImageConfig{gcRegistry, "apparmor-loader", "0.1", false}
BusyBox = ImageConfig{dockerHubRegistry, "busybox", "1.29", false}