diff --git a/api/swagger-spec/api.json b/api/swagger-spec/api.json new file mode 100644 index 00000000000..251994b49cf --- /dev/null +++ b/api/swagger-spec/api.json @@ -0,0 +1,27 @@ +{ + "swaggerVersion": "1.2", + "apiVersion": "", + "basePath": "127.0.0.1:8050", + "resourcePath": "/api", + "apis": [ + { + "path": "/api", + "description": "get available api versions", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "get available api versions", + "nickname": "getApiVersions", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "application/json" + ] + } + ] + } + ] + } \ No newline at end of file diff --git a/api/swagger-spec/resourceListing.json b/api/swagger-spec/resourceListing.json new file mode 100644 index 00000000000..22cee15c893 --- /dev/null +++ b/api/swagger-spec/resourceListing.json @@ -0,0 +1,30 @@ +{ + "swaggerVersion": "1.2", + "apis": [ + { + "path": "/api/v1beta1", + "description": "API at /api/v1beta1 version v1beta1" + }, + { + "path": "/api/v1beta2", + "description": "API at /api/v1beta2 version v1beta2" + }, + { + "path": "/api/v1beta3", + "description": "API at /api/v1beta3 version v1beta3" + }, + { + "path": "/api", + "description": "get available api versions" + }, + { + "path": "/version", + "description": "git code version from which this is built" + } + ], + "apiVersion": "", + "info": { + "title": "", + "description": "" + } + } \ No newline at end of file diff --git a/api/swagger-spec/v1beta1.json b/api/swagger-spec/v1beta1.json new file mode 100644 index 00000000000..d22713500b3 --- /dev/null +++ b/api/swagger-spec/v1beta1.json @@ -0,0 +1,4247 @@ +{ + "swaggerVersion": "1.2", + "apiVersion": "v1beta1", + "basePath": "127.0.0.1:8050", + "resourcePath": "/api/v1beta1", + "apis": [ + { + "path": "/api/v1beta1/services", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.Service", + "method": "GET", + "summary": "list objects of kind Service", + "nickname": "listService", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a Service", + "nickname": "createService", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta1.Service", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/replicationControllers", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.ReplicationControllerList", + "method": "GET", + "summary": "list objects of kind ReplicationController", + "nickname": "listReplicationController", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a ReplicationController", + "nickname": "createReplicationController", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta1.ReplicationController", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/events", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.EventList", + "method": "GET", + "summary": "list objects of kind Event", + "nickname": "listEvent", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a Event", + "nickname": "createEvent", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta1.Event", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/watch/nodes/{name}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.Minion", + "method": "GET", + "summary": "watch a particular Node", + "nickname": "watchNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/redirect/nodes/{name}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "redirect GET request to Node", + "nickname": "redirectNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/proxy/nodes/{name}/{path:*}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "proxy GET requests to Node", + "nickname": "proxyGETNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "proxy PUT requests to Node", + "nickname": "proxyPUTNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "proxy POST requests to Node", + "nickname": "proxyPOSTNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "proxy DELETE requests to Node", + "nickname": "proxyDELETENode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/watch/limitRanges", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.LimitRangeList", + "method": "GET", + "summary": "watch a list of LimitRange", + "nickname": "watchLimitRangelist", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/pods", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.PodList", + "method": "GET", + "summary": "list objects of kind Pod", + "nickname": "listPod", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a Pod", + "nickname": "createPod", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta1.Pod", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/endpoints", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.EndpointsList", + "method": "GET", + "summary": "list objects of kind Endpoints", + "nickname": "listEndpoints", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a Endpoints", + "nickname": "createEndpoints", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta1.Endpoints", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/watch/endpoints", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.EndpointsList", + "method": "GET", + "summary": "watch a list of Endpoints", + "nickname": "watchEndpointslist", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/redirect/minions/{name}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "redirect GET request to Node", + "nickname": "redirectNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/proxy/minions/{name}/{path:*}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "proxy GET requests to Node", + "nickname": "proxyGETNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "proxy PUT requests to Node", + "nickname": "proxyPUTNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "proxy POST requests to Node", + "nickname": "proxyPOSTNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "proxy DELETE requests to Node", + "nickname": "proxyDELETENode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/watch/pods", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.PodList", + "method": "GET", + "summary": "watch a list of Pod", + "nickname": "watchPodlist", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/watch/minions/{name}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.Minion", + "method": "GET", + "summary": "watch a particular Node", + "nickname": "watchNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/watch/events/{name}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.Event", + "method": "GET", + "summary": "watch a particular Event", + "nickname": "watchEvent", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Event", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/pods/{name}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.Pod", + "method": "GET", + "summary": "read the specified Pod", + "nickname": "readPod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "update the specified Pod", + "nickname": "updatePod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta1.Pod", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "delete a Pod", + "nickname": "deletePod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/watch/replicationControllers/{name}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.ReplicationController", + "method": "GET", + "summary": "watch a particular ReplicationController", + "nickname": "watchReplicationController", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ReplicationController", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/endpoints/{name}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.Endpoints", + "method": "GET", + "summary": "read the specified Endpoints", + "nickname": "readEndpoints", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Endpoints", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "update the specified Endpoints", + "nickname": "updateEndpoints", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Endpoints", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta1.Endpoints", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/resourceQuotas", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.ResourceQuotaList", + "method": "GET", + "summary": "list objects of kind ResourceQuota", + "nickname": "listResourceQuota", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a ResourceQuota", + "nickname": "createResourceQuota", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta1.ResourceQuota", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/proxy/pods/{name}/{path:*}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "proxy GET requests to Pod", + "nickname": "proxyGETPod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "proxy PUT requests to Pod", + "nickname": "proxyPUTPod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "proxy POST requests to Pod", + "nickname": "proxyPOSTPod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "proxy DELETE requests to Pod", + "nickname": "proxyDELETEPod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/nodes", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.MinionList", + "method": "GET", + "summary": "list objects of kind Node", + "nickname": "listNode", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a Node", + "nickname": "createNode", + "parameters": [ + { + "type": "v1beta1.Minion", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/watch/limitRanges/{name}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.LimitRange", + "method": "GET", + "summary": "watch a particular LimitRange", + "nickname": "watchLimitRange", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the LimitRange", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/proxy/services/{name}/{path:*}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "proxy GET requests to Service", + "nickname": "proxyGETService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "proxy PUT requests to Service", + "nickname": "proxyPUTService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "proxy POST requests to Service", + "nickname": "proxyPOSTService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "proxy DELETE requests to Service", + "nickname": "proxyDELETEService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/redirect/pods/{name}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "redirect GET request to Pod", + "nickname": "redirectPod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/bindings", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "void", + "method": "POST", + "summary": "create a Binding", + "nickname": "createBinding", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta1.Binding", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/events/{name}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.Event", + "method": "GET", + "summary": "read the specified Event", + "nickname": "readEvent", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Event", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "delete a Event", + "nickname": "deleteEvent", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Event", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/watch/services", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.Service", + "method": "GET", + "summary": "watch a list of Service", + "nickname": "watchServicelist", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/watch/services/{name}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.Service", + "method": "GET", + "summary": "watch a particular Service", + "nickname": "watchService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/nodes/{name}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.Minion", + "method": "GET", + "summary": "read the specified Node", + "nickname": "readNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "update the specified Node", + "nickname": "updateNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + }, + { + "type": "v1beta1.Minion", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "delete a Node", + "nickname": "deleteNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/limitRanges", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.LimitRangeList", + "method": "GET", + "summary": "list objects of kind LimitRange", + "nickname": "listLimitRange", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a LimitRange", + "nickname": "createLimitRange", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta1.LimitRange", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/watch/replicationControllers", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.ReplicationControllerList", + "method": "GET", + "summary": "watch a list of ReplicationController", + "nickname": "watchReplicationControllerlist", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/minions", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.MinionList", + "method": "GET", + "summary": "list objects of kind Node", + "nickname": "listNode", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a Node", + "nickname": "createNode", + "parameters": [ + { + "type": "v1beta1.Minion", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/watch/minions", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.MinionList", + "method": "GET", + "summary": "watch a list of Node", + "nickname": "watchNodelist", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/resourceQuotas/{name}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.ResourceQuota", + "method": "GET", + "summary": "read the specified ResourceQuota", + "nickname": "readResourceQuota", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ResourceQuota", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "update the specified ResourceQuota", + "nickname": "updateResourceQuota", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ResourceQuota", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta1.ResourceQuota", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "delete a ResourceQuota", + "nickname": "deleteResourceQuota", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ResourceQuota", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/services/{name}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.Service", + "method": "GET", + "summary": "read the specified Service", + "nickname": "readService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "update the specified Service", + "nickname": "updateService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta1.Service", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "delete a Service", + "nickname": "deleteService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/minions/{name}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.Minion", + "method": "GET", + "summary": "read the specified Node", + "nickname": "readNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "update the specified Node", + "nickname": "updateNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + }, + { + "type": "v1beta1.Minion", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "delete a Node", + "nickname": "deleteNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/watch/events", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.EventList", + "method": "GET", + "summary": "watch a list of Event", + "nickname": "watchEventlist", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/redirect/services/{name}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "redirect GET request to Service", + "nickname": "redirectService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/limitRanges/{name}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.LimitRange", + "method": "GET", + "summary": "read the specified LimitRange", + "nickname": "readLimitRange", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the LimitRange", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "update the specified LimitRange", + "nickname": "updateLimitRange", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the LimitRange", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta1.LimitRange", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "delete a LimitRange", + "nickname": "deleteLimitRange", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the LimitRange", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/watch/pods/{name}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.Pod", + "method": "GET", + "summary": "watch a particular Pod", + "nickname": "watchPod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/replicationControllers/{name}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.ReplicationController", + "method": "GET", + "summary": "read the specified ReplicationController", + "nickname": "readReplicationController", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ReplicationController", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "update the specified ReplicationController", + "nickname": "updateReplicationController", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ReplicationController", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta1.ReplicationController", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "delete a ReplicationController", + "nickname": "deleteReplicationController", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ReplicationController", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/watch/resourceQuotas", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.ResourceQuotaList", + "method": "GET", + "summary": "watch a list of ResourceQuota", + "nickname": "watchResourceQuotalist", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/watch/resourceQuotas/{name}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.ResourceQuota", + "method": "GET", + "summary": "watch a particular ResourceQuota", + "nickname": "watchResourceQuota", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ResourceQuota", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/resourceQuotaUsages", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "void", + "method": "POST", + "summary": "create a ResourceQuotaUsage", + "nickname": "createResourceQuotaUsage", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta1.ResourceQuotaUsage", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/watch/endpoints/{name}", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.Endpoints", + "method": "GET", + "summary": "watch a particular Endpoints", + "nickname": "watchEndpoints", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Endpoints", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta1/watch/nodes", + "description": "API at /api/v1beta1 version v1beta1", + "operations": [ + { + "type": "v1beta1.MinionList", + "method": "GET", + "summary": "watch a list of Node", + "nickname": "watchNodelist", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + } + ], + "models": { + "v1beta1.Binding": { + "id": "v1beta1.Binding", + "required": [ + "podID", + "host" + ], + "properties": { + "annotations": { + "type": "v1beta1.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "host": { + "type": "string", + "description": "host to which to bind the specified pod" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "podID": { + "type": "string", + "description": "name of the pod to bind" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta1.Capabilities": { + "id": "v1beta1.Capabilities", + "properties": { + "add": { + "type": "array", + "items": [ + { + "$ref": "v1beta1.CapabilityType" + } + ], + "description": "added capabilities" + }, + "drop": { + "type": "array", + "items": [ + { + "$ref": "v1beta1.CapabilityType" + } + ], + "description": "droped capabilities" + } + } + }, + "v1beta1.CapabilityType": { + "id": "v1beta1.CapabilityType", + "properties": {} + }, + "v1beta1.Container": { + "id": "v1beta1.Container", + "required": [ + "name", + "image", + "imagePullPolicy" + ], + "properties": { + "capabilities": { + "type": "v1beta1.Capabilities", + "description": "capabilities for container" + }, + "command": { + "type": "array", + "items": [ + { + "$ref": "string" + } + ], + "description": "command argv array; not executed within a shell; defaults to entrypoint or command in the image" + }, + "cpu": { + "type": "integer", + "format": "int32", + "description": "CPU share in thousandths of a core" + }, + "env": { + "type": "array", + "items": [ + { + "$ref": "v1beta1.EnvVar" + } + ], + "description": "list of environment variables to set in the container" + }, + "image": { + "type": "string", + "description": "Docker image name" + }, + "imagePullPolicy": { + "type": "v1beta1.PullPolicy", + "description": "image pull policy; one of PullAlways, PullNever, PullIfNotPresent; defaults to PullAlways if :latest tag is specified, or PullIfNotPresent otherwise" + }, + "lifecycle": { + "type": "v1beta1.Lifecycle", + "description": "actions that the management system should take in response to container lifecycle events" + }, + "livenessProbe": { + "type": "v1beta1.LivenessProbe", + "description": "periodic probe of container liveness; container will be restarted if the probe fails" + }, + "memory": { + "type": "integer", + "format": "int64", + "description": "memory limit in bytes; defaults to unlimited" + }, + "name": { + "type": "string", + "description": "name of the container; must be a DNS_LABEL and unique within the pod" + }, + "ports": { + "type": "array", + "items": [ + { + "$ref": "v1beta1.Port" + } + ], + "description": "list of ports to expose from the container" + }, + "privileged": { + "type": "boolean", + "description": "whether or not the container is granted privileged status; defaults to false" + }, + "resources": { + "type": "v1beta1.ResourceRequirementSpec", + "description": "Compute Resources required by this container" + }, + "terminationMessagePath": { + "type": "string", + "description": "path at which the file to which the container's termination message will be written is mounted into the container's filesystem; message written is intended to be brief final status, such as an assertion failure message; defaults to /dev/termination-log" + }, + "volumeMounts": { + "type": "array", + "items": [ + { + "$ref": "v1beta1.VolumeMount" + } + ], + "description": "pod volumes to mount into the container's filesystem" + }, + "workingDir": { + "type": "string", + "description": "container's working directory; defaults to image's default" + } + } + }, + "v1beta1.ContainerManifest": { + "id": "v1beta1.ContainerManifest", + "required": [ + "version", + "id", + "volumes", + "containers" + ], + "properties": { + "containers": { + "type": "array", + "items": [ + { + "$ref": "v1beta1.Container" + } + ], + "description": "list of containers belonging to the pod" + }, + "dnsPolicy": { + "type": "v1beta1.DNSPolicy", + "description": "DNS policy for containers within the pod; one of 'ClusterFirst' or 'Default'" + }, + "id": { + "type": "string", + "description": "manifest name; must be a DNS_SUBDOMAIN" + }, + "restartPolicy": { + "type": "v1beta1.RestartPolicy", + "description": "restart policy for all containers within the pod; one of RestartPolicyAlways, RestartPolicyOnFailure, RestartPolicyNever" + }, + "uuid": { + "type": "types.UID", + "description": "manifest UUID" + }, + "version": { + "type": "string", + "description": "manifest version; must be v1beta1" + }, + "volumes": { + "type": "array", + "items": [ + { + "$ref": "v1beta1.Volume" + } + ], + "description": "list of volumes that can be mounted by containers belonging to the pod" + } + } + }, + "v1beta1.EmptyDir": { + "id": "v1beta1.EmptyDir", + "properties": {} + }, + "v1beta1.Endpoints": { + "id": "v1beta1.Endpoints", + "properties": { + "annotations": { + "type": "v1beta1.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "endpoints": { + "type": "array", + "items": [ + { + "$ref": "string" + } + ], + "description": "list of endpoints corresponding to a service, of the form address:port, such as 10.10.1.1:1909" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta1.EndpointsList": { + "id": "v1beta1.EndpointsList", + "required": [ + "items" + ], + "properties": { + "annotations": { + "type": "v1beta1.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "items": { + "type": "array", + "items": [ + { + "$ref": "v1beta1.Endpoints" + } + ], + "description": "list of service endpoint lists" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta1.EnvVar": { + "id": "v1beta1.EnvVar", + "required": [ + "name" + ], + "properties": { + "key": { + "type": "string", + "description": "name of the environment variable; must be a C_IDENTIFIER; deprecated - use name instead" + }, + "name": { + "type": "string", + "description": "name of the environment variable; must be a C_IDENTIFIER" + }, + "value": { + "type": "string", + "description": "value of the environment variable; defaults to empty string" + } + } + }, + "v1beta1.Event": { + "id": "v1beta1.Event", + "properties": { + "annotations": { + "type": "v1beta1.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "host": { + "type": "string", + "description": "host name on which this event was generated" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "involvedObject": { + "type": "v1beta1.ObjectReference", + "description": "object that this event is about" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "message": { + "type": "string", + "description": "human-readable description of the status of this operation" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "reason": { + "type": "string", + "description": "short, machine understandable string that gives the reason for the transition into the object's current status" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "source": { + "type": "string", + "description": "component reporting this event; short machine understandable string" + }, + "status": { + "type": "string", + "description": "short, machine understandable string that describes the current status of the referred object" + }, + "timestamp": { + "type": "string", + "description": "time at which the client recorded the event" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta1.EventList": { + "id": "v1beta1.EventList", + "required": [ + "items" + ], + "properties": { + "annotations": { + "type": "v1beta1.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "items": { + "type": "array", + "items": [ + { + "$ref": "v1beta1.Event" + } + ], + "description": "list of events" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta1.ExecAction": { + "id": "v1beta1.ExecAction", + "properties": { + "command": { + "type": "array", + "items": [ + { + "$ref": "string" + } + ], + "description": "command line to execute inside the container; working directory for the command is root ('/') in the container's file system; the command is exec'd, not run inside a shell; exit status of 0 is treated as live/healthy and non-zero is unhealthy" + } + } + }, + "v1beta1.GCEPersistentDisk": { + "id": "v1beta1.GCEPersistentDisk", + "required": [ + "pdName" + ], + "properties": { + "fsType": { + "type": "string", + "description": "file system type to mount, such as ext4, xfs, ntfs" + }, + "partition": { + "type": "integer", + "format": "int32", + "description": "partition on the disk to mount (e.g., '1' for /dev/sda1); if omitted the plain device name (e.g., /dev/sda) will be mounted" + }, + "pdName": { + "type": "string", + "description": "unique name of the PD resource in GCE" + }, + "readOnly": { + "type": "boolean", + "description": "read-only if true, read-write otherwise (false or unspecified)" + } + } + }, + "v1beta1.GitRepo": { + "id": "v1beta1.GitRepo", + "required": [ + "repository", + "revision" + ], + "properties": { + "repository": { + "type": "string", + "description": "repository URL" + }, + "revision": { + "type": "string", + "description": "commit hash for the specified revision" + } + } + }, + "v1beta1.HTTPGetAction": { + "id": "v1beta1.HTTPGetAction", + "properties": { + "host": { + "type": "string", + "description": "hostname to connect to; defaults to pod IP" + }, + "path": { + "type": "string", + "description": "path to access on the HTTP server" + }, + "port": { + "type": "string", + "description": "number or name of the port to access on the container" + } + } + }, + "v1beta1.Handler": { + "id": "v1beta1.Handler", + "properties": { + "exec": { + "type": "v1beta1.ExecAction", + "description": "exec-based handler" + }, + "httpGet": { + "type": "v1beta1.HTTPGetAction", + "description": "HTTP-based handler" + }, + "tcpSocket": { + "type": "v1beta1.TCPSocketAction", + "description": "TCP-based handler; TCP hooks not yet supported" + } + } + }, + "v1beta1.HostPath": { + "id": "v1beta1.HostPath", + "required": [ + "path" + ], + "properties": { + "path": { + "type": "string", + "description": "path of the directory on the host" + } + } + }, + "v1beta1.Lifecycle": { + "id": "v1beta1.Lifecycle", + "properties": { + "postStart": { + "type": "v1beta1.Handler", + "description": "called immediately after a container is started; if the handler fails, the container is terminated and restarted according to its restart policy; other management of the container blocks until the hook completes" + }, + "preStop": { + "type": "v1beta1.Handler", + "description": "called before a container is terminated; the container is terminated after the handler completes; other management of the container blocks until the hook completes" + } + } + }, + "v1beta1.LimitRange": { + "id": "v1beta1.LimitRange", + "properties": { + "annotations": { + "type": "v1beta1.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "spec": { + "type": "v1beta1.LimitRangeSpec" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta1.LimitRangeItem": { + "id": "v1beta1.LimitRangeItem", + "properties": { + "max": { + "type": "v1beta1.ResourceList" + }, + "min": { + "type": "v1beta1.ResourceList" + }, + "type": { + "type": "v1beta1.LimitType" + } + } + }, + "v1beta1.LimitRangeList": { + "id": "v1beta1.LimitRangeList", + "required": [ + "items" + ], + "properties": { + "annotations": { + "type": "v1beta1.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "items": { + "type": "array", + "items": [ + { + "$ref": "v1beta1.LimitRange" + } + ] + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta1.LimitRangeSpec": { + "id": "v1beta1.LimitRangeSpec", + "required": [ + "limits" + ], + "properties": { + "limits": { + "type": "array", + "items": [ + { + "$ref": "v1beta1.LimitRangeItem" + } + ] + } + } + }, + "v1beta1.LivenessProbe": { + "id": "v1beta1.LivenessProbe", + "properties": { + "exec": { + "type": "v1beta1.ExecAction", + "description": "parameters for exec-based liveness probe" + }, + "httpGet": { + "type": "v1beta1.HTTPGetAction", + "description": "parameters for HTTP-based liveness probe" + }, + "initialDelaySeconds": { + "type": "integer", + "format": "int64", + "description": "number of seconds after the container has started before liveness probes are initiated" + }, + "tcpSocket": { + "type": "v1beta1.TCPSocketAction", + "description": "parameters for TCP-based liveness probe" + } + } + }, + "v1beta1.Minion": { + "id": "v1beta1.Minion", + "properties": { + "annotations": { + "type": "v1beta1.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "hostIP": { + "type": "string", + "description": "IP address of the node" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "labels": { + "type": "v1beta1.Minion.labels", + "description": "map of string keys and values that can be used to organize and categorize minions; labels of a minion assigned by the scheduler must match the scheduled pod's nodeSelector" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "resources": { + "type": "v1beta1.NodeResources", + "description": "characterization of node resources" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "status": { + "type": "v1beta1.NodeStatus", + "description": "current status of node" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta1.Minion.labels": { + "id": "v1beta1.Minion.labels", + "properties": {} + }, + "v1beta1.MinionList": { + "id": "v1beta1.MinionList", + "required": [ + "items" + ], + "properties": { + "annotations": { + "type": "v1beta1.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "items": { + "type": "array", + "items": [ + { + "$ref": "v1beta1.Minion" + } + ], + "description": "list of nodes" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "minions": { + "type": "array", + "items": [ + { + "$ref": "v1beta1.Minion" + } + ], + "description": "list of nodes; deprecated" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta1.NodeCondition": { + "id": "v1beta1.NodeCondition", + "required": [ + "kind", + "status" + ], + "properties": { + "kind": { + "type": "v1beta1.NodeConditionKind", + "description": "kind of the condition, one of reachable, ready" + }, + "lastTransitionTime": { + "type": "string", + "description": "last time the condition transit from one status to another" + }, + "message": { + "type": "string", + "description": "human readable message indicating details about last transition" + }, + "reason": { + "type": "string", + "description": "(brief) reason for the condition's last transition" + }, + "status": { + "type": "v1beta1.NodeConditionStatus", + "description": "status of the condition, one of full, none, unknown" + } + } + }, + "v1beta1.NodeResources": { + "id": "v1beta1.NodeResources", + "properties": { + "capacity": { + "type": "v1beta1.ResourceList", + "description": "resource capacity of a node represented as a map of resource name to quantity of resource" + } + } + }, + "v1beta1.NodeStatus": { + "id": "v1beta1.NodeStatus", + "properties": { + "conditions": { + "type": "array", + "items": [ + { + "$ref": "v1beta1.NodeCondition" + } + ], + "description": "conditions is an array of current node conditions" + }, + "phase": { + "type": "v1beta1.NodePhase", + "description": "node phase is the current lifecycle phase of the node" + } + } + }, + "v1beta1.ObjectReference": { + "id": "v1beta1.ObjectReference", + "properties": { + "apiVersion": { + "type": "string", + "description": "API version of the referent" + }, + "fieldPath": { + "type": "string", + "description": "if referring to a piece of an object instead of an entire object, this string should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]" + }, + "kind": { + "type": "string", + "description": "kind of the referent" + }, + "name": { + "type": "string", + "description": "id of the referent" + }, + "namespace": { + "type": "string", + "description": "namespace of the referent" + }, + "resourceVersion": { + "type": "string", + "description": "specific resourceVersion to which this reference is made, if any" + }, + "uid": { + "type": "types.UID", + "description": "uid of the referent" + } + } + }, + "v1beta1.Pod": { + "id": "v1beta1.Pod", + "properties": { + "annotations": { + "type": "v1beta1.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "currentState": { + "type": "v1beta1.PodState", + "description": "current state of the pod" + }, + "desiredState": { + "type": "v1beta1.PodState", + "description": "specification of the desired state of the pod" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "labels": { + "type": "v1beta1.Pod.labels", + "description": "map of string keys and values that can be used to organize and categorize pods; may match selectors of replication controllers and services" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "nodeSelector": { + "type": "v1beta1.Pod.nodeSelector", + "description": "selector which must match a node's labels for the pod to be scheduled on that node" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta1.Pod.labels": { + "id": "v1beta1.Pod.labels", + "properties": {} + }, + "v1beta1.Pod.nodeSelector": { + "id": "v1beta1.Pod.nodeSelector", + "properties": {} + }, + "v1beta1.PodList": { + "id": "v1beta1.PodList", + "required": [ + "items" + ], + "properties": { + "annotations": { + "type": "v1beta1.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "items": { + "type": "array", + "items": [ + { + "$ref": "v1beta1.Pod" + } + ], + "description": "list of pods" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta1.PodState": { + "id": "v1beta1.PodState", + "properties": { + "host": { + "type": "string", + "description": "host to which the pod is assigned; empty if not yet scheduled" + }, + "hostIP": { + "type": "string", + "description": "IP address of the host to which the pod is assigned; empty if not yet scheduled" + }, + "info": { + "type": "v1beta1.PodInfo", + "description": "map of container name to container status" + }, + "manifest": { + "type": "v1beta1.ContainerManifest", + "description": "manifest of containers and volumes comprising the pod" + }, + "message": { + "type": "string", + "description": "human readable message indicating details about why the pod is in this condition" + }, + "podIP": { + "type": "string", + "description": "IP address allocated to the pod; routable at least within the cluster; empty if not yet allocated" + }, + "status": { + "type": "v1beta1.PodStatus", + "description": "current condition of the pod, Waiting, Running, or Terminated" + } + } + }, + "v1beta1.PodTemplate": { + "id": "v1beta1.PodTemplate", + "properties": { + "annotations": { + "type": "v1beta1.PodTemplate.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about pods created from the template" + }, + "desiredState": { + "type": "v1beta1.PodState", + "description": "specification of the desired state of pods created from this template" + }, + "labels": { + "type": "v1beta1.PodTemplate.labels", + "description": "map of string keys and values that can be used to organize and categorize the pods created from the template; must match the selector of the replication controller to which the template belongs; may match selectors of services" + }, + "nodeSelector": { + "type": "v1beta1.PodTemplate.nodeSelector", + "description": "a selector which must be true for the pod to fit on a node" + } + } + }, + "v1beta1.PodTemplate.annotations": { + "id": "v1beta1.PodTemplate.annotations", + "properties": {} + }, + "v1beta1.PodTemplate.labels": { + "id": "v1beta1.PodTemplate.labels", + "properties": {} + }, + "v1beta1.PodTemplate.nodeSelector": { + "id": "v1beta1.PodTemplate.nodeSelector", + "properties": {} + }, + "v1beta1.Port": { + "id": "v1beta1.Port", + "required": [ + "containerPort" + ], + "properties": { + "containerPort": { + "type": "integer", + "format": "int32", + "description": "number of port to expose on the pod's IP address" + }, + "hostIP": { + "type": "string", + "description": "host IP to bind the port to" + }, + "hostPort": { + "type": "integer", + "format": "int32", + "description": "number of port to expose on the host; most containers do not need this" + }, + "name": { + "type": "string", + "description": "name for the port that can be referred to by services; must be a DNS_LABEL and unique without the pod" + }, + "protocol": { + "type": "v1beta1.Protocol", + "description": "protocol for port; must be UDP or TCP; TCP if unspecified" + } + } + }, + "v1beta1.ReplicationController": { + "id": "v1beta1.ReplicationController", + "properties": { + "annotations": { + "type": "v1beta1.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "currentState": { + "type": "v1beta1.ReplicationControllerState", + "description": "current state of the replication controller" + }, + "desiredState": { + "type": "v1beta1.ReplicationControllerState", + "description": "specification of the desired state of the replication controller" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "labels": { + "type": "v1beta1.ReplicationController.labels", + "description": "map of string keys and values that can be used to organize and categorize replication controllers" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta1.ReplicationController.labels": { + "id": "v1beta1.ReplicationController.labels", + "properties": {} + }, + "v1beta1.ReplicationControllerList": { + "id": "v1beta1.ReplicationControllerList", + "required": [ + "items" + ], + "properties": { + "annotations": { + "type": "v1beta1.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "items": { + "type": "array", + "items": [ + { + "$ref": "v1beta1.ReplicationController" + } + ], + "description": "list of replication controllers" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta1.ReplicationControllerState": { + "id": "v1beta1.ReplicationControllerState", + "required": [ + "replicas" + ], + "properties": { + "podTemplate": { + "type": "v1beta1.PodTemplate", + "description": "template for pods to be created by this replication controller when the observed number of replicas is less than the desired number of replicas" + }, + "replicaSelector": { + "type": "v1beta1.ReplicationControllerState.replicaSelector", + "description": "label keys and values that must match in order to be controlled by this replication controller" + }, + "replicas": { + "type": "integer", + "format": "int32", + "description": "number of replicas (desired or observed, as appropriate)" + } + } + }, + "v1beta1.ReplicationControllerState.replicaSelector": { + "id": "v1beta1.ReplicationControllerState.replicaSelector", + "properties": {} + }, + "v1beta1.ResourceQuota": { + "id": "v1beta1.ResourceQuota", + "properties": { + "annotations": { + "type": "v1beta1.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "spec": { + "type": "v1beta1.ResourceQuotaSpec" + }, + "status": { + "type": "v1beta1.ResourceQuotaStatus" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta1.ResourceQuotaList": { + "id": "v1beta1.ResourceQuotaList", + "required": [ + "items" + ], + "properties": { + "annotations": { + "type": "v1beta1.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "items": { + "type": "array", + "items": [ + { + "$ref": "v1beta1.ResourceQuota" + } + ] + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta1.ResourceQuotaSpec": { + "id": "v1beta1.ResourceQuotaSpec", + "properties": { + "hard": { + "type": "v1beta1.ResourceList" + } + } + }, + "v1beta1.ResourceQuotaStatus": { + "id": "v1beta1.ResourceQuotaStatus", + "properties": { + "hard": { + "type": "v1beta1.ResourceList" + }, + "used": { + "type": "v1beta1.ResourceList" + } + } + }, + "v1beta1.ResourceQuotaUsage": { + "id": "v1beta1.ResourceQuotaUsage", + "properties": { + "annotations": { + "type": "v1beta1.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "status": { + "type": "v1beta1.ResourceQuotaStatus" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta1.ResourceRequirementSpec": { + "id": "v1beta1.ResourceRequirementSpec", + "properties": { + "limits": { + "type": "v1beta1.ResourceList", + "description": "Maximum amount of compute resources allowed" + } + } + }, + "v1beta1.RestartPolicy": { + "id": "v1beta1.RestartPolicy", + "properties": { + "always": { + "type": "v1beta1.RestartPolicyAlways", + "description": "always restart the container after termination" + }, + "never": { + "type": "v1beta1.RestartPolicyNever", + "description": "never restart the container" + }, + "onFailure": { + "type": "v1beta1.RestartPolicyOnFailure", + "description": "restart the container if it fails for any reason, but not if it succeeds (exit 0)" + } + } + }, + "v1beta1.RestartPolicyAlways": { + "id": "v1beta1.RestartPolicyAlways", + "properties": {} + }, + "v1beta1.RestartPolicyNever": { + "id": "v1beta1.RestartPolicyNever", + "properties": {} + }, + "v1beta1.RestartPolicyOnFailure": { + "id": "v1beta1.RestartPolicyOnFailure", + "properties": {} + }, + "v1beta1.Service": { + "id": "v1beta1.Service", + "required": [ + "port", + "selector" + ], + "properties": { + "annotations": { + "type": "v1beta1.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "containerPort": { + "type": "string", + "description": "number or name of the port to access on the containers belonging to pods targeted by the service" + }, + "createExternalLoadBalancer": { + "type": "boolean", + "description": "set up a cloud-provider-specific load balancer on an external IP" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "labels": { + "type": "v1beta1.Service.labels", + "description": "map of string keys and values that can be used to organize and categorize services" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "port": { + "type": "integer", + "format": "int32", + "description": "port exposed by the service" + }, + "portalIP": { + "type": "string", + "description": "IP address of the service; usually assigned by the system; if specified, it will be allocated to the service if unused, and creation of the service will fail otherwise; cannot be updated" + }, + "protocol": { + "type": "v1beta1.Protocol", + "description": "protocol for port; must be UDP or TCP; TCP if unspecified" + }, + "proxyPort": { + "type": "integer", + "format": "int32", + "description": "if non-zero, a pre-allocated host port used for this service by the proxy on each node; assigned by the master and ignored on input" + }, + "publicIPs": { + "type": "array", + "items": [ + { + "$ref": "string" + } + ], + "description": "externally visible IPs from which to select the address for the external load balancer" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selector": { + "type": "v1beta1.Service.selector", + "description": "label keys and values that must match in order to receive traffic for this service; if empty, all pods are selected, if not specified, endpoints must be manually specified" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "sessionAffinity": { + "type": "v1beta1.AffinityType", + "description": "enable client IP based session affinity; must be ClientIP or None; defaults to None" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta1.Service.labels": { + "id": "v1beta1.Service.labels", + "properties": {} + }, + "v1beta1.Service.selector": { + "id": "v1beta1.Service.selector", + "properties": {} + }, + "v1beta1.TCPSocketAction": { + "id": "v1beta1.TCPSocketAction", + "properties": { + "port": { + "type": "string", + "description": "number of name of the port to access on the container" + } + } + }, + "v1beta1.Volume": { + "id": "v1beta1.Volume", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "description": "volume name; must be a DNS_LABEL and unique within the pod" + }, + "source": { + "type": "v1beta1.VolumeSource", + "description": "location and type of volume to mount; at most one of HostDir, EmptyDir, GCEPersistentDisk, or GitRepo; default is EmptyDir" + } + } + }, + "v1beta1.VolumeMount": { + "id": "v1beta1.VolumeMount", + "required": [ + "name", + "mountPath" + ], + "properties": { + "mountPath": { + "type": "string", + "description": "path within the container at which the volume should be mounted; overrides path" + }, + "mountType": { + "type": "string", + "description": "LOCAL or HOST; defaults to LOCAL; deprecated" + }, + "name": { + "type": "string", + "description": "name of the volume to mount" + }, + "path": { + "type": "string", + "description": "path within the container at which the volume should be mounted; deprecated" + }, + "readOnly": { + "type": "boolean", + "description": "mounted read-only if true, read-write otherwise (false or unspecified)" + } + } + }, + "v1beta1.VolumeSource": { + "id": "v1beta1.VolumeSource", + "required": [ + "hostDir", + "emptyDir", + "persistentDisk", + "gitRepo" + ], + "properties": { + "emptyDir": { + "type": "v1beta1.EmptyDir", + "description": "temporary directory that shares a pod's lifetime" + }, + "gitRepo": { + "type": "v1beta1.GitRepo", + "description": "git repository at a particular revision" + }, + "hostDir": { + "type": "v1beta1.HostPath", + "description": "pre-existing host file or directory; generally for privileged system daemons or other agents tied to the host" + }, + "persistentDisk": { + "type": "v1beta1.GCEPersistentDisk", + "description": "GCE disk resource attached to the host machine on demand" + } + } + } + } + } \ No newline at end of file diff --git a/api/swagger-spec/v1beta2.json b/api/swagger-spec/v1beta2.json new file mode 100644 index 00000000000..d3664433f4b --- /dev/null +++ b/api/swagger-spec/v1beta2.json @@ -0,0 +1,4226 @@ +{ + "swaggerVersion": "1.2", + "apiVersion": "v1beta2", + "basePath": "127.0.0.1:8050", + "resourcePath": "/api/v1beta2", + "apis": [ + { + "path": "/api/v1beta2/watch/endpoints", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.EndpointsList", + "method": "GET", + "summary": "watch a list of Endpoints", + "nickname": "watchEndpointslist", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/pods/{name}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.Pod", + "method": "GET", + "summary": "read the specified Pod", + "nickname": "readPod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "update the specified Pod", + "nickname": "updatePod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta2.Pod", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "delete a Pod", + "nickname": "deletePod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/redirect/pods/{name}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "redirect GET request to Pod", + "nickname": "redirectPod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/minions/{name}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.Minion", + "method": "GET", + "summary": "read the specified Node", + "nickname": "readNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "update the specified Node", + "nickname": "updateNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + }, + { + "type": "v1beta2.Minion", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "delete a Node", + "nickname": "deleteNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/watch/services/{name}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.Service", + "method": "GET", + "summary": "watch a particular Service", + "nickname": "watchService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/limitRanges", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.LimitRangeList", + "method": "GET", + "summary": "list objects of kind LimitRange", + "nickname": "listLimitRange", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a LimitRange", + "nickname": "createLimitRange", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta2.LimitRange", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/watch/limitRanges", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.LimitRangeList", + "method": "GET", + "summary": "watch a list of LimitRange", + "nickname": "watchLimitRangelist", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/resourceQuotas", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.ResourceQuotaList", + "method": "GET", + "summary": "list objects of kind ResourceQuota", + "nickname": "listResourceQuota", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a ResourceQuota", + "nickname": "createResourceQuota", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta2.ResourceQuota", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/watch/resourceQuotas/{name}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.ResourceQuota", + "method": "GET", + "summary": "watch a particular ResourceQuota", + "nickname": "watchResourceQuota", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ResourceQuota", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/redirect/minions/{name}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "redirect GET request to Node", + "nickname": "redirectNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/redirect/services/{name}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "redirect GET request to Service", + "nickname": "redirectService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/redirect/nodes/{name}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "redirect GET request to Node", + "nickname": "redirectNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/proxy/nodes/{name}/{path:*}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "proxy GET requests to Node", + "nickname": "proxyGETNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "proxy PUT requests to Node", + "nickname": "proxyPUTNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "proxy POST requests to Node", + "nickname": "proxyPOSTNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "proxy DELETE requests to Node", + "nickname": "proxyDELETENode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/replicationControllers", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.ReplicationControllerList", + "method": "GET", + "summary": "list objects of kind ReplicationController", + "nickname": "listReplicationController", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a ReplicationController", + "nickname": "createReplicationController", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta2.ReplicationController", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/limitRanges/{name}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.LimitRange", + "method": "GET", + "summary": "read the specified LimitRange", + "nickname": "readLimitRange", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the LimitRange", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "update the specified LimitRange", + "nickname": "updateLimitRange", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the LimitRange", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta2.LimitRange", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "delete a LimitRange", + "nickname": "deleteLimitRange", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the LimitRange", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/bindings", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "void", + "method": "POST", + "summary": "create a Binding", + "nickname": "createBinding", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta2.Binding", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/watch/minions/{name}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.Minion", + "method": "GET", + "summary": "watch a particular Node", + "nickname": "watchNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/watch/events", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.EventList", + "method": "GET", + "summary": "watch a list of Event", + "nickname": "watchEventlist", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/events/{name}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.Event", + "method": "GET", + "summary": "read the specified Event", + "nickname": "readEvent", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Event", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "delete a Event", + "nickname": "deleteEvent", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Event", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/services", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.Service", + "method": "GET", + "summary": "list objects of kind Service", + "nickname": "listService", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a Service", + "nickname": "createService", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta2.Service", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/replicationControllers/{name}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.ReplicationController", + "method": "GET", + "summary": "read the specified ReplicationController", + "nickname": "readReplicationController", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ReplicationController", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "update the specified ReplicationController", + "nickname": "updateReplicationController", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ReplicationController", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta2.ReplicationController", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "delete a ReplicationController", + "nickname": "deleteReplicationController", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ReplicationController", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/resourceQuotas/{name}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.ResourceQuota", + "method": "GET", + "summary": "read the specified ResourceQuota", + "nickname": "readResourceQuota", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ResourceQuota", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "update the specified ResourceQuota", + "nickname": "updateResourceQuota", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ResourceQuota", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta2.ResourceQuota", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "delete a ResourceQuota", + "nickname": "deleteResourceQuota", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ResourceQuota", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/pods", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.PodList", + "method": "GET", + "summary": "list objects of kind Pod", + "nickname": "listPod", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a Pod", + "nickname": "createPod", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta2.Pod", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/proxy/minions/{name}/{path:*}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "proxy GET requests to Node", + "nickname": "proxyGETNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "proxy PUT requests to Node", + "nickname": "proxyPUTNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "proxy POST requests to Node", + "nickname": "proxyPOSTNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "proxy DELETE requests to Node", + "nickname": "proxyDELETENode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/endpoints", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.EndpointsList", + "method": "GET", + "summary": "list objects of kind Endpoints", + "nickname": "listEndpoints", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a Endpoints", + "nickname": "createEndpoints", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta2.Endpoints", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/watch/nodes/{name}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.Minion", + "method": "GET", + "summary": "watch a particular Node", + "nickname": "watchNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/watch/replicationControllers", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.ReplicationControllerList", + "method": "GET", + "summary": "watch a list of ReplicationController", + "nickname": "watchReplicationControllerlist", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/watch/resourceQuotas", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.ResourceQuotaList", + "method": "GET", + "summary": "watch a list of ResourceQuota", + "nickname": "watchResourceQuotalist", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/watch/limitRanges/{name}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.LimitRange", + "method": "GET", + "summary": "watch a particular LimitRange", + "nickname": "watchLimitRange", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the LimitRange", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/minions", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.MinionList", + "method": "GET", + "summary": "list objects of kind Node", + "nickname": "listNode", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a Node", + "nickname": "createNode", + "parameters": [ + { + "type": "v1beta2.Minion", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/proxy/services/{name}/{path:*}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "proxy GET requests to Service", + "nickname": "proxyGETService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "proxy PUT requests to Service", + "nickname": "proxyPUTService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "proxy POST requests to Service", + "nickname": "proxyPOSTService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "proxy DELETE requests to Service", + "nickname": "proxyDELETEService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/nodes", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.MinionList", + "method": "GET", + "summary": "list objects of kind Node", + "nickname": "listNode", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a Node", + "nickname": "createNode", + "parameters": [ + { + "type": "v1beta2.Minion", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/nodes/{name}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.Minion", + "method": "GET", + "summary": "read the specified Node", + "nickname": "readNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "update the specified Node", + "nickname": "updateNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + }, + { + "type": "v1beta2.Minion", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "delete a Node", + "nickname": "deleteNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/watch/nodes", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.MinionList", + "method": "GET", + "summary": "watch a list of Node", + "nickname": "watchNodelist", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/watch/replicationControllers/{name}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.ReplicationController", + "method": "GET", + "summary": "watch a particular ReplicationController", + "nickname": "watchReplicationController", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ReplicationController", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/watch/pods/{name}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.Pod", + "method": "GET", + "summary": "watch a particular Pod", + "nickname": "watchPod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/proxy/pods/{name}/{path:*}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "proxy GET requests to Pod", + "nickname": "proxyGETPod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "proxy PUT requests to Pod", + "nickname": "proxyPUTPod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "proxy POST requests to Pod", + "nickname": "proxyPOSTPod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "proxy DELETE requests to Pod", + "nickname": "proxyDELETEPod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/watch/minions", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.MinionList", + "method": "GET", + "summary": "watch a list of Node", + "nickname": "watchNodelist", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/watch/services", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.Service", + "method": "GET", + "summary": "watch a list of Service", + "nickname": "watchServicelist", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/services/{name}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.Service", + "method": "GET", + "summary": "read the specified Service", + "nickname": "readService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "update the specified Service", + "nickname": "updateService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta2.Service", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "delete a Service", + "nickname": "deleteService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/endpoints/{name}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.Endpoints", + "method": "GET", + "summary": "read the specified Endpoints", + "nickname": "readEndpoints", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Endpoints", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "update the specified Endpoints", + "nickname": "updateEndpoints", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Endpoints", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta2.Endpoints", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/watch/pods", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.PodList", + "method": "GET", + "summary": "watch a list of Pod", + "nickname": "watchPodlist", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/events", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.EventList", + "method": "GET", + "summary": "list objects of kind Event", + "nickname": "listEvent", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a Event", + "nickname": "createEvent", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta2.Event", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/watch/events/{name}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.Event", + "method": "GET", + "summary": "watch a particular Event", + "nickname": "watchEvent", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Event", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/resourceQuotaUsages", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "void", + "method": "POST", + "summary": "create a ResourceQuotaUsage", + "nickname": "createResourceQuotaUsage", + "parameters": [ + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + }, + { + "type": "v1beta2.ResourceQuotaUsage", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta2/watch/endpoints/{name}", + "description": "API at /api/v1beta2 version v1beta2", + "operations": [ + { + "type": "v1beta2.Endpoints", + "method": "GET", + "summary": "watch a particular Endpoints", + "nickname": "watchEndpoints", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Endpoints", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "query", + "name": "namespace", + "description": "object name and auth scope, such as for teams and projects", + "required": false, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + } + ], + "models": { + "v1beta2.Binding": { + "id": "v1beta2.Binding", + "required": [ + "podID", + "host" + ], + "properties": { + "annotations": { + "type": "v1beta2.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "host": { + "type": "string", + "description": "host to which to bind the specified pod" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "podID": { + "type": "string", + "description": "name of the pod to bind" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta2.Capabilities": { + "id": "v1beta2.Capabilities", + "properties": { + "add": { + "type": "array", + "items": [ + { + "$ref": "v1beta2.CapabilityType" + } + ], + "description": "added capabilities" + }, + "drop": { + "type": "array", + "items": [ + { + "$ref": "v1beta2.CapabilityType" + } + ], + "description": "droped capabilities" + } + } + }, + "v1beta2.CapabilityType": { + "id": "v1beta2.CapabilityType", + "properties": {} + }, + "v1beta2.Container": { + "id": "v1beta2.Container", + "required": [ + "name", + "image", + "imagePullPolicy" + ], + "properties": { + "capabilities": { + "type": "v1beta2.Capabilities", + "description": "capabilities for container" + }, + "command": { + "type": "array", + "items": [ + { + "$ref": "string" + } + ], + "description": "command argv array; not executed within a shell; defaults to entrypoint or command in the image" + }, + "cpu": { + "type": "integer", + "format": "int32", + "description": "CPU share in thousandths of a core" + }, + "env": { + "type": "array", + "items": [ + { + "$ref": "v1beta2.EnvVar" + } + ], + "description": "list of environment variables to set in the container" + }, + "image": { + "type": "string", + "description": "Docker image name" + }, + "imagePullPolicy": { + "type": "v1beta2.PullPolicy", + "description": "image pull policy; one of PullAlways, PullNever, PullIfNotPresent; defaults to PullAlways if :latest tag is specified, or PullIfNotPresent otherwise" + }, + "lifecycle": { + "type": "v1beta2.Lifecycle", + "description": "actions that the management system should take in response to container lifecycle events" + }, + "livenessProbe": { + "type": "v1beta2.LivenessProbe", + "description": "periodic probe of container liveness; container will be restarted if the probe fails" + }, + "memory": { + "type": "integer", + "format": "int64", + "description": "memory limit in bytes; defaults to unlimited" + }, + "name": { + "type": "string", + "description": "name of the container; must be a DNS_LABEL and unique within the pod" + }, + "ports": { + "type": "array", + "items": [ + { + "$ref": "v1beta2.Port" + } + ], + "description": "list of ports to expose from the container" + }, + "privileged": { + "type": "boolean", + "description": "whether or not the container is granted privileged status; defaults to false" + }, + "resources": { + "type": "v1beta2.ResourceRequirementSpec", + "description": "Compute Resources required by this container" + }, + "terminationMessagePath": { + "type": "string", + "description": "path at which the file to which the container's termination message will be written is mounted into the container's filesystem; message written is intended to be brief final status, such as an assertion failure message; defaults to /dev/termination-log" + }, + "volumeMounts": { + "type": "array", + "items": [ + { + "$ref": "v1beta2.VolumeMount" + } + ], + "description": "pod volumes to mount into the container's filesystem" + }, + "workingDir": { + "type": "string", + "description": "container's working directory; defaults to image's default" + } + } + }, + "v1beta2.ContainerManifest": { + "id": "v1beta2.ContainerManifest", + "required": [ + "version", + "id", + "volumes", + "containers" + ], + "properties": { + "containers": { + "type": "array", + "items": [ + { + "$ref": "v1beta2.Container" + } + ], + "description": "list of containers belonging to the pod" + }, + "dnsPolicy": { + "type": "v1beta2.DNSPolicy", + "description": "DNS policy for containers within the pod; one of 'ClusterFirst' or 'Default'" + }, + "id": { + "type": "string", + "description": "manifest name; must be a DNS_SUBDOMAIN" + }, + "restartPolicy": { + "type": "v1beta2.RestartPolicy", + "description": "restart policy for all containers within the pod; one of RestartPolicyAlways, RestartPolicyOnFailure, RestartPolicyNever" + }, + "uuid": { + "type": "types.UID", + "description": "manifest UUID" + }, + "version": { + "type": "string", + "description": "manifest version; must be v1beta1" + }, + "volumes": { + "type": "array", + "items": [ + { + "$ref": "v1beta2.Volume" + } + ], + "description": "list of volumes that can be mounted by containers belonging to the pod" + } + } + }, + "v1beta2.EmptyDir": { + "id": "v1beta2.EmptyDir", + "properties": {} + }, + "v1beta2.Endpoints": { + "id": "v1beta2.Endpoints", + "properties": { + "annotations": { + "type": "v1beta2.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "endpoints": { + "type": "array", + "items": [ + { + "$ref": "string" + } + ], + "description": "list of endpoints corresponding to a service, of the form address:port, such as 10.10.1.1:1909" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta2.EndpointsList": { + "id": "v1beta2.EndpointsList", + "required": [ + "items" + ], + "properties": { + "annotations": { + "type": "v1beta2.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "items": { + "type": "array", + "items": [ + { + "$ref": "v1beta2.Endpoints" + } + ], + "description": "list of service endpoint lists" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta2.EnvVar": { + "id": "v1beta2.EnvVar", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "description": "name of the environment variable; must be a C_IDENTIFIER" + }, + "value": { + "type": "string", + "description": "value of the environment variable; defaults to empty string" + } + } + }, + "v1beta2.Event": { + "id": "v1beta2.Event", + "properties": { + "annotations": { + "type": "v1beta2.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "host": { + "type": "string", + "description": "host name on which this event was generated" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "involvedObject": { + "type": "v1beta2.ObjectReference", + "description": "object that this event is about" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "message": { + "type": "string", + "description": "human-readable description of the status of this operation" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "reason": { + "type": "string", + "description": "short, machine understandable string that gives the reason for the transition into the object's current status" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "source": { + "type": "string", + "description": "component reporting this event; short machine understandable string" + }, + "status": { + "type": "string", + "description": "short, machine understandable string that describes the current status of the referred object" + }, + "timestamp": { + "type": "string", + "description": "time at which the client recorded the event" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta2.EventList": { + "id": "v1beta2.EventList", + "required": [ + "items" + ], + "properties": { + "annotations": { + "type": "v1beta2.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "items": { + "type": "array", + "items": [ + { + "$ref": "v1beta2.Event" + } + ], + "description": "list of events" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta2.ExecAction": { + "id": "v1beta2.ExecAction", + "properties": { + "command": { + "type": "array", + "items": [ + { + "$ref": "string" + } + ], + "description": "command line to execute inside the container; working directory for the command is root ('/') in the container's file system; the command is exec'd, not run inside a shell; exit status of 0 is treated as live/healthy and non-zero is unhealthy" + } + } + }, + "v1beta2.GCEPersistentDisk": { + "id": "v1beta2.GCEPersistentDisk", + "required": [ + "pdName" + ], + "properties": { + "fsType": { + "type": "string", + "description": "file system type to mount, such as ext4, xfs, ntfs" + }, + "partition": { + "type": "integer", + "format": "int32", + "description": "partition on the disk to mount (e.g., '1' for /dev/sda1); if omitted the plain device name (e.g., /dev/sda) will be mounted" + }, + "pdName": { + "type": "string", + "description": "unique name of the PD resource in GCE" + }, + "readOnly": { + "type": "boolean", + "description": "read-only if true, read-write otherwise (false or unspecified)" + } + } + }, + "v1beta2.GitRepo": { + "id": "v1beta2.GitRepo", + "required": [ + "repository", + "revision" + ], + "properties": { + "repository": { + "type": "string", + "description": "repository URL" + }, + "revision": { + "type": "string", + "description": "commit hash for the specified revision" + } + } + }, + "v1beta2.HTTPGetAction": { + "id": "v1beta2.HTTPGetAction", + "properties": { + "host": { + "type": "string", + "description": "hostname to connect to; defaults to pod IP" + }, + "path": { + "type": "string", + "description": "path to access on the HTTP server" + }, + "port": { + "type": "string", + "description": "number or name of the port to access on the container" + } + } + }, + "v1beta2.Handler": { + "id": "v1beta2.Handler", + "properties": { + "exec": { + "type": "v1beta2.ExecAction", + "description": "exec-based handler" + }, + "httpGet": { + "type": "v1beta2.HTTPGetAction", + "description": "HTTP-based handler" + }, + "tcpSocket": { + "type": "v1beta2.TCPSocketAction", + "description": "TCP-based handler; TCP hooks not yet supported" + } + } + }, + "v1beta2.HostPath": { + "id": "v1beta2.HostPath", + "required": [ + "path" + ], + "properties": { + "path": { + "type": "string", + "description": "path of the directory on the host" + } + } + }, + "v1beta2.Lifecycle": { + "id": "v1beta2.Lifecycle", + "properties": { + "postStart": { + "type": "v1beta2.Handler", + "description": "called immediately after a container is started; if the handler fails, the container is terminated and restarted according to its restart policy; other management of the container blocks until the hook completes" + }, + "preStop": { + "type": "v1beta2.Handler", + "description": "called before a container is terminated; the container is terminated after the handler completes; other management of the container blocks until the hook completes" + } + } + }, + "v1beta2.LimitRange": { + "id": "v1beta2.LimitRange", + "properties": { + "annotations": { + "type": "v1beta2.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "spec": { + "type": "v1beta2.LimitRangeSpec" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta2.LimitRangeItem": { + "id": "v1beta2.LimitRangeItem", + "properties": { + "max": { + "type": "v1beta2.ResourceList" + }, + "min": { + "type": "v1beta2.ResourceList" + }, + "type": { + "type": "v1beta2.LimitType" + } + } + }, + "v1beta2.LimitRangeList": { + "id": "v1beta2.LimitRangeList", + "required": [ + "items" + ], + "properties": { + "annotations": { + "type": "v1beta2.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "items": { + "type": "array", + "items": [ + { + "$ref": "v1beta2.LimitRange" + } + ] + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta2.LimitRangeSpec": { + "id": "v1beta2.LimitRangeSpec", + "required": [ + "limits" + ], + "properties": { + "limits": { + "type": "array", + "items": [ + { + "$ref": "v1beta2.LimitRangeItem" + } + ] + } + } + }, + "v1beta2.LivenessProbe": { + "id": "v1beta2.LivenessProbe", + "properties": { + "exec": { + "type": "v1beta2.ExecAction", + "description": "parameters for exec-based liveness probe" + }, + "httpGet": { + "type": "v1beta2.HTTPGetAction", + "description": "parameters for HTTP-based liveness probe" + }, + "initialDelaySeconds": { + "type": "integer", + "format": "int64", + "description": "number of seconds after the container has started before liveness probes are initiated" + }, + "tcpSocket": { + "type": "v1beta2.TCPSocketAction", + "description": "parameters for TCP-based liveness probe" + } + } + }, + "v1beta2.Minion": { + "id": "v1beta2.Minion", + "properties": { + "annotations": { + "type": "v1beta2.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "hostIP": { + "type": "string", + "description": "IP address of the node" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "labels": { + "type": "v1beta2.Minion.labels", + "description": "map of string keys and values that can be used to organize and categorize minions; labels of a minion assigned by the scheduler must match the scheduled pod's nodeSelector" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "resources": { + "type": "v1beta2.NodeResources", + "description": "characterization of node resources" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "status": { + "type": "v1beta2.NodeStatus", + "description": "current status of node" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta2.Minion.labels": { + "id": "v1beta2.Minion.labels", + "properties": {} + }, + "v1beta2.MinionList": { + "id": "v1beta2.MinionList", + "required": [ + "items" + ], + "properties": { + "annotations": { + "type": "v1beta2.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "items": { + "type": "array", + "items": [ + { + "$ref": "v1beta2.Minion" + } + ], + "description": "list of nodes" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta2.NodeCondition": { + "id": "v1beta2.NodeCondition", + "required": [ + "kind", + "status" + ], + "properties": { + "kind": { + "type": "v1beta2.NodeConditionKind", + "description": "kind of the condition, one of reachable, ready" + }, + "lastTransitionTime": { + "type": "string", + "description": "last time the condition transit from one status to another" + }, + "message": { + "type": "string", + "description": "human readable message indicating details about last transition" + }, + "reason": { + "type": "string", + "description": "(brief) reason for the condition's last transition" + }, + "status": { + "type": "v1beta2.NodeConditionStatus", + "description": "status of the condition, one of full, none, unknown" + } + } + }, + "v1beta2.NodeResources": { + "id": "v1beta2.NodeResources", + "properties": { + "capacity": { + "type": "v1beta2.ResourceList", + "description": "resource capacity of a node represented as a map of resource name to quantity of resource" + } + } + }, + "v1beta2.NodeStatus": { + "id": "v1beta2.NodeStatus", + "properties": { + "conditions": { + "type": "array", + "items": [ + { + "$ref": "v1beta2.NodeCondition" + } + ], + "description": "conditions is an array of current node conditions" + }, + "phase": { + "type": "v1beta2.NodePhase", + "description": "node phase is the current lifecycle phase of the node" + } + } + }, + "v1beta2.ObjectReference": { + "id": "v1beta2.ObjectReference", + "properties": { + "apiVersion": { + "type": "string", + "description": "API version of the referent" + }, + "fieldPath": { + "type": "string", + "description": "if referring to a piece of an object instead of an entire object, this string should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]" + }, + "kind": { + "type": "string", + "description": "kind of the referent" + }, + "name": { + "type": "string", + "description": "id of the referent" + }, + "namespace": { + "type": "string", + "description": "namespace of the referent" + }, + "resourceVersion": { + "type": "string", + "description": "specific resourceVersion to which this reference is made, if any" + }, + "uid": { + "type": "types.UID", + "description": "uid of the referent" + } + } + }, + "v1beta2.Pod": { + "id": "v1beta2.Pod", + "properties": { + "annotations": { + "type": "v1beta2.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "currentState": { + "type": "v1beta2.PodState", + "description": "current state of the pod" + }, + "desiredState": { + "type": "v1beta2.PodState", + "description": "specification of the desired state of the pod" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "labels": { + "type": "v1beta2.Pod.labels", + "description": "map of string keys and values that can be used to organize and categorize pods; may match selectors of replication controllers and services" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "nodeSelector": { + "type": "v1beta2.Pod.nodeSelector", + "description": "selector which must match a node's labels for the pod to be scheduled on that node" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta2.Pod.labels": { + "id": "v1beta2.Pod.labels", + "properties": {} + }, + "v1beta2.Pod.nodeSelector": { + "id": "v1beta2.Pod.nodeSelector", + "properties": {} + }, + "v1beta2.PodList": { + "id": "v1beta2.PodList", + "required": [ + "items" + ], + "properties": { + "annotations": { + "type": "v1beta2.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "items": { + "type": "array", + "items": [ + { + "$ref": "v1beta2.Pod" + } + ], + "description": "list of pods" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta2.PodState": { + "id": "v1beta2.PodState", + "properties": { + "host": { + "type": "string", + "description": "host to which the pod is assigned; empty if not yet scheduled" + }, + "hostIP": { + "type": "string", + "description": "IP address of the host to which the pod is assigned; empty if not yet scheduled" + }, + "info": { + "type": "v1beta2.PodInfo", + "description": "map of container name to container status" + }, + "manifest": { + "type": "v1beta2.ContainerManifest", + "description": "manifest of containers and volumes comprising the pod" + }, + "message": { + "type": "string", + "description": "human readable message indicating details about why the pod is in this condition" + }, + "podIP": { + "type": "string", + "description": "IP address allocated to the pod; routable at least within the cluster; empty if not yet allocated" + }, + "status": { + "type": "v1beta2.PodStatus", + "description": "current condition of the pod, Waiting, Running, or Terminated" + } + } + }, + "v1beta2.PodTemplate": { + "id": "v1beta2.PodTemplate", + "properties": { + "annotations": { + "type": "v1beta2.PodTemplate.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about pods created from the template" + }, + "desiredState": { + "type": "v1beta2.PodState", + "description": "specification of the desired state of pods created from this template" + }, + "labels": { + "type": "v1beta2.PodTemplate.labels", + "description": "map of string keys and values that can be used to organize and categorize the pods created from the template; must match the selector of the replication controller to which the template belongs; may match selectors of services" + }, + "nodeSelector": { + "type": "v1beta2.PodTemplate.nodeSelector", + "description": "a selector which must be true for the pod to fit on a node" + } + } + }, + "v1beta2.PodTemplate.annotations": { + "id": "v1beta2.PodTemplate.annotations", + "properties": {} + }, + "v1beta2.PodTemplate.labels": { + "id": "v1beta2.PodTemplate.labels", + "properties": {} + }, + "v1beta2.PodTemplate.nodeSelector": { + "id": "v1beta2.PodTemplate.nodeSelector", + "properties": {} + }, + "v1beta2.Port": { + "id": "v1beta2.Port", + "required": [ + "containerPort" + ], + "properties": { + "containerPort": { + "type": "integer", + "format": "int32", + "description": "number of port to expose on the pod's IP address" + }, + "hostIP": { + "type": "string", + "description": "host IP to bind the port to" + }, + "hostPort": { + "type": "integer", + "format": "int32", + "description": "number of port to expose on the host; most containers do not need this" + }, + "name": { + "type": "string", + "description": "name for the port that can be referred to by services; must be a DNS_LABEL and unique without the pod" + }, + "protocol": { + "type": "v1beta2.Protocol", + "description": "protocol for port; must be UDP or TCP; TCP if unspecified" + } + } + }, + "v1beta2.ReplicationController": { + "id": "v1beta2.ReplicationController", + "properties": { + "annotations": { + "type": "v1beta2.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "currentState": { + "type": "v1beta2.ReplicationControllerState", + "description": "current state of the replication controller" + }, + "desiredState": { + "type": "v1beta2.ReplicationControllerState", + "description": "specification of the desired state of the replication controller" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "labels": { + "type": "v1beta2.ReplicationController.labels", + "description": "map of string keys and values that can be used to organize and categorize replication controllers" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta2.ReplicationController.labels": { + "id": "v1beta2.ReplicationController.labels", + "properties": {} + }, + "v1beta2.ReplicationControllerList": { + "id": "v1beta2.ReplicationControllerList", + "required": [ + "items" + ], + "properties": { + "annotations": { + "type": "v1beta2.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "items": { + "type": "array", + "items": [ + { + "$ref": "v1beta2.ReplicationController" + } + ], + "description": "list of replication controllers" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta2.ReplicationControllerState": { + "id": "v1beta2.ReplicationControllerState", + "required": [ + "replicas" + ], + "properties": { + "podTemplate": { + "type": "v1beta2.PodTemplate", + "description": "template for pods to be created by this replication controller when the observed number of replicas is less than the desired number of replicas" + }, + "replicaSelector": { + "type": "v1beta2.ReplicationControllerState.replicaSelector", + "description": "label keys and values that must match in order to be controlled by this replication controller" + }, + "replicas": { + "type": "integer", + "format": "int32", + "description": "number of replicas (desired or observed, as appropriate)" + } + } + }, + "v1beta2.ReplicationControllerState.replicaSelector": { + "id": "v1beta2.ReplicationControllerState.replicaSelector", + "properties": {} + }, + "v1beta2.ResourceQuota": { + "id": "v1beta2.ResourceQuota", + "properties": { + "annotations": { + "type": "v1beta2.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "spec": { + "type": "v1beta2.ResourceQuotaSpec" + }, + "status": { + "type": "v1beta2.ResourceQuotaStatus" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta2.ResourceQuotaList": { + "id": "v1beta2.ResourceQuotaList", + "required": [ + "items" + ], + "properties": { + "annotations": { + "type": "v1beta2.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "items": { + "type": "array", + "items": [ + { + "$ref": "v1beta2.ResourceQuota" + } + ] + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta2.ResourceQuotaSpec": { + "id": "v1beta2.ResourceQuotaSpec", + "properties": { + "hard": { + "type": "v1beta2.ResourceList" + } + } + }, + "v1beta2.ResourceQuotaStatus": { + "id": "v1beta2.ResourceQuotaStatus", + "properties": { + "hard": { + "type": "v1beta2.ResourceList" + }, + "used": { + "type": "v1beta2.ResourceList" + } + } + }, + "v1beta2.ResourceQuotaUsage": { + "id": "v1beta2.ResourceQuotaUsage", + "properties": { + "annotations": { + "type": "v1beta2.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "status": { + "type": "v1beta2.ResourceQuotaStatus" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta2.ResourceRequirementSpec": { + "id": "v1beta2.ResourceRequirementSpec", + "properties": { + "limits": { + "type": "v1beta2.ResourceList", + "description": "Maximum amount of compute resources allowed" + } + } + }, + "v1beta2.RestartPolicy": { + "id": "v1beta2.RestartPolicy", + "properties": { + "always": { + "type": "v1beta2.RestartPolicyAlways", + "description": "always restart the container after termination" + }, + "never": { + "type": "v1beta2.RestartPolicyNever", + "description": "never restart the container" + }, + "onFailure": { + "type": "v1beta2.RestartPolicyOnFailure", + "description": "restart the container if it fails for any reason, but not if it succeeds (exit 0)" + } + } + }, + "v1beta2.RestartPolicyAlways": { + "id": "v1beta2.RestartPolicyAlways", + "properties": {} + }, + "v1beta2.RestartPolicyNever": { + "id": "v1beta2.RestartPolicyNever", + "properties": {} + }, + "v1beta2.RestartPolicyOnFailure": { + "id": "v1beta2.RestartPolicyOnFailure", + "properties": {} + }, + "v1beta2.Service": { + "id": "v1beta2.Service", + "required": [ + "port", + "selector" + ], + "properties": { + "annotations": { + "type": "v1beta2.TypeMeta.annotations", + "description": "map of string keys and values that can be used by external tooling to store and retrieve arbitrary metadata about the object" + }, + "apiVersion": { + "type": "string", + "description": "version of the schema the object should have" + }, + "containerPort": { + "type": "string", + "description": "number or name of the port to access on the containers belonging to pods targeted by the service" + }, + "createExternalLoadBalancer": { + "type": "boolean", + "description": "set up a cloud-provider-specific load balancer on an external IP" + }, + "creationTimestamp": { + "type": "string", + "description": "RFC 3339 date and time at which the object was created; recorded by the system; null for lists" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "id": { + "type": "string", + "description": "name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs" + }, + "kind": { + "type": "string", + "description": "kind of object, in CamelCase" + }, + "labels": { + "type": "v1beta2.Service.labels", + "description": "map of string keys and values that can be used to organize and categorize services" + }, + "namespace": { + "type": "string", + "description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default" + }, + "port": { + "type": "integer", + "format": "int32", + "description": "port exposed by the service" + }, + "portalIP": { + "type": "string", + "description": "IP address of the service; usually assigned by the system; if specified, it will be allocated to the service if unused, and creation of the service will fail otherwise; cannot be updated" + }, + "protocol": { + "type": "v1beta2.Protocol", + "description": "protocol for port; must be UDP or TCP; TCP if unspecified" + }, + "proxyPort": { + "type": "integer", + "format": "int32", + "description": "if non-zero, a pre-allocated host port used for this service by the proxy on each node; assigned by the master and ignored on input" + }, + "publicIPs": { + "type": "array", + "items": [ + { + "$ref": "string" + } + ], + "description": "externally visible IPs from which to select the address for the external load balancer" + }, + "resourceVersion": { + "type": "uint64", + "description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server" + }, + "selector": { + "type": "v1beta2.Service.selector", + "description": "label keys and values that must match in order to receive traffic for this service; if empty, all pods are selected, if not specified, endpoints must be manually specified" + }, + "selfLink": { + "type": "string", + "description": "URL for the object" + }, + "sessionAffinity": { + "type": "v1beta2.AffinityType", + "description": "enable client IP based session affinity; must be ClientIP or None; defaults to None" + }, + "uid": { + "type": "types.UID", + "description": "UUID assigned by the system upon creation, unique across space and time" + } + } + }, + "v1beta2.Service.labels": { + "id": "v1beta2.Service.labels", + "properties": {} + }, + "v1beta2.Service.selector": { + "id": "v1beta2.Service.selector", + "properties": {} + }, + "v1beta2.TCPSocketAction": { + "id": "v1beta2.TCPSocketAction", + "properties": { + "port": { + "type": "string", + "description": "number of name of the port to access on the container" + } + } + }, + "v1beta2.Volume": { + "id": "v1beta2.Volume", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "description": "volume name; must be a DNS_LABEL and unique within the pod" + }, + "source": { + "type": "v1beta2.VolumeSource", + "description": "location and type of volume to mount; at most one of HostDir, EmptyDir, GCEPersistentDisk, or GitRepo; default is EmptyDir" + } + } + }, + "v1beta2.VolumeMount": { + "id": "v1beta2.VolumeMount", + "required": [ + "name", + "mountPath" + ], + "properties": { + "mountPath": { + "type": "string", + "description": "path within the container at which the volume should be mounted" + }, + "name": { + "type": "string", + "description": "name of the volume to mount" + }, + "readOnly": { + "type": "boolean", + "description": "mounted read-only if true, read-write otherwise (false or unspecified)" + } + } + }, + "v1beta2.VolumeSource": { + "id": "v1beta2.VolumeSource", + "required": [ + "hostDir", + "emptyDir", + "persistentDisk", + "gitRepo" + ], + "properties": { + "emptyDir": { + "type": "v1beta2.EmptyDir", + "description": "temporary directory that shares a pod's lifetime" + }, + "gitRepo": { + "type": "v1beta2.GitRepo", + "description": "git repository at a particular revision" + }, + "hostDir": { + "type": "v1beta2.HostPath", + "description": "pre-existing host file or directory; generally for privileged system daemons or other agents tied to the host" + }, + "persistentDisk": { + "type": "v1beta2.GCEPersistentDisk", + "description": "GCE disk resource attached to the host machine on demand" + } + } + } + } + } \ No newline at end of file diff --git a/api/swagger-spec/v1beta3.json b/api/swagger-spec/v1beta3.json new file mode 100644 index 00000000000..8743266e539 --- /dev/null +++ b/api/swagger-spec/v1beta3.json @@ -0,0 +1,3812 @@ +{ + "swaggerVersion": "1.2", + "apiVersion": "v1beta3", + "basePath": "127.0.0.1:8050", + "resourcePath": "/api/v1beta3", + "apis": [ + { + "path": "/api/v1beta3/resourcequotas", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.ResourceQuotaList", + "method": "GET", + "summary": "list objects of kind ResourceQuota", + "nickname": "listResourceQuota", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/ns/{ns}/pods", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.PodList", + "method": "GET", + "summary": "list objects of kind Pod", + "nickname": "listPod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a Pod", + "nickname": "createPod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "v1beta3.Pod", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/services", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.Service", + "method": "GET", + "summary": "list objects of kind Service", + "nickname": "listService", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/proxy/nodes/{name}/{path:*}", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "proxy GET requests to Node", + "nickname": "proxyGETNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "proxy PUT requests to Node", + "nickname": "proxyPUTNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "proxy POST requests to Node", + "nickname": "proxyPOSTNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "proxy DELETE requests to Node", + "nickname": "proxyDELETENode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/watch/ns/{ns}/replicationcontrollers", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.ReplicationControllerList", + "method": "GET", + "summary": "watch a list of ReplicationController", + "nickname": "watchReplicationControllerlist", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/ns/{ns}/services", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.Service", + "method": "GET", + "summary": "list objects of kind Service", + "nickname": "listService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a Service", + "nickname": "createService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "v1beta3.Service", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/ns/{ns}/limitranges", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.LimitRangeList", + "method": "GET", + "summary": "list objects of kind LimitRange", + "nickname": "listLimitRange", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a LimitRange", + "nickname": "createLimitRange", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "v1beta3.LimitRange", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/ns/{ns}/events", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.EventList", + "method": "GET", + "summary": "list objects of kind Event", + "nickname": "listEvent", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a Event", + "nickname": "createEvent", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "v1beta3.Event", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/watch/ns/{ns}/events/{name}", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.Event", + "method": "GET", + "summary": "watch a particular Event", + "nickname": "watchEvent", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Event", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/watch/ns/{ns}/resourcequotas", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.ResourceQuotaList", + "method": "GET", + "summary": "watch a list of ResourceQuota", + "nickname": "watchResourceQuotalist", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/ns/{ns}/resourcequotausages", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "void", + "method": "POST", + "summary": "create a ResourceQuotaUsage", + "nickname": "createResourceQuotaUsage", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "v1beta3.ResourceQuotaUsage", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/watch/endpoints", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.EndpointsList", + "method": "GET", + "summary": "watch a list of Endpoints", + "nickname": "watchEndpointslist", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/watch/ns/{ns}/pods", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.PodList", + "method": "GET", + "summary": "watch a list of Pod", + "nickname": "watchPodlist", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/replicationcontrollers", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.ReplicationControllerList", + "method": "GET", + "summary": "list objects of kind ReplicationController", + "nickname": "listReplicationController", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/watch/replicationcontrollers", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.ReplicationControllerList", + "method": "GET", + "summary": "watch a list of ReplicationController", + "nickname": "watchReplicationControllerlist", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/watch/ns/{ns}/limitranges/{name}", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.LimitRange", + "method": "GET", + "summary": "watch a particular LimitRange", + "nickname": "watchLimitRange", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the LimitRange", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/limitranges", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.LimitRangeList", + "method": "GET", + "summary": "list objects of kind LimitRange", + "nickname": "listLimitRange", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/nodes/{name}", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.Node", + "method": "GET", + "summary": "read the specified Node", + "nickname": "readNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "update the specified Node", + "nickname": "updateNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + }, + { + "type": "v1beta3.Node", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "delete a Node", + "nickname": "deleteNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/watch/nodes/{name}", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.Node", + "method": "GET", + "summary": "watch a particular Node", + "nickname": "watchNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/watch/ns/{ns}/events", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.EventList", + "method": "GET", + "summary": "watch a list of Event", + "nickname": "watchEventlist", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/ns/{ns}/events/{name}", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.Event", + "method": "GET", + "summary": "read the specified Event", + "nickname": "readEvent", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Event", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "delete a Event", + "nickname": "deleteEvent", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Event", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/ns/{ns}/endpoints/{name}", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.Endpoints", + "method": "GET", + "summary": "read the specified Endpoints", + "nickname": "readEndpoints", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Endpoints", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "update the specified Endpoints", + "nickname": "updateEndpoints", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Endpoints", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "v1beta3.Endpoints", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/pods", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.PodList", + "method": "GET", + "summary": "list objects of kind Pod", + "nickname": "listPod", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/ns/{ns}/services/{name}", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.Service", + "method": "GET", + "summary": "read the specified Service", + "nickname": "readService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "update the specified Service", + "nickname": "updateService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "v1beta3.Service", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "delete a Service", + "nickname": "deleteService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/events", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.EventList", + "method": "GET", + "summary": "list objects of kind Event", + "nickname": "listEvent", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/watch/ns/{ns}/endpoints", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.EndpointsList", + "method": "GET", + "summary": "watch a list of Endpoints", + "nickname": "watchEndpointslist", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/watch/nodes", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.NodeList", + "method": "GET", + "summary": "watch a list of Node", + "nickname": "watchNodelist", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/ns/{ns}/resourcequotas", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.ResourceQuotaList", + "method": "GET", + "summary": "list objects of kind ResourceQuota", + "nickname": "listResourceQuota", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a ResourceQuota", + "nickname": "createResourceQuota", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "v1beta3.ResourceQuota", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/ns/{ns}/bindings", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "void", + "method": "POST", + "summary": "create a Binding", + "nickname": "createBinding", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "v1beta3.Binding", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/watch/services", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.Service", + "method": "GET", + "summary": "watch a list of Service", + "nickname": "watchServicelist", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/watch/ns/{ns}/limitranges", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.LimitRangeList", + "method": "GET", + "summary": "watch a list of LimitRange", + "nickname": "watchLimitRangelist", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/ns/{ns}/limitranges/{name}", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.LimitRange", + "method": "GET", + "summary": "read the specified LimitRange", + "nickname": "readLimitRange", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the LimitRange", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "update the specified LimitRange", + "nickname": "updateLimitRange", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the LimitRange", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "v1beta3.LimitRange", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "delete a LimitRange", + "nickname": "deleteLimitRange", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the LimitRange", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/ns/{ns}/resourcequotas/{name}", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.ResourceQuota", + "method": "GET", + "summary": "read the specified ResourceQuota", + "nickname": "readResourceQuota", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ResourceQuota", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "update the specified ResourceQuota", + "nickname": "updateResourceQuota", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ResourceQuota", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "v1beta3.ResourceQuota", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "delete a ResourceQuota", + "nickname": "deleteResourceQuota", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ResourceQuota", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/ns/{ns}/pods/{name}", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.Pod", + "method": "GET", + "summary": "read the specified Pod", + "nickname": "readPod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "update the specified Pod", + "nickname": "updatePod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "v1beta3.Pod", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "delete a Pod", + "nickname": "deletePod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/watch/ns/{ns}/pods/{name}", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.Pod", + "method": "GET", + "summary": "watch a particular Pod", + "nickname": "watchPod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/proxy/ns/{ns}/pods/{name}/{path:*}", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "proxy GET requests to Pod", + "nickname": "proxyGETPod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "proxy PUT requests to Pod", + "nickname": "proxyPUTPod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "proxy POST requests to Pod", + "nickname": "proxyPOSTPod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "proxy DELETE requests to Pod", + "nickname": "proxyDELETEPod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/endpoints", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.EndpointsList", + "method": "GET", + "summary": "list objects of kind Endpoints", + "nickname": "listEndpoints", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/watch/resourcequotas", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.ResourceQuotaList", + "method": "GET", + "summary": "watch a list of ResourceQuota", + "nickname": "watchResourceQuotalist", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/ns/{ns}/replicationcontrollers", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.ReplicationControllerList", + "method": "GET", + "summary": "list objects of kind ReplicationController", + "nickname": "listReplicationController", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a ReplicationController", + "nickname": "createReplicationController", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "v1beta3.ReplicationController", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/watch/ns/{ns}/replicationcontrollers/{name}", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.ReplicationController", + "method": "GET", + "summary": "watch a particular ReplicationController", + "nickname": "watchReplicationController", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ReplicationController", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/watch/ns/{ns}/services", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.Service", + "method": "GET", + "summary": "watch a list of Service", + "nickname": "watchServicelist", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/watch/ns/{ns}/resourcequotas/{name}", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.ResourceQuota", + "method": "GET", + "summary": "watch a particular ResourceQuota", + "nickname": "watchResourceQuota", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ResourceQuota", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/watch/ns/{ns}/services/{name}", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.Service", + "method": "GET", + "summary": "watch a particular Service", + "nickname": "watchService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/watch/events", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.EventList", + "method": "GET", + "summary": "watch a list of Event", + "nickname": "watchEventlist", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/nodes", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.NodeList", + "method": "GET", + "summary": "list objects of kind Node", + "nickname": "listNode", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a Node", + "nickname": "createNode", + "parameters": [ + { + "type": "v1beta3.Node", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/proxy/ns/{ns}/services/{name}/{path:*}", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "proxy GET requests to Service", + "nickname": "proxyGETService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "proxy PUT requests to Service", + "nickname": "proxyPUTService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "proxy POST requests to Service", + "nickname": "proxyPOSTService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "proxy DELETE requests to Service", + "nickname": "proxyDELETEService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/ns/{ns}/endpoints", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.EndpointsList", + "method": "GET", + "summary": "list objects of kind Endpoints", + "nickname": "listEndpoints", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "POST", + "summary": "create a Endpoints", + "nickname": "createEndpoints", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "v1beta3.Endpoints", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/watch/ns/{ns}/endpoints/{name}", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.Endpoints", + "method": "GET", + "summary": "watch a particular Endpoints", + "nickname": "watchEndpoints", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Endpoints", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/redirect/nodes/{name}", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "redirect GET request to Node", + "nickname": "redirectNode", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Node", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/watch/pods", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.PodList", + "method": "GET", + "summary": "watch a list of Pod", + "nickname": "watchPodlist", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/ns/{ns}/replicationcontrollers/{name}", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.ReplicationController", + "method": "GET", + "summary": "read the specified ReplicationController", + "nickname": "readReplicationController", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ReplicationController", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "PUT", + "summary": "update the specified ReplicationController", + "nickname": "updateReplicationController", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ReplicationController", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + }, + { + "type": "v1beta3.ReplicationController", + "paramType": "body", + "name": "body", + "description": "", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + }, + { + "type": "void", + "method": "DELETE", + "summary": "delete a ReplicationController", + "nickname": "deleteReplicationController", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the ReplicationController", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/redirect/ns/{ns}/services/{name}", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "redirect GET request to Service", + "nickname": "redirectService", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Service", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/watch/limitranges", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "v1beta3.LimitRangeList", + "method": "GET", + "summary": "watch a list of LimitRange", + "nickname": "watchLimitRangelist", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "*/*" + ] + } + ] + }, + { + "path": "/api/v1beta3/redirect/ns/{ns}/pods/{name}", + "description": "API at /api/v1beta3 version v1beta3", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "redirect GET request to Pod", + "nickname": "redirectPod", + "parameters": [ + { + "type": "string", + "paramType": "path", + "name": "name", + "description": "name of the Pod", + "required": true, + "allowMultiple": false + }, + { + "type": "string", + "paramType": "path", + "name": "ns", + "description": "object name and auth scope, such as for teams and projects", + "required": true, + "allowMultiple": false + } + ], + "produces": [ + "*/*" + ], + "consumes": [ + "*/*" + ] + } + ] + } + ], + "models": { + "v1beta3.Binding": { + "id": "v1beta3.Binding", + "required": [ + "podID", + "host" + ], + "properties": { + "annotations": { + "type": "v1beta3.ObjectMeta.annotations" + }, + "apiVersion": { + "type": "string" + }, + "creationTimestamp": { + "type": "string" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "host": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "labels": { + "type": "v1beta3.ObjectMeta.labels" + }, + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "podID": { + "type": "string" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + }, + "uid": { + "type": "types.UID" + } + } + }, + "v1beta3.Capabilities": { + "id": "v1beta3.Capabilities", + "properties": { + "add": { + "type": "array", + "items": [ + { + "$ref": "v1beta3.CapabilityType" + } + ] + }, + "drop": { + "type": "array", + "items": [ + { + "$ref": "v1beta3.CapabilityType" + } + ] + } + } + }, + "v1beta3.CapabilityType": { + "id": "v1beta3.CapabilityType", + "properties": {} + }, + "v1beta3.Container": { + "id": "v1beta3.Container", + "required": [ + "name", + "image", + "imagePullPolicy" + ], + "properties": { + "capabilities": { + "type": "v1beta3.Capabilities" + }, + "command": { + "type": "array", + "items": [ + { + "$ref": "string" + } + ] + }, + "env": { + "type": "array", + "items": [ + { + "$ref": "v1beta3.EnvVar" + } + ] + }, + "image": { + "type": "string" + }, + "imagePullPolicy": { + "type": "v1beta3.PullPolicy" + }, + "lifecycle": { + "type": "v1beta3.Lifecycle" + }, + "livenessProbe": { + "type": "v1beta3.Probe" + }, + "name": { + "type": "string" + }, + "ports": { + "type": "array", + "items": [ + { + "$ref": "v1beta3.Port" + } + ] + }, + "privileged": { + "type": "boolean" + }, + "resources": { + "type": "v1beta3.ResourceRequirementSpec", + "description": "Compute Resources required by this container" + }, + "terminationMessagePath": { + "type": "string" + }, + "volumeMounts": { + "type": "array", + "items": [ + { + "$ref": "v1beta3.VolumeMount" + } + ] + }, + "workingDir": { + "type": "string" + } + } + }, + "v1beta3.EmptyDir": { + "id": "v1beta3.EmptyDir", + "properties": {} + }, + "v1beta3.Endpoints": { + "id": "v1beta3.Endpoints", + "required": [ + "endpoints" + ], + "properties": { + "annotations": { + "type": "v1beta3.ObjectMeta.annotations" + }, + "apiVersion": { + "type": "string" + }, + "creationTimestamp": { + "type": "string" + }, + "endpoints": { + "type": "array", + "items": [ + { + "$ref": "string" + } + ] + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "kind": { + "type": "string" + }, + "labels": { + "type": "v1beta3.ObjectMeta.labels" + }, + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + }, + "uid": { + "type": "types.UID" + } + } + }, + "v1beta3.EndpointsList": { + "id": "v1beta3.EndpointsList", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "type": "string" + }, + "items": { + "type": "array", + "items": [ + { + "$ref": "v1beta3.Endpoints" + } + ] + }, + "kind": { + "type": "string" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + } + } + }, + "v1beta3.EnvVar": { + "id": "v1beta3.EnvVar", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "string" + } + } + }, + "v1beta3.Event": { + "id": "v1beta3.Event", + "properties": { + "annotations": { + "type": "v1beta3.ObjectMeta.annotations" + }, + "apiVersion": { + "type": "string" + }, + "creationTimestamp": { + "type": "string" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "involvedObject": { + "type": "v1beta3.ObjectReference" + }, + "kind": { + "type": "string" + }, + "labels": { + "type": "v1beta3.ObjectMeta.labels" + }, + "message": { + "type": "string" + }, + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "reason": { + "type": "string" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + }, + "source": { + "type": "v1beta3.EventSource" + }, + "timestamp": { + "type": "string" + }, + "uid": { + "type": "types.UID" + } + } + }, + "v1beta3.EventList": { + "id": "v1beta3.EventList", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "type": "string" + }, + "items": { + "type": "array", + "items": [ + { + "$ref": "v1beta3.Event" + } + ] + }, + "kind": { + "type": "string" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + } + } + }, + "v1beta3.EventSource": { + "id": "v1beta3.EventSource", + "properties": { + "component": { + "type": "string" + }, + "host": { + "type": "string" + } + } + }, + "v1beta3.ExecAction": { + "id": "v1beta3.ExecAction", + "properties": { + "command": { + "type": "array", + "items": [ + { + "$ref": "string" + } + ] + } + } + }, + "v1beta3.GCEPersistentDisk": { + "id": "v1beta3.GCEPersistentDisk", + "required": [ + "pdName" + ], + "properties": { + "fsType": { + "type": "string" + }, + "partition": { + "type": "integer", + "format": "int32" + }, + "pdName": { + "type": "string" + }, + "readOnly": { + "type": "boolean" + } + } + }, + "v1beta3.GitRepo": { + "id": "v1beta3.GitRepo", + "required": [ + "repository", + "revision" + ], + "properties": { + "repository": { + "type": "string" + }, + "revision": { + "type": "string" + } + } + }, + "v1beta3.HTTPGetAction": { + "id": "v1beta3.HTTPGetAction", + "properties": { + "host": { + "type": "string" + }, + "path": { + "type": "string" + }, + "port": { + "type": "string" + } + } + }, + "v1beta3.Handler": { + "id": "v1beta3.Handler", + "properties": { + "exec": { + "type": "v1beta3.ExecAction" + }, + "httpGet": { + "type": "v1beta3.HTTPGetAction" + }, + "tcpSocket": { + "type": "v1beta3.TCPSocketAction" + } + } + }, + "v1beta3.HostPath": { + "id": "v1beta3.HostPath", + "required": [ + "path" + ], + "properties": { + "path": { + "type": "string" + } + } + }, + "v1beta3.Lifecycle": { + "id": "v1beta3.Lifecycle", + "properties": { + "postStart": { + "type": "v1beta3.Handler" + }, + "preStop": { + "type": "v1beta3.Handler" + } + } + }, + "v1beta3.LimitRange": { + "id": "v1beta3.LimitRange", + "properties": { + "annotations": { + "type": "v1beta3.ObjectMeta.annotations" + }, + "apiVersion": { + "type": "string" + }, + "creationTimestamp": { + "type": "string" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "kind": { + "type": "string" + }, + "labels": { + "type": "v1beta3.ObjectMeta.labels" + }, + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + }, + "spec": { + "type": "v1beta3.LimitRangeSpec" + }, + "uid": { + "type": "types.UID" + } + } + }, + "v1beta3.LimitRangeItem": { + "id": "v1beta3.LimitRangeItem", + "properties": { + "max": { + "type": "v1beta3.ResourceList" + }, + "min": { + "type": "v1beta3.ResourceList" + }, + "type": { + "type": "v1beta3.LimitType" + } + } + }, + "v1beta3.LimitRangeList": { + "id": "v1beta3.LimitRangeList", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "type": "string" + }, + "items": { + "type": "array", + "items": [ + { + "$ref": "v1beta3.LimitRange" + } + ] + }, + "kind": { + "type": "string" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + } + } + }, + "v1beta3.LimitRangeSpec": { + "id": "v1beta3.LimitRangeSpec", + "required": [ + "limits" + ], + "properties": { + "limits": { + "type": "array", + "items": [ + { + "$ref": "v1beta3.LimitRangeItem" + } + ] + } + } + }, + "v1beta3.Node": { + "id": "v1beta3.Node", + "properties": { + "annotations": { + "type": "v1beta3.ObjectMeta.annotations" + }, + "apiVersion": { + "type": "string" + }, + "creationTimestamp": { + "type": "string" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "kind": { + "type": "string" + }, + "labels": { + "type": "v1beta3.ObjectMeta.labels" + }, + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + }, + "spec": { + "type": "v1beta3.NodeSpec" + }, + "status": { + "type": "v1beta3.NodeStatus" + }, + "uid": { + "type": "types.UID" + } + } + }, + "v1beta3.NodeCondition": { + "id": "v1beta3.NodeCondition", + "required": [ + "kind", + "status" + ], + "properties": { + "kind": { + "type": "v1beta3.NodeConditionKind" + }, + "lastTransitionTime": { + "type": "string" + }, + "message": { + "type": "string" + }, + "reason": { + "type": "string" + }, + "status": { + "type": "v1beta3.NodeConditionStatus" + } + } + }, + "v1beta3.NodeList": { + "id": "v1beta3.NodeList", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "type": "string" + }, + "items": { + "type": "array", + "items": [ + { + "$ref": "v1beta3.Node" + } + ] + }, + "kind": { + "type": "string" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + } + } + }, + "v1beta3.NodeSpec": { + "id": "v1beta3.NodeSpec", + "properties": { + "capacity": { + "type": "v1beta3.ResourceList" + } + } + }, + "v1beta3.NodeStatus": { + "id": "v1beta3.NodeStatus", + "properties": { + "conditions": { + "type": "array", + "items": [ + { + "$ref": "v1beta3.NodeCondition" + } + ] + }, + "hostIP": { + "type": "string" + }, + "phase": { + "type": "v1beta3.NodePhase" + } + } + }, + "v1beta3.ObjectReference": { + "id": "v1beta3.ObjectReference", + "properties": { + "apiVersion": { + "type": "string" + }, + "fieldPath": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "resourceVersion": { + "type": "string" + }, + "uid": { + "type": "types.UID" + } + } + }, + "v1beta3.Pod": { + "id": "v1beta3.Pod", + "properties": { + "annotations": { + "type": "v1beta3.ObjectMeta.annotations" + }, + "apiVersion": { + "type": "string" + }, + "creationTimestamp": { + "type": "string" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "kind": { + "type": "string" + }, + "labels": { + "type": "v1beta3.ObjectMeta.labels" + }, + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + }, + "spec": { + "type": "v1beta3.PodSpec" + }, + "status": { + "type": "v1beta3.PodStatus" + }, + "uid": { + "type": "types.UID" + } + } + }, + "v1beta3.PodList": { + "id": "v1beta3.PodList", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "type": "string" + }, + "items": { + "type": "array", + "items": [ + { + "$ref": "v1beta3.Pod" + } + ] + }, + "kind": { + "type": "string" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + } + } + }, + "v1beta3.PodSpec": { + "id": "v1beta3.PodSpec", + "required": [ + "volumes", + "containers" + ], + "properties": { + "containers": { + "type": "array", + "items": [ + { + "$ref": "v1beta3.Container" + } + ] + }, + "dnsPolicy": { + "type": "v1beta3.DNSPolicy" + }, + "host": { + "type": "string", + "description": "host requested for this pod" + }, + "nodeSelector": { + "type": "v1beta3.PodSpec.nodeSelector" + }, + "restartPolicy": { + "type": "v1beta3.RestartPolicy" + }, + "volumes": { + "type": "array", + "items": [ + { + "$ref": "v1beta3.Volume" + } + ] + } + } + }, + "v1beta3.PodSpec.nodeSelector": { + "id": "v1beta3.PodSpec.nodeSelector", + "properties": {} + }, + "v1beta3.PodStatus": { + "id": "v1beta3.PodStatus", + "properties": { + "host": { + "type": "string" + }, + "hostIP": { + "type": "string" + }, + "info": { + "type": "v1beta3.PodInfo" + }, + "message": { + "type": "string" + }, + "phase": { + "type": "v1beta3.PodPhase" + }, + "podIP": { + "type": "string" + } + } + }, + "v1beta3.PodTemplateSpec": { + "id": "v1beta3.PodTemplateSpec", + "properties": { + "annotations": { + "type": "v1beta3.ObjectMeta.annotations" + }, + "creationTimestamp": { + "type": "string" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "labels": { + "type": "v1beta3.ObjectMeta.labels" + }, + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + }, + "spec": { + "type": "v1beta3.PodSpec" + }, + "uid": { + "type": "types.UID" + } + } + }, + "v1beta3.Port": { + "id": "v1beta3.Port", + "required": [ + "containerPort" + ], + "properties": { + "containerPort": { + "type": "integer", + "format": "int32" + }, + "hostIP": { + "type": "string" + }, + "hostPort": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "protocol": { + "type": "v1beta3.Protocol" + } + } + }, + "v1beta3.Probe": { + "id": "v1beta3.Probe", + "properties": { + "exec": { + "type": "v1beta3.ExecAction" + }, + "httpGet": { + "type": "v1beta3.HTTPGetAction" + }, + "initialDelaySeconds": { + "type": "integer", + "format": "int64" + }, + "tcpSocket": { + "type": "v1beta3.TCPSocketAction" + } + } + }, + "v1beta3.ReplicationController": { + "id": "v1beta3.ReplicationController", + "properties": { + "annotations": { + "type": "v1beta3.ObjectMeta.annotations" + }, + "apiVersion": { + "type": "string" + }, + "creationTimestamp": { + "type": "string" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "kind": { + "type": "string" + }, + "labels": { + "type": "v1beta3.ObjectMeta.labels" + }, + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + }, + "spec": { + "type": "v1beta3.ReplicationControllerSpec" + }, + "status": { + "type": "v1beta3.ReplicationControllerStatus" + }, + "uid": { + "type": "types.UID" + } + } + }, + "v1beta3.ReplicationControllerList": { + "id": "v1beta3.ReplicationControllerList", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "type": "string" + }, + "items": { + "type": "array", + "items": [ + { + "$ref": "v1beta3.ReplicationController" + } + ] + }, + "kind": { + "type": "string" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + } + } + }, + "v1beta3.ReplicationControllerSpec": { + "id": "v1beta3.ReplicationControllerSpec", + "required": [ + "replicas" + ], + "properties": { + "replicas": { + "type": "integer", + "format": "int32" + }, + "selector": { + "type": "v1beta3.ReplicationControllerSpec.selector" + }, + "template": { + "type": "v1beta3.PodTemplateSpec" + }, + "templateRef": { + "type": "v1beta3.ObjectReference" + } + } + }, + "v1beta3.ReplicationControllerSpec.selector": { + "id": "v1beta3.ReplicationControllerSpec.selector", + "properties": {} + }, + "v1beta3.ReplicationControllerStatus": { + "id": "v1beta3.ReplicationControllerStatus", + "required": [ + "replicas" + ], + "properties": { + "replicas": { + "type": "integer", + "format": "int32" + } + } + }, + "v1beta3.ResourceQuota": { + "id": "v1beta3.ResourceQuota", + "properties": { + "annotations": { + "type": "v1beta3.ObjectMeta.annotations" + }, + "apiVersion": { + "type": "string" + }, + "creationTimestamp": { + "type": "string" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "kind": { + "type": "string" + }, + "labels": { + "type": "v1beta3.ObjectMeta.labels" + }, + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + }, + "spec": { + "type": "v1beta3.ResourceQuotaSpec" + }, + "status": { + "type": "v1beta3.ResourceQuotaStatus" + }, + "uid": { + "type": "types.UID" + } + } + }, + "v1beta3.ResourceQuotaList": { + "id": "v1beta3.ResourceQuotaList", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "type": "string" + }, + "items": { + "type": "array", + "items": [ + { + "$ref": "v1beta3.ResourceQuota" + } + ] + }, + "kind": { + "type": "string" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + } + } + }, + "v1beta3.ResourceQuotaSpec": { + "id": "v1beta3.ResourceQuotaSpec", + "properties": { + "hard": { + "type": "v1beta3.ResourceList" + } + } + }, + "v1beta3.ResourceQuotaStatus": { + "id": "v1beta3.ResourceQuotaStatus", + "properties": { + "hard": { + "type": "v1beta3.ResourceList" + }, + "used": { + "type": "v1beta3.ResourceList" + } + } + }, + "v1beta3.ResourceQuotaUsage": { + "id": "v1beta3.ResourceQuotaUsage", + "properties": { + "annotations": { + "type": "v1beta3.ObjectMeta.annotations" + }, + "apiVersion": { + "type": "string" + }, + "creationTimestamp": { + "type": "string" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "kind": { + "type": "string" + }, + "labels": { + "type": "v1beta3.ObjectMeta.labels" + }, + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + }, + "status": { + "type": "v1beta3.ResourceQuotaStatus" + }, + "uid": { + "type": "types.UID" + } + } + }, + "v1beta3.ResourceRequirementSpec": { + "id": "v1beta3.ResourceRequirementSpec", + "properties": { + "limits": { + "type": "v1beta3.ResourceList", + "description": "Maximum amount of compute resources allowed" + } + } + }, + "v1beta3.RestartPolicy": { + "id": "v1beta3.RestartPolicy", + "properties": { + "always": { + "type": "v1beta3.RestartPolicyAlways" + }, + "never": { + "type": "v1beta3.RestartPolicyNever" + }, + "onFailure": { + "type": "v1beta3.RestartPolicyOnFailure" + } + } + }, + "v1beta3.RestartPolicyAlways": { + "id": "v1beta3.RestartPolicyAlways", + "properties": {} + }, + "v1beta3.RestartPolicyNever": { + "id": "v1beta3.RestartPolicyNever", + "properties": {} + }, + "v1beta3.RestartPolicyOnFailure": { + "id": "v1beta3.RestartPolicyOnFailure", + "properties": {} + }, + "v1beta3.Service": { + "id": "v1beta3.Service", + "properties": { + "annotations": { + "type": "v1beta3.ObjectMeta.annotations" + }, + "apiVersion": { + "type": "string" + }, + "creationTimestamp": { + "type": "string" + }, + "generateName": { + "type": "string", + "description": "an optional prefix to use to generate a unique name; has the same validation rules as name; optional, and is applied only name if is not specified" + }, + "kind": { + "type": "string" + }, + "labels": { + "type": "v1beta3.ObjectMeta.labels" + }, + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + }, + "spec": { + "type": "v1beta3.ServiceSpec" + }, + "status": { + "type": "v1beta3.ServiceStatus" + }, + "uid": { + "type": "types.UID" + } + } + }, + "v1beta3.ServiceSpec": { + "id": "v1beta3.ServiceSpec", + "required": [ + "port", + "selector" + ], + "properties": { + "containerPort": { + "type": "string" + }, + "createExternalLoadBalancer": { + "type": "boolean" + }, + "port": { + "type": "integer", + "format": "int32" + }, + "portalIP": { + "type": "string" + }, + "protocol": { + "type": "v1beta3.Protocol" + }, + "publicIPs": { + "type": "array", + "items": [ + { + "$ref": "string" + } + ] + }, + "selector": { + "type": "v1beta3.ServiceSpec.selector" + }, + "sessionAffinity": { + "type": "v1beta3.AffinityType" + } + } + }, + "v1beta3.ServiceSpec.selector": { + "id": "v1beta3.ServiceSpec.selector", + "properties": {} + }, + "v1beta3.ServiceStatus": { + "id": "v1beta3.ServiceStatus", + "properties": {} + }, + "v1beta3.TCPSocketAction": { + "id": "v1beta3.TCPSocketAction", + "properties": { + "port": { + "type": "string" + } + } + }, + "v1beta3.Volume": { + "id": "v1beta3.Volume", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "source": { + "type": "v1beta3.VolumeSource" + } + } + }, + "v1beta3.VolumeMount": { + "id": "v1beta3.VolumeMount", + "required": [ + "name", + "mountPath" + ], + "properties": { + "mountPath": { + "type": "string" + }, + "name": { + "type": "string" + }, + "readOnly": { + "type": "boolean" + } + } + }, + "v1beta3.VolumeSource": { + "id": "v1beta3.VolumeSource", + "required": [ + "hostPath", + "emptyDir", + "gcePersistentDisk", + "gitRepo" + ], + "properties": { + "emptyDir": { + "type": "v1beta3.EmptyDir" + }, + "gcePersistentDisk": { + "type": "v1beta3.GCEPersistentDisk" + }, + "gitRepo": { + "type": "v1beta3.GitRepo" + }, + "hostPath": { + "type": "v1beta3.HostPath" + } + } + } + } + } \ No newline at end of file diff --git a/api/swagger-spec/version.json b/api/swagger-spec/version.json new file mode 100644 index 00000000000..a6f262cfe8a --- /dev/null +++ b/api/swagger-spec/version.json @@ -0,0 +1,27 @@ +{ + "swaggerVersion": "1.2", + "apiVersion": "", + "basePath": "127.0.0.1:8050", + "resourcePath": "/version", + "apis": [ + { + "path": "/version", + "description": "git code version from which this is built", + "operations": [ + { + "type": "void", + "method": "GET", + "summary": "get the code version", + "nickname": "getCodeVersion", + "parameters": [], + "produces": [ + "application/json" + ], + "consumes": [ + "application/json" + ] + } + ] + } + ] + } \ No newline at end of file diff --git a/build/README.md b/build/README.md index b583f3ba323..c02146d8f41 100644 --- a/build/README.md +++ b/build/README.md @@ -34,7 +34,7 @@ The `release.sh` script will build a release. It will build binaries, run tests The main output is a tar file: `kubernetes.tar.gz`. This includes: * Cross compiled client utilities. -* Script (`cluster/kubecfg.sh`) for picking and running the right client binary based on platform. +* Script (`cluster/kubectl.sh`) for picking and running the right client binary based on platform. * Examples * Cluster deployment scripts for various clouds * Tar file containing all server binaries diff --git a/cluster/kube-up.sh b/cluster/kube-up.sh index 37d59d9f59d..6972ad80a70 100755 --- a/cluster/kube-up.sh +++ b/cluster/kube-up.sh @@ -46,3 +46,5 @@ echo "... calling setup-logging-firewall" >&2 setup-logging-firewall echo "Done" >&2 + +exit 0 diff --git a/cluster/kubectl.sh b/cluster/kubectl.sh index 9642c22e426..9a4ca11fdea 100755 --- a/cluster/kubectl.sh +++ b/cluster/kubectl.sh @@ -123,7 +123,7 @@ elif [[ "${KUBERNETES_PROVIDER}" == "gke" ]]; then ) fi -detect-master &> /dev/null +detect-master > /dev/null if [[ -n "${KUBE_MASTER_IP-}" && -z "${KUBERNETES_MASTER-}" ]]; then export KUBERNETES_MASTER=https://${KUBE_MASTER_IP} fi diff --git a/cmd/integration/integration.go b/cmd/integration/integration.go index 7a7ab6bf860..b4c47a3fcb8 100644 --- a/cmd/integration/integration.go +++ b/cmd/integration/integration.go @@ -96,7 +96,7 @@ func (fakeKubeletClient) GetPodStatus(host, podNamespace, podID string) (api.Pod return r, nil } -func (fakeKubeletClient) HealthCheck(host string) (probe.Status, error) { +func (fakeKubeletClient) HealthCheck(host string) (probe.Result, error) { return probe.Success, nil } diff --git a/cmd/kubernetes/kubernetes.go b/cmd/kubernetes/kubernetes.go index 9eb08284f56..e01fabd565e 100644 --- a/cmd/kubernetes/kubernetes.go +++ b/cmd/kubernetes/kubernetes.go @@ -33,6 +33,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/client" nodeControllerPkg "github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider/controller" "github.com/GoogleCloudPlatform/kubernetes/pkg/controller" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/dockertools" kubeletServer "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/server" "github.com/GoogleCloudPlatform/kubernetes/pkg/master" "github.com/GoogleCloudPlatform/kubernetes/pkg/master/ports" @@ -139,7 +140,7 @@ func startComponents(etcdClient tools.EtcdClient, cl *client.Client, addr net.IP runScheduler(cl) runControllerManager(machineList, cl, *nodeMilliCPU, *nodeMemory) - dockerClient := util.ConnectToDockerOrDie(*dockerEndpoint) + dockerClient := dockertools.ConnectToDockerOrDie(*dockerEndpoint) kubeletServer.SimpleRunKubelet(cl, nil, dockerClient, machineList[0], "/tmp/kubernetes", "", "127.0.0.1", 10250, *masterServiceNamespace, kubeletServer.ProbeVolumePlugins()) } diff --git a/contrib/git-sync/Dockerfile b/contrib/git-sync/Dockerfile new file mode 100644 index 00000000000..6929d15b454 --- /dev/null +++ b/contrib/git-sync/Dockerfile @@ -0,0 +1,4 @@ +FROM golang:1.4-onbuild +VOLUME ["/git"] +ENV GIT_SYNC_DEST /git +ENTRYPOINT ["/go/bin/git-sync"] diff --git a/contrib/git-sync/README.md b/contrib/git-sync/README.md new file mode 100644 index 00000000000..f8faa4a0cd1 --- /dev/null +++ b/contrib/git-sync/README.md @@ -0,0 +1,16 @@ +# git-sync + +git-sync is a command that pull a git repository to a local directory. + +It can be used to source a container volume with the content of a git repo. + +## Usage + +``` +# build the container +docker build -t git-sync . +# run the git-sync container +docker run -d GIT_SYNC_REPO=https://github.com/GoogleCloudPlatform/kubernetes -e GIT_SYNC_BRANCH=gh-pages -r HEAD -v /git-data:/git git-sync +# run a nginx container to serve sync'ed content +docker run -d -p 8080:80 -v /git-data:/usr/share/nginx/html nginx +``` diff --git a/contrib/git-sync/demo/README.md b/contrib/git-sync/demo/README.md new file mode 100644 index 00000000000..e2a72465b56 --- /dev/null +++ b/contrib/git-sync/demo/README.md @@ -0,0 +1,30 @@ +# git-blog-demo + +This demo shows how to use the `git-sync` sidekick container along side `volumes` and `volumeMounts` to create a markdown powered blog. + +## How it works + +The pod is composed of 3 containers that share directories using 2 volumes: + +- The `git-sync` container clones a git repo into the `markdown` volume +- The `hugo` container read from the `markdown` volume and render it into the `html` volume. +- The `nginx` container serve the content from the `html` volume. + +## Usage + +Build the demo containers, and push them to a registry + +``` +docker build -t /git-sync .. +docker build -t /hugo hugo/ +docker push /hugo /git-sync +``` + +Create the pod and the service for the blog + +``` +kubectl pods create config/pod.html +kubectl services create config/pod.html +``` + +Open the service external ip in your browser diff --git a/contrib/git-sync/demo/blog/archetypes/.keep b/contrib/git-sync/demo/blog/archetypes/.keep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/contrib/git-sync/demo/blog/config.toml b/contrib/git-sync/demo/blog/config.toml new file mode 100644 index 00000000000..ab3aa9e446e --- /dev/null +++ b/contrib/git-sync/demo/blog/config.toml @@ -0,0 +1,3 @@ +baseurl = "http://example.com" +languageCode = "en-us" +title = "example blog" diff --git a/contrib/git-sync/demo/blog/content/about.md b/contrib/git-sync/demo/blog/content/about.md new file mode 100644 index 00000000000..afb2ac0f4bb --- /dev/null +++ b/contrib/git-sync/demo/blog/content/about.md @@ -0,0 +1,9 @@ ++++ +date = "2014-12-19T15:29:48-08:00" +draft = true +title = "about" ++++ + +## A headline + +Some content about the blog. diff --git a/contrib/git-sync/demo/blog/content/post/first.md b/contrib/git-sync/demo/blog/content/post/first.md new file mode 100644 index 00000000000..630bbbd01d3 --- /dev/null +++ b/contrib/git-sync/demo/blog/content/post/first.md @@ -0,0 +1,9 @@ ++++ +date = "2014-12-19T15:30:18-08:00" +draft = true +title = "first" ++++ + +## first port + +This is the first post. diff --git a/contrib/git-sync/demo/blog/layouts/.keep b/contrib/git-sync/demo/blog/layouts/.keep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/contrib/git-sync/demo/blog/static/.keep b/contrib/git-sync/demo/blog/static/.keep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/contrib/git-sync/demo/config/pod.yaml b/contrib/git-sync/demo/config/pod.yaml new file mode 100644 index 00000000000..75ff074c18b --- /dev/null +++ b/contrib/git-sync/demo/config/pod.yaml @@ -0,0 +1,50 @@ +id: blog-pod +kind: Pod +apiVersion: v1beta1 +desiredState: + manifest: + version: v1beta1 + containers: + - name: git-sync + image: proppy/git-sync + imagePullPolicy: PullAlways + env:: + - name: GIT_SYNC_REPO + value: https://github.com/proppy/blog.git + - name: GIT_SYNC_DEST + value: /git + volumeMounts: + - name: markdown + mountPath: /git + - name: hugo + image: proppy/hugo + imagePullPolicy: PullAlways + env: + - name: SRC + value: /src + - name: BUILD_DRAFT + value: 'true' + - name: BASE_URL + value: kube.proppy.sh + volumeMounts: + - name: markdown + mountPath: /src + - name: html + mountPath: /dest + - name: nginx + image: nginx + volumeMounts: + - name: html + mountPath: /usr/share/nginx/html + ports: + - name: http-server + containerPort: 80 + volumes: + - name: markdown + source: + emptyDir: {} + - name: html + source: + emptyDir: {} +labels: + name: blog diff --git a/contrib/git-sync/demo/config/service.yaml b/contrib/git-sync/demo/config/service.yaml new file mode 100644 index 00000000000..646b4c59aa6 --- /dev/null +++ b/contrib/git-sync/demo/config/service.yaml @@ -0,0 +1,8 @@ +id: blog-service +kind: Service +apiVersion: v1beta1 +port: 80 +containerPort: http-server +selector: + name: blog +createExternalLoadBalancer: true diff --git a/contrib/git-sync/demo/hugo/Dockerfile b/contrib/git-sync/demo/hugo/Dockerfile new file mode 100644 index 00000000000..40af5e67ed8 --- /dev/null +++ b/contrib/git-sync/demo/hugo/Dockerfile @@ -0,0 +1,13 @@ +FROM golang +RUN go get -v github.com/spf13/hugo +RUN git clone --recursive https://github.com/spf13/hugoThemes.git /themes +VOLUME ["/src", "/dest"] +EXPOSE 1313 +ENV SRC /src +ENV DEST /dest +ENV THEME hyde +ENV BUILD_DRAFT false +ENV BASE_URL "" +ADD run-hugo /run-hugo +ENTRYPOINT ["/run-hugo"] +CMD ["server", "--source=${SRC}", "--theme=${THEME}", "--buildDrafts=${BUILD_DRAFT}", "--baseUrl=${BASE_URL}", "--watch", "--destination=${DEST}", "--appendPort=false"] diff --git a/cluster/test-network.sh b/contrib/git-sync/demo/hugo/run-hugo similarity index 71% rename from cluster/test-network.sh rename to contrib/git-sync/demo/hugo/run-hugo index 0480e137eb6..37636025523 100755 --- a/cluster/test-network.sh +++ b/contrib/git-sync/demo/hugo/run-hugo @@ -14,12 +14,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -set -o errexit -set -o nounset -set -o pipefail - -KUBE_ROOT=$(dirname "${BASH_SOURCE}")/.. -source "${KUBE_ROOT}/cluster/kube-env.sh" -source "${KUBE_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh" - -${KUBE_ROOT}/hack/e2e-suite/goe2e.sh -tTestNetwork +set -ex +if [ ! -d ${SRC}/themes ]; then + ln -s /themes ${SRC}/themes +fi +hugo $(eval echo $*) # force default CMD env expansion diff --git a/contrib/git-sync/main.go b/contrib/git-sync/main.go new file mode 100644 index 00000000000..7667e8df7a5 --- /dev/null +++ b/contrib/git-sync/main.go @@ -0,0 +1,112 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +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. +*/ + +// git-sync is a command that pull a git repository to a local directory. + +package main // import "github.com/GoogleCloudPlatform/kubernetes/contrib/git-sync" + +import ( + "flag" + "fmt" + "log" + "os" + "os/exec" + "path" + "strconv" + "strings" + "time" +) + +var flRepo = flag.String("repo", envString("GIT_SYNC_REPO", ""), "git repo url") +var flBranch = flag.String("branch", envString("GIT_SYNC_BRANCH", "master"), "git branch") +var flRev = flag.String("rev", envString("GIT_SYNC_BRANCH", "HEAD"), "git rev") +var flDest = flag.String("dest", envString("GIT_SYNC_DEST", ""), "destination path") +var flWait = flag.Int("wait", envInt("GIT_SYNC_WAIT", 0), "number of seconds to wait before exit") + +func envString(key, def string) string { + if env := os.Getenv(key); env != "" { + return env + } + return def +} + +func envInt(key string, def int) int { + if env := os.Getenv(key); env != "" { + val, err := strconv.Atoi(env) + if err != nil { + log.Println("invalid value for %q: using default: %q", key, def) + return def + } + return val + } + return def +} + +const usage = "usage: GIT_SYNC_REPO= GIT_SYNC_DEST= [GIT_SYNC_BRANCH= GIT_SYNC_WAIT=] git-sync -repo GIT_REPO_URL -dest PATH [-branch -wait]" + +func main() { + flag.Parse() + if *flRepo == "" || *flDest == "" { + flag.Usage() + log.Fatal(usage) + } + if _, err := exec.LookPath("git"); err != nil { + log.Fatalf("required git executable not found: %v", err) + } + if err := syncRepo(*flRepo, *flDest, *flBranch, *flRev); err != nil { + log.Fatalf("error syncing repo: %v", err) + } + log.Printf("wait %d seconds", *flWait) + time.Sleep(time.Duration(*flWait) * time.Second) + log.Println("done") +} + +// syncRepo syncs the branch of a given repository to the destination at the given rev. +func syncRepo(repo, dest, branch, rev string) error { + gitRepoPath := path.Join(dest, ".git") + _, err := os.Stat(gitRepoPath) + switch { + case os.IsNotExist(err): + // clone repo + cmd := exec.Command("git", "clone", "--no-checkout", "-b", branch, repo, dest) + output, err := cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("error cloning repo %q: %v: %s", strings.Join(cmd.Args, " "), err, string(output)) + } + log.Printf("clone %q: %s", repo, string(output)) + case err != nil: + return fmt.Errorf("error checking if repo exist %q: %v", gitRepoPath, err) + } + + // fetch branch + cmd := exec.Command("git", "fetch", "origin", branch) + cmd.Dir = dest + output, err := cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("error running command %q: %v: %s", strings.Join(cmd.Args, " "), err, string(output)) + } + log.Printf("fetch %q: %s", branch, string(output)) + + // reset working copy + cmd = exec.Command("git", "reset", "--hard", rev) + cmd.Dir = dest + output, err = cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("error running command %q : %v: %s", strings.Join(cmd.Args, " "), err, string(output)) + } + log.Printf("reset %q: %v", rev, string(output)) + return nil +} diff --git a/contrib/init/systemd/kube-apiserver.service b/contrib/init/systemd/kube-apiserver.service index eef9fbf96fa..7d947fe9cae 100644 --- a/contrib/init/systemd/kube-apiserver.service +++ b/contrib/init/systemd/kube-apiserver.service @@ -7,15 +7,15 @@ EnvironmentFile=-/etc/kubernetes/config EnvironmentFile=-/etc/kubernetes/apiserver User=kube ExecStart=/usr/bin/kube-apiserver \ - ${KUBE_LOGTOSTDERR} \ - ${KUBE_LOG_LEVEL} \ - ${KUBE_ETCD_SERVERS} \ - ${KUBE_API_ADDRESS} \ - ${KUBE_API_PORT} \ - ${KUBELET_PORT} \ - ${KUBE_ALLOW_PRIV} \ - ${KUBE_SERVICE_ADDRESSES} \ - ${KUBE_API_ARGS} + $KUBE_LOGTOSTDERR \ + $KUBE_LOG_LEVEL \ + $KUBE_ETCD_SERVERS \ + $KUBE_API_ADDRESS \ + $KUBE_API_PORT \ + $KUBELET_PORT \ + $KUBE_ALLOW_PRIV \ + $KUBE_SERVICE_ADDRESSES \ + $KUBE_API_ARGS Restart=on-failure [Install] diff --git a/contrib/init/systemd/kube-controller-manager.service b/contrib/init/systemd/kube-controller-manager.service index 14d5ee5825d..872115c4f97 100644 --- a/contrib/init/systemd/kube-controller-manager.service +++ b/contrib/init/systemd/kube-controller-manager.service @@ -8,11 +8,11 @@ EnvironmentFile=-/etc/kubernetes/apiserver EnvironmentFile=-/etc/kubernetes/controller-manager User=kube ExecStart=/usr/bin/kube-controller-manager \ - ${KUBE_LOGTOSTDERR} \ - ${KUBE_LOG_LEVEL} \ - ${KUBELET_ADDRESSES} \ - ${KUBE_MASTER} \ - ${KUBE_CONTROLLER_MANAGER_ARGS} + $KUBE_LOGTOSTDERR \ + $KUBE_LOG_LEVEL \ + $KUBELET_ADDRESSES \ + $KUBE_MASTER \ + $KUBE_CONTROLLER_MANAGER_ARGS Restart=on-failure [Install] diff --git a/contrib/init/systemd/kube-proxy.service b/contrib/init/systemd/kube-proxy.service index fcfc2e276c0..921f4ceee33 100644 --- a/contrib/init/systemd/kube-proxy.service +++ b/contrib/init/systemd/kube-proxy.service @@ -6,10 +6,10 @@ Documentation=https://github.com/GoogleCloudPlatform/kubernetes EnvironmentFile=-/etc/kubernetes/config EnvironmentFile=-/etc/kubernetes/proxy ExecStart=/usr/bin/kube-proxy \ - ${KUBE_LOGTOSTDERR} \ - ${KUBE_LOG_LEVEL} \ - ${KUBE_ETCD_SERVERS} \ - ${KUBE_PROXY_ARGS} + $KUBE_LOGTOSTDERR \ + $KUBE_LOG_LEVEL \ + $KUBE_ETCD_SERVERS \ + $KUBE_PROXY_ARGS Restart=on-failure [Install] diff --git a/contrib/init/systemd/kube-scheduler.service b/contrib/init/systemd/kube-scheduler.service index 7ca88417e8f..f04666ebf7f 100644 --- a/contrib/init/systemd/kube-scheduler.service +++ b/contrib/init/systemd/kube-scheduler.service @@ -8,10 +8,10 @@ EnvironmentFile=-/etc/kubernetes/apiserver EnvironmentFile=-/etc/kubernetes/scheduler User=kube ExecStart=/usr/bin/kube-scheduler \ - ${KUBE_LOGTOSTDERR} \ - ${KUBE_LOG_LEVEL} \ - ${KUBE_MASTER} \ - ${KUBE_SCHEDULER_ARGS} + $KUBE_LOGTOSTDERR \ + $KUBE_LOG_LEVEL \ + $KUBE_MASTER \ + $KUBE_SCHEDULER_ARGS Restart=on-failure [Install] diff --git a/contrib/init/systemd/kubelet.service b/contrib/init/systemd/kubelet.service index 973db5b608e..9c43f50ef1c 100644 --- a/contrib/init/systemd/kubelet.service +++ b/contrib/init/systemd/kubelet.service @@ -9,14 +9,14 @@ WorkingDirectory=/var/lib/kubelet EnvironmentFile=-/etc/kubernetes/config EnvironmentFile=-/etc/kubernetes/kubelet ExecStart=/usr/bin/kubelet \ - ${KUBE_LOGTOSTDERR} \ - ${KUBE_LOG_LEVEL} \ - ${KUBE_ETCD_SERVERS} \ - ${KUBELET_ADDRESS} \ - ${KUBELET_PORT} \ - ${KUBELET_HOSTNAME} \ - ${KUBE_ALLOW_PRIV} \ - ${KUBELET_ARGS} + $KUBE_LOGTOSTDERR \ + $KUBE_LOG_LEVEL \ + $KUBE_ETCD_SERVERS \ + $KUBELET_ADDRESS \ + $KUBELET_PORT \ + $KUBELET_HOSTNAME \ + $KUBE_ALLOW_PRIV \ + $KUBELET_ARGS Restart=on-failure [Install] diff --git a/docs/getting-started-guides/aws-coreos.md b/docs/getting-started-guides/aws-coreos.md index 240b61a6fa4..83132c1bf7f 100644 --- a/docs/getting-started-guides/aws-coreos.md +++ b/docs/getting-started-guides/aws-coreos.md @@ -14,7 +14,7 @@ The example below creates an elastic Kubernetes cluster with 3 worker nodes and ## Prerequisites -* [kubecfg CLI](aws/kubecfg.md) +* [kubectl CLI](aws/kubectl.md) * [aws CLI](http://aws.amazon.com/cli) * [CoreOS image for AWS](https://coreos.com/docs/running-coreos/cloud-providers/ec2/#choosing-a-channel) @@ -42,7 +42,7 @@ aws cloudformation describe-stack-events --stack-name kubernetes aws cloudformation describe-stacks --stack-name kubernetes ``` -[Skip to kubecfg client configuration](#configure-the-kubecfg-ssh-tunnel) +[Skip to kubectl client configuration](#configure-the-kubectl-ssh-tunnel) ### Manually @@ -121,9 +121,9 @@ aws ec2 run-instances --count 1 --image-id --key-name \ --user-data file://node.yaml ``` -### Configure the kubecfg SSH tunnel +### Configure the kubectl SSH tunnel -This command enables secure communication between the kubecfg client and the Kubernetes API. +This command enables secure communication between the kubectl client and the Kubernetes API. ``` ssh -f -nNT -L 8080:127.0.0.1:8080 core@ @@ -134,7 +134,7 @@ ssh -f -nNT -L 8080:127.0.0.1:8080 core@ Once the worker instances have fully booted, they will be automatically registered with the Kubernetes API server by the kube-register service running on the master node. It may take a few mins. ``` -kubecfg list minions +kubectl get nodes ``` ## Starting a simple pod @@ -167,16 +167,16 @@ Create a pod manifest: `pod.json` } ``` -### Create the pod using the kubecfg command line tool +### Create the pod using the kubectl command line tool ``` -kubecfg -c pod.json create pods +kubectl create -f pod.json ``` ### Testing ``` -kubecfg list pods +kubectl get pods ``` > Record the **Host** of the pod, which should be the private IP address. @@ -208,5 +208,5 @@ Visit the public IP address in your browser to view the running pod. ### Delete the pod ``` -kubecfg delete pods/hello +kubectl delete pods hello ``` diff --git a/docs/getting-started-guides/aws/cloudformation-template.json b/docs/getting-started-guides/aws/cloudformation-template.json index 87eab68c9c1..510f9f155c0 100644 --- a/docs/getting-started-guides/aws/cloudformation-template.json +++ b/docs/getting-started-guides/aws/cloudformation-template.json @@ -247,7 +247,7 @@ " ExecStart=/opt/bin/kube-apiserver \\\n", " --address=0.0.0.0 \\\n", " --port=8080 \\\n", - " --portal_net 10.244.0.0/16 \\\n", + " --portal_net=10.244.0.0/16 \\\n", " --etcd_servers=http://127.0.0.1:4001 \\\n", " --public_address_override=$private_ipv4 \\\n", " --logtostderr=true\n", diff --git a/docs/getting-started-guides/aws/kubecfg.md b/docs/getting-started-guides/aws/kubecfg.md deleted file mode 100644 index 2b6a24e0618..00000000000 --- a/docs/getting-started-guides/aws/kubecfg.md +++ /dev/null @@ -1,28 +0,0 @@ -# Install and configure kubecfg - -## Download the kubecfg CLI tool - -### Darwin - -``` -wget http://storage.googleapis.com/k8s/darwin/kubecfg -``` - -### Linux - -``` -wget http://storage.googleapis.com/k8s/linux/kubecfg -``` - -### Copy kubecfg to your path - -``` -chmod +x kubecfg -mv kubecfg /usr/local/bin/ -``` - -### Create a secure tunnel for API communication - -``` -ssh -f -nNT -L 8080:127.0.0.1:8080 core@ -``` diff --git a/docs/getting-started-guides/aws/kubectl.md b/docs/getting-started-guides/aws/kubectl.md new file mode 100644 index 00000000000..0f93d2c46d6 --- /dev/null +++ b/docs/getting-started-guides/aws/kubectl.md @@ -0,0 +1,28 @@ +# Install and configure kubecfg + +## Download the kubecfg CLI tool + +### Darwin + +``` +wget https://storage.googleapis.com/kubernetes-release/release/v0.9.2/bin/darwin/amd64/kubectl +``` + +### Linux + +``` +wget https://storage.googleapis.com/kubernetes-release/release/v0.9.2/bin/linux/amd64/kubectl +``` + +### Copy kubectl to your path + +``` +chmod +x kubectl +mv kubectl /usr/local/bin/ +``` + +### Create a secure tunnel for API communication + +``` +ssh -f -nNT -L 8080:127.0.0.1:8080 core@ +``` diff --git a/docs/getting-started-guides/azure.md b/docs/getting-started-guides/azure.md index 1d9c75ac373..4eb1ef51cde 100644 --- a/docs/getting-started-guides/azure.md +++ b/docs/getting-started-guides/azure.md @@ -34,21 +34,26 @@ can tweak some of these parameters by editing `cluster/azure/config-default.sh`. ### Running a container (simple version) -The `cluster/kubecfg.sh` command below spins up two containers, running [Nginx](http://nginx.org/en/) and with port 80 mapped to 8080: +Once you have your instances up and running, the `hack/build-go.sh` script sets up +your Go workspace and builds the Go components. -``` -cd kubernetes -cluster/kubecfg.sh -p 8080:80 run dockerfile/nginx 2 myNginx +The `kubectl.sh` line below spins up two containers running +[Nginx](http://nginx.org/en/) running on port 80: + +```bash +cluster/kubectl.sh run-container my-nginx --image=dockerfile/nginx --replicas=2 --port=80 ``` To stop the containers: -``` -cluster/kubecfg.sh stop myNginx + +```bash +cluster/kubectl.sh stop rc my-nginx ``` To delete the containers: -``` -cluster/kubecfg.sh rm myNginx + +```bash +cluster/kubectl.sh delete rc my-nginx ``` ### Running a container (more complete version) diff --git a/docs/getting-started-guides/gce.md b/docs/getting-started-guides/gce.md index 7c6c368dd7c..4cb4ce19905 100644 --- a/docs/getting-started-guides/gce.md +++ b/docs/getting-started-guides/gce.md @@ -50,23 +50,23 @@ field values: Once you have your instances up and running, the `hack/build-go.sh` script sets up your Go workspace and builds the Go components. -The `kubecfg.sh` line below spins up two containers running -[Nginx](http://nginx.org/en/) with port 80 mapped to 8080: +The `kubectl.sh` line below spins up two containers running +[Nginx](http://nginx.org/en/) running on port 80: ```bash -cluster/kubecfg.sh -p 8080:80 run dockerfile/nginx 2 myNginx +cluster/kubectl.sh run-container my-nginx --image=dockerfile/nginx --replicas=2 --port=80 ``` To stop the containers: ```bash -cluster/kubecfg.sh stop myNginx +cluster/kubectl.sh stop rc my-nginx ``` To delete the containers: ```bash -cluster/kubecfg.sh rm myNginx +cluster/kubectl.sh delete rc my-nginx ``` ### Running a container (more complete version) diff --git a/docs/getting-started-guides/locally.md b/docs/getting-started-guides/locally.md index a7120f42f3a..40e6cf6fd60 100644 --- a/docs/getting-started-guides/locally.md +++ b/docs/getting-started-guides/locally.md @@ -30,7 +30,7 @@ hack/local-up-cluster.sh This will build and start a lightweight local cluster, consisting of a master and a single minion. Type Control-C to shut it down. -You can use the cluster/kubecfg.sh script to interact with the local cluster. +You can use the cluster/kubectl.sh script to interact with the local cluster. You must set the KUBERNETES_PROVIDER and KUBERNETES_MASTER environment variables to let other programs know how to reach your master. @@ -43,13 +43,13 @@ export KUBERNETES_MASTER=http://localhost:8080 Your cluster is running, and you want to start running containers! -You can now use any of the cluster/kubecfg.sh commands to interact with your local setup. +You can now use any of the cluster/kubectl.sh commands to interact with your local setup. ``` cluster/kubectl.sh get pods cluster/kubectl.sh get services cluster/kubectl.sh get replicationControllers -cluster/kubecfg.sh -p 8081:80 run dockerfile/nginx 1 myNginx +cluster/kubectl.sh run-container my-nginx --image=dockerfile/nginx --replicas=2 --port=80 ## begin wait for provision to complete, you can monitor the docker pull by opening a new terminal diff --git a/docs/getting-started-guides/ubuntu_single_node.md b/docs/getting-started-guides/ubuntu_single_node.md index b244eb1275f..a84f11b7dd5 100644 --- a/docs/getting-started-guides/ubuntu_single_node.md +++ b/docs/getting-started-guides/ubuntu_single_node.md @@ -25,7 +25,7 @@ $ sudo ./util.sh After this the kubernetes and `etcd` services would be up and running. You can use `service start/stop/restart/force-reload` on the services. -Launching and scheduling containers using kubecfg can also be used at this point, as explained mentioned in the [examples](https://github.com/GoogleCloudPlatform/kubernetes/tree/master/examples/guestbook) +Launching and scheduling containers using kubectl can also be used at this point, as explained mentioned in the [examples](https://github.com/GoogleCloudPlatform/kubernetes/tree/master/examples/guestbook) ### 3. Customizing the ubuntu launch To customize the defaults you will need to tweak `/etc/default/kube*` files and restart the appropriate services. This is needed if the binaries are copied in a place other than `/opt/bin`. A run could look like diff --git a/docs/getting-started-guides/vagrant.md b/docs/getting-started-guides/vagrant.md index 4d27fd572ed..8f7ab7ba786 100644 --- a/docs/getting-started-guides/vagrant.md +++ b/docs/getting-started-guides/vagrant.md @@ -178,10 +178,9 @@ NAME IMAGE(S SELECTOR REPLICAS ``` Start a container running nginx with a replication controller and three replicas -(note that this step uses the `kubecfg.sh` command instead of `kubectl.sh`): ``` -$ cluster/kubecfg.sh -p 8080:80 run dockerfile/nginx 3 myNginx +$ cluster/kubectl.sh run-container my-nginx --image=dockerfile/nginx --replicas=3 --port=80 ``` When listing the pods, you will see that three containers have been started and are in Waiting state: @@ -231,7 +230,7 @@ NAME LABELS SELECTOR IP PORT $ cluster/kubectl.sh get replicationControllers NAME IMAGE(S SELECTOR REPLICAS -myNginx dockerfile/nginx name=myNginx 3 +myNginx dockerfile/nginx name=my-nginx 3 ``` We did not start any services, hence there are none listed. But we see three replicas displayed properly. @@ -239,7 +238,7 @@ Check the [guestbook](../../examples/guestbook/README.md) application to learn h You can already play with resizing the replicas with: ``` -$ cluster/kubecfg.sh resize myNginx 2 +$ cluster/kubectl.sh resize rc my-nginx --replicas=2 $ cluster/kubectl.sh get pods NAME IMAGE(S) HOST LABELS STATUS 7813c8bd-3ffe-11e4-9036-0800279696e1 dockerfile/nginx 10.245.2.2/10.245.2.2 name=myNginx Running diff --git a/docs/kubectl.md b/docs/kubectl.md index b04dee7703e..992cf657a41 100644 --- a/docs/kubectl.md +++ b/docs/kubectl.md @@ -73,7 +73,8 @@ Usage: --v=0: log level for V logs --validate=false: If true, use a schema to validate the input before sending it --vmodule=: comma-separated list of pattern=N settings for file-filtered logging - -w, --www="": Also serve static files from the given directory under the prefix /static + -w, --www="": Also serve static files from the given directory under the specified prefix + -P, --www-prefix="/static/": Prefix to serve static files under, if static file dir is specified ``` @@ -337,7 +338,7 @@ Usage: kubectl config [command] Available Commands: - view displays the specified .kubeconfig file or a merged result + view displays merged .kubeconfig settings or a specified .kubeconfig file. set-cluster name [--server=server] [--certificate-authority=path/to/certficate/authority] [--api-version=apiversion] [--insecure-skip-tls-verify=true] Sets a cluster entry in .kubeconfig set-credentials name [--auth-path=path/to/auth/file] [--client-certificate=path/to/certficate/file] [--client-key=path/to/key/file] [--token=bearer_token_string] Sets a user entry in .kubeconfig set-context name [--cluster=cluster-nickname] [--user=user-nickname] [--namespace=namespace] Sets a context entry in .kubeconfig @@ -394,7 +395,13 @@ Use "kubectl help [command]" for more information about that command. ``` #### config view -displays the specified .kubeconfig file or a merged result +displays merged .kubeconfig settings or a specified .kubeconfig file. +Examples: + // Show merged .kubeconfig settings. + $ kubectl config view + + // Show only local ./.kubeconfig settings + $ kubectl config view --local Usage: ``` @@ -420,10 +427,14 @@ Usage: --log_flush_frequency=5s: Maximum number of seconds between log flushes --logtostderr=true: log to standard error instead of files --match-server-version=false: Require server version to match client version - --merge=false: merge together the full hierarchy of .kubeconfig files + --merge=true: merge together the full hierarchy of .kubeconfig files --namespace="": If present, the namespace scope for this CLI request. + --no-headers=false: When using the default output, don't print headers + -o, --output="": Output format: json|yaml|template|templatefile + --output-version="": Output the formatted object with the given version (default api-version) -s, --server="": The address of the Kubernetes API server --stderrthreshold=2: logs at or above this threshold go to stderr + -t, --template="": Template string or path to template file to use when -o=template or -o=templatefile. --token="": Bearer token for authentication to the API server. --user="": The name of the kubeconfig user to use --v=0: log level for V logs diff --git a/docs/labels.md b/docs/labels.md index 46a9b00ec97..9f9d4ee3629 100644 --- a/docs/labels.md +++ b/docs/labels.md @@ -11,6 +11,15 @@ key/value labels set on it, with at most one label with a particular key. } ``` +While there are no restrictions on the format of label values, label keys must be of the form: +``` +label-key ::= prefixed-name | name +prefixed-name ::= prefix '/' name +prefix ::= DNS_SUBDOMAIN +name ::= DNS_LABEL +``` +DNS_LABEL and DNS_SUBDOMAIN are defined in the [identifiers design doc](/docs/design/identifiers.md). The prefix is optional. If the prefix is not specified, the key is assumed to be private to the user. Other system components that wish to use labels must specify a prefix. The "kubernetes.io/" prefix is reserved for use by kubernetes components. + Unlike [names and UIDs](identifiers.md), labels do not provide uniqueness. In general, we expect many objects to carry the same label(s). Via a _label selector_, the client/user can identify a set of objects. The label selector is the core grouping primitive in Kubernetes. diff --git a/examples/guestbook/README.md b/examples/guestbook/README.md index 61fb160a994..177f5b3632b 100644 --- a/examples/guestbook/README.md +++ b/examples/guestbook/README.md @@ -6,7 +6,7 @@ The example combines a web frontend, a redis master for storage and a replicated ### Step Zero: Prerequisites -This example assumes that have a basic understanding of kubernetes services and that you have forked the repository and [turned up a Kubernetes cluster](https://github.com/GoogleCloudPlatform/kubernetes#contents): +This example assumes that you have a basic understanding of kubernetes services and that you have forked the repository and [turned up a Kubernetes cluster](https://github.com/GoogleCloudPlatform/kubernetes#contents): ```shell $ cd kubernetes diff --git a/hack/e2e-suite/certs.sh b/hack/e2e-suite/certs.sh index 782e4ff7099..fb1574be20d 100755 --- a/hack/e2e-suite/certs.sh +++ b/hack/e2e-suite/certs.sh @@ -22,8 +22,17 @@ set -o nounset set -o pipefail KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../.. + +: ${KUBE_VERSION_ROOT:=${KUBE_ROOT}} +: ${KUBECTL:="${KUBE_VERSION_ROOT}/cluster/kubectl.sh"} +: ${KUBE_CONFIG_FILE:="config-test.sh"} + +export KUBECTL KUBE_CONFIG_FILE + source "${KUBE_ROOT}/cluster/kube-env.sh" -source "${KUBE_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh" +source "${KUBE_VERSION_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh" + +prepare-e2e if [[ "${KUBERNETES_PROVIDER}" != "gce" ]] && [[ "${KUBERNETES_PROVIDER}" != "gke" ]]; then echo "WARNING: Skipping certs.sh for cloud provider: ${KUBERNETES_PROVIDER}." diff --git a/hack/e2e-suite/guestbook.sh b/hack/e2e-suite/guestbook.sh index 8b348b36fe2..274194fc373 100755 --- a/hack/e2e-suite/guestbook.sh +++ b/hack/e2e-suite/guestbook.sh @@ -23,8 +23,17 @@ set -o nounset set -o pipefail KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../.. + +: ${KUBE_VERSION_ROOT:=${KUBE_ROOT}} +: ${KUBECTL:="${KUBE_VERSION_ROOT}/cluster/kubectl.sh"} +: ${KUBE_CONFIG_FILE:="config-test.sh"} + +export KUBECTL KUBE_CONFIG_FILE + source "${KUBE_ROOT}/cluster/kube-env.sh" -source "${KUBE_ROOT}/cluster/$KUBERNETES_PROVIDER/util.sh" +source "${KUBE_VERSION_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh" + +prepare-e2e GUESTBOOK="${KUBE_ROOT}/examples/guestbook" diff --git a/hack/e2e-suite/liveness.sh b/hack/e2e-suite/liveness.sh index 7178430289f..cb78dfe6364 100755 --- a/hack/e2e-suite/liveness.sh +++ b/hack/e2e-suite/liveness.sh @@ -22,8 +22,17 @@ set -o nounset set -o pipefail KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../.. + +: ${KUBE_VERSION_ROOT:=${KUBE_ROOT}} +: ${KUBECTL:="${KUBE_VERSION_ROOT}/cluster/kubectl.sh"} +: ${KUBE_CONFIG_FILE:="config-test.sh"} + +export KUBECTL KUBE_CONFIG_FILE + source "${KUBE_ROOT}/cluster/kube-env.sh" -source "${KUBE_ROOT}/cluster/$KUBERNETES_PROVIDER/util.sh" +source "${KUBE_VERSION_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh" + +prepare-e2e liveness_tests="http exec" if [[ ${KUBERNETES_PROVIDER} == "gke" ]]; then diff --git a/hack/e2e-suite/monitoring.sh b/hack/e2e-suite/monitoring.sh index 78df2d8a67d..d999af4fda3 100755 --- a/hack/e2e-suite/monitoring.sh +++ b/hack/e2e-suite/monitoring.sh @@ -23,8 +23,17 @@ set -o nounset set -o pipefail KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../.. + +: ${KUBE_VERSION_ROOT:=${KUBE_ROOT}} +: ${KUBECTL:="${KUBE_VERSION_ROOT}/cluster/kubectl.sh"} +: ${KUBE_CONFIG_FILE:="config-test.sh"} + +export KUBECTL KUBE_CONFIG_FILE + source "${KUBE_ROOT}/cluster/kube-env.sh" -source "${KUBE_ROOT}/cluster/$KUBERNETES_PROVIDER/util.sh" +source "${KUBE_VERSION_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh" + +prepare-e2e MONITORING="${KUBE_ROOT}/cluster/addons/cluster-monitoring" KUBECTL="${KUBE_ROOT}/cluster/kubectl.sh" diff --git a/hack/e2e-suite/pd.sh b/hack/e2e-suite/pd.sh index 673e69d2fe4..2910023021a 100755 --- a/hack/e2e-suite/pd.sh +++ b/hack/e2e-suite/pd.sh @@ -22,8 +22,17 @@ set -o nounset set -o pipefail KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../.. + +: ${KUBE_VERSION_ROOT:=${KUBE_ROOT}} +: ${KUBECTL:="${KUBE_VERSION_ROOT}/cluster/kubectl.sh"} +: ${KUBE_CONFIG_FILE:="config-test.sh"} + +export KUBECTL KUBE_CONFIG_FILE + source "${KUBE_ROOT}/cluster/kube-env.sh" -source "${KUBE_ROOT}/cluster/$KUBERNETES_PROVIDER/util.sh" +source "${KUBE_VERSION_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh" + +prepare-e2e if [[ "$KUBERNETES_PROVIDER" != "gce" ]] && [[ "$KUBERNETES_PROVIDER" != "gke" ]]; then echo "WARNING: Skipping pd.sh for cloud provider: ${KUBERNETES_PROVIDER}." diff --git a/hack/e2e-suite/services.sh b/hack/e2e-suite/services.sh index ed8926e51d3..a8b4ec9d031 100755 --- a/hack/e2e-suite/services.sh +++ b/hack/e2e-suite/services.sh @@ -21,8 +21,17 @@ set -o nounset set -o pipefail KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../.. + +: ${KUBE_VERSION_ROOT:=${KUBE_ROOT}} +: ${KUBECTL:="${KUBE_VERSION_ROOT}/cluster/kubectl.sh"} +: ${KUBE_CONFIG_FILE:="config-test.sh"} + +export KUBECTL KUBE_CONFIG_FILE + source "${KUBE_ROOT}/cluster/kube-env.sh" -source "${KUBE_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh" +source "${KUBE_VERSION_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh" + +prepare-e2e if [[ "$KUBERNETES_PROVIDER" == "vagrant" ]]; then echo "WARNING: Skipping services.sh for ${KUBERNETES_PROVIDER}. See https://github.com/GoogleCloudPlatform/kubernetes/issues/3655" diff --git a/hack/e2e-suite/update.sh b/hack/e2e-suite/update.sh index 6ddc1ab32e8..c147492e48c 100755 --- a/hack/e2e-suite/update.sh +++ b/hack/e2e-suite/update.sh @@ -21,9 +21,17 @@ set -o nounset set -o pipefail KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../.. -source "${KUBE_ROOT}/cluster/kube-env.sh" -source "${KUBE_ROOT}/cluster/$KUBERNETES_PROVIDER/util.sh" +: ${KUBE_VERSION_ROOT:=${KUBE_ROOT}} +: ${KUBECTL:="${KUBE_VERSION_ROOT}/cluster/kubectl.sh"} +: ${KUBE_CONFIG_FILE:="config-test.sh"} + +export KUBECTL KUBE_CONFIG_FILE + +source "${KUBE_ROOT}/cluster/kube-env.sh" +source "${KUBE_VERSION_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh" + +prepare-e2e CONTROLLER_NAME=update-demo diff --git a/hack/e2e-test.sh b/hack/e2e-test.sh index 6c8e7809ba0..284d270609b 100755 --- a/hack/e2e-test.sh +++ b/hack/e2e-test.sh @@ -15,6 +15,6 @@ # limitations under the License. # Provided for backwards compatibility -go run "$(dirname $0)/e2e.go" -v -build -up -tests="*" -down +go run "$(dirname $0)/e2e.go" -v -build -up -test -down exit $? diff --git a/hack/e2e.go b/hack/e2e.go index b5d8da8a8d3..bfdeccd526c 100644 --- a/hack/e2e.go +++ b/hack/e2e.go @@ -30,10 +30,8 @@ import ( "os/signal" "path" "path/filepath" - "sort" "strconv" "strings" - "time" ) var ( @@ -44,12 +42,8 @@ var ( push = flag.Bool("push", false, "If true, push to e2e cluster. Has no effect if -up is true.") pushup = flag.Bool("pushup", false, "If true, push to e2e cluster if it's up, otherwise start the e2e cluster.") down = flag.Bool("down", false, "If true, tear down the cluster before exiting.") - orderseed = flag.Int64("orderseed", 0, "If non-zero, seed of random test shuffle order. (Otherwise random.)") - test = flag.Bool("test", false, "Run all tests in hack/e2e-suite.") - tests = flag.String("tests", "", "Run only tests in hack/e2e-suite matching this glob. Ignored if -test is set.") - times = flag.Int("times", 1, "Number of times each test is eligible to be run. Individual order is determined by shuffling --times instances of each test using --orderseed (like a multi-deck shoe of cards).") + test = flag.Bool("test", false, "Run Ginkgo tests.") root = flag.String("root", absOrDie(filepath.Clean(filepath.Join(path.Base(os.Args[0]), ".."))), "Root directory of kubernetes repository.") - tap = flag.Bool("tap", false, "Enable Test Anything Protocol (TAP) output (disables --verbose, only failure output recorded)") verbose = flag.Bool("v", false, "If true, print all command output.") trace_bash = flag.Bool("trace-bash", false, "If true, pass -x to bash to trace all bash commands") checkVersionSkew = flag.Bool("check_version_skew", true, ""+ @@ -95,21 +89,6 @@ func main() { flag.Parse() signal.Notify(signals, os.Interrupt) - if *tap { - fmt.Printf("TAP version 13\n") - log.SetPrefix("# ") - - // TODO: this limitation is fixable by moving runBash to - // outputing to temp files, which still lets people check on - // stuck things interactively. The current stdout/stderr - // approach isn't really going to work with TAP, though. - *verbose = false - } - - if *test { - *tests = "*" - } - if *isup { status := 1 if IsUp() { @@ -137,9 +116,12 @@ func main() { log.Fatalf("Error preparing a binary of version %s: %s. Aborting.", *version, err) } else { versionRoot = newVersionRoot + os.Setenv("KUBE_VERSION_ROOT", newVersionRoot) } } + os.Setenv("KUBECTL", versionRoot+`/cluster/kubectl.sh`+kubectlArgs()) + if *pushup { if IsUp() { log.Printf("e2e cluster is up, pushing.") @@ -165,8 +147,8 @@ func main() { switch { case *ctlCmd != "": failure = !runBash("'kubectl "+*ctlCmd+"'", "$KUBECTL "+*ctlCmd) - case *tests != "": - failure = PrintResults(Test()) + case *test: + failure = Test() } if *down { @@ -275,7 +257,7 @@ func shuffleStrings(strings []string, r *rand.Rand) { } } -func Test() (results ResultsByTest) { +func Test() bool { defer runBashUntil("watchEvents", "while true; do $KUBECTL --watch-only get events; done")() if !IsUp() { @@ -284,128 +266,7 @@ func Test() (results ResultsByTest) { ValidateClusterSize() - // run tests! - dir, err := os.Open(filepath.Join(*root, "hack", "e2e-suite")) - if err != nil { - log.Fatal("Couldn't open e2e-suite dir") - } - defer dir.Close() - names, err := dir.Readdirnames(0) - if err != nil { - log.Fatal("Couldn't read names in e2e-suite dir") - } - - toRun := make([]string, 0, len(names)) - for i := range names { - name := names[i] - if name == "." || name == ".." { - continue - } - if match, err := path.Match(*tests, name); !match && err == nil { - continue - } - if err != nil { - log.Fatalf("Bad test pattern: %v", *tests) - } - toRun = append(toRun, name) - } - - if *orderseed == 0 { - // Use low order bits of NanoTime as the default seed. (Using - // all the bits makes for a long, very similar looking seed - // between runs.) - *orderseed = time.Now().UnixNano() & (1<<32 - 1) - } - sort.Strings(toRun) - if *times != 1 { - if *times <= 0 { - log.Fatal("Invalid --times (negative or no testing requested)!") - } - newToRun := make([]string, 0, *times*len(toRun)) - for i := 0; i < *times; i++ { - newToRun = append(newToRun, toRun...) - } - toRun = newToRun - } - shuffleStrings(toRun, rand.New(rand.NewSource(*orderseed))) - log.Printf("Running tests matching %v shuffled with seed %#x: %v", *tests, *orderseed, toRun) - results = ResultsByTest{} - if *tap { - fmt.Printf("1..%v\n", len(toRun)) - } - for i, name := range toRun { - absName := filepath.Join(*root, "hack", "e2e-suite", name) - log.Printf("Starting test [%v/%v]: %v", i+1, len(toRun), name) - start := time.Now() - testResult := results[name] - res, stdout, stderr := runBashWithOutputs(name, absName) - // The duration_ms output is an undocumented Jenkins TAP - // plugin feature for test duration. One might think _ms means - // milliseconds, but Jenkins interprets this field in seconds. - duration_secs := time.Now().Sub(start).Seconds() - if res { - fmt.Printf("ok %v - %v\n", i+1, name) - if *tap { - fmt.Printf(" ---\n duration_ms: %.3f\n ...\n", duration_secs) - } - testResult.Pass++ - } else { - fmt.Printf("not ok %v - %v\n", i+1, name) - if *tap { - fmt.Printf(" ---\n duration_ms: %.3f\n", duration_secs) - } - printBashOutputs(" ", " ", stdout, stderr, *tap) - if *tap { - fmt.Printf(" ...\n") - } - testResult.Fail++ - } - results[name] = testResult - } - - return -} - -func PrintResults(results ResultsByTest) bool { - failures := 0 - - passed := []string{} - flaky := []string{} - failed := []string{} - for test, result := range results { - if result.Pass > 0 && result.Fail == 0 { - passed = append(passed, test) - } else if result.Pass > 0 && result.Fail > 0 { - flaky = append(flaky, test) - failures += result.Fail - } else { - failed = append(failed, test) - failures += result.Fail - } - } - sort.Strings(passed) - sort.Strings(flaky) - sort.Strings(failed) - printSubreport("Passed", passed, results) - printSubreport("Flaky", flaky, results) - printSubreport("Failed", failed, results) - if failures > 0 { - log.Printf("%v test(s) failed.", failures) - } else { - log.Printf("Success!") - } - - return failures > 0 -} - -func printSubreport(title string, tests []string, results ResultsByTest) { - report := title + " tests:" - - for _, test := range tests { - result := results[test] - report += fmt.Sprintf(" %v[%v/%v]", test, result.Pass, result.Pass+result.Fail) - } - log.Printf(report) + return runBash("Ginkgo tests", filepath.Join(*root, "hack", "ginkgo-e2e.sh")) } // All nonsense below is temporary until we have go versions of these things. @@ -448,10 +309,6 @@ func runBashUntil(stepName, bashFragment string) func() { cmd.Process.Signal(os.Interrupt) headerprefix := stepName + " " lineprefix := " " - if *tap { - headerprefix = "# " + headerprefix - lineprefix = "# " + lineprefix - } printBashOutputs(headerprefix, lineprefix, string(stdout.Bytes()), string(stderr.Bytes()), false) } } diff --git a/hack/e2e-suite/goe2e.sh b/hack/ginkgo-e2e.sh similarity index 86% rename from hack/e2e-suite/goe2e.sh rename to hack/ginkgo-e2e.sh index b2938637aa7..c0ef4c57f82 100755 --- a/hack/e2e-suite/goe2e.sh +++ b/hack/ginkgo-e2e.sh @@ -14,11 +14,24 @@ # See the License for the specific language governing permissions and # limitations under the License. -KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../.. -source "${KUBE_ROOT}/cluster/kube-env.sh" -source "${KUBE_ROOT}/cluster/$KUBERNETES_PROVIDER/util.sh" +set -o errexit +set -o nounset +set -o pipefail -detect-master > /dev/null +KUBE_ROOT=$(dirname "${BASH_SOURCE}")/.. + +: ${KUBE_VERSION_ROOT:=${KUBE_ROOT}} +: ${KUBECTL:="${KUBE_VERSION_ROOT}/cluster/kubectl.sh"} +: ${KUBE_CONFIG_FILE:="config-test.sh"} + +export KUBECTL KUBE_CONFIG_FILE + +source "${KUBE_ROOT}/cluster/kube-env.sh" +source "${KUBE_VERSION_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh" + +prepare-e2e + +detect-master >/dev/null # Detect the OS name/arch so that we can find our binary case "$(uname -s)" in @@ -89,5 +102,6 @@ fi "${e2e}" "${auth_config[@]:+${auth_config[@]}}" \ --host="https://${KUBE_MASTER_IP-}" \ --provider="${KUBERNETES_PROVIDER}" \ + --ginkgo.v \ ${E2E_REPORT_DIR+"--report_dir=${E2E_REPORT_DIR}"} \ "${@}" diff --git a/hack/jenkins/e2e.sh b/hack/jenkins/e2e.sh index 25e8d50362e..37c2a1f1d48 100755 --- a/hack/jenkins/e2e.sh +++ b/hack/jenkins/e2e.sh @@ -83,5 +83,5 @@ export E2E_REPORT_DIR=${WORKSPACE} go run ./hack/e2e.go ${E2E_OPT} -v --down go run ./hack/e2e.go ${E2E_OPT} -v --up go run ./hack/e2e.go -v --ctl="version --match-server-version=false" -go run ./hack/e2e.go ${E2E_OPT} --test --tap | tee ../e2e.${JOB_NAME}.${BUILD_NUMBER}.${GITHASH}.tap +go run ./hack/e2e.go ${E2E_OPT} -v --test || echo "Ignored, Jenkins will pass/fail based on test failures" go run ./hack/e2e.go ${E2E_OPT} -v --down diff --git a/hack/lib/golang.sh b/hack/lib/golang.sh index 4a6598c8a6d..d81f7e6c46e 100644 --- a/hack/lib/golang.sh +++ b/hack/lib/golang.sh @@ -55,6 +55,7 @@ readonly KUBE_TEST_PORTABLE=( contrib/for-tests/network-tester/service.json hack/e2e.go hack/e2e-suite + hack/ginkgo-e2e.sh ) # If we update this we need to also update the set of golang compilers we build diff --git a/hack/test-cmd.sh b/hack/test-cmd.sh index 5d48dcaa10b..2fd73970294 100755 --- a/hack/test-cmd.sh +++ b/hack/test-cmd.sh @@ -55,6 +55,7 @@ kube::log::status "Starting kubelet in masterless mode" "${KUBE_OUTPUT_HOSTBIN}/kubelet" \ --really_crash_for_testing=true \ --root_dir=/tmp/kubelet.$$ \ + --docker_endpoint="fake://" \ --address="127.0.0.1" \ --port="$KUBELET_PORT" 1>&2 & KUBELET_PID=$! @@ -65,6 +66,7 @@ kube::log::status "Starting kubelet in masterful mode" "${KUBE_OUTPUT_HOSTBIN}/kubelet" \ --really_crash_for_testing=true \ --root_dir=/tmp/kubelet.$$ \ + --docker_endpoint="fake://" \ --etcd_servers="http://${ETCD_HOST}:${ETCD_PORT}" \ --hostname_override="127.0.0.1" \ --address="127.0.0.1" \ diff --git a/hack/update-swagger-spec.sh b/hack/update-swagger-spec.sh new file mode 100755 index 00000000000..8ff143d205a --- /dev/null +++ b/hack/update-swagger-spec.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +# Copyright 2015 Google Inc. All rights reserved. +# +# 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. + +# Script to fetch latest swagger spec. +# Puts the updated spec at swagger-spec/ + +set -o errexit +set -o nounset +set -o pipefail + +KUBE_ROOT=$(dirname "${BASH_SOURCE}")/.. +SWAGGER_ROOT_DIR="${KUBE_ROOT}/api/swagger-spec" +source "${KUBE_ROOT}/hack/lib/init.sh" + +function cleanup() +{ + [[ -n ${APISERVER_PID-} ]] && kill ${APISERVER_PID} 1>&2 2>/dev/null + + kube::etcd::cleanup + + kube::log::status "Clean up complete" +} + +trap cleanup EXIT SIGINT + +kube::etcd::start + +ETCD_HOST=${ETCD_HOST:-127.0.0.1} +ETCD_PORT=${ETCD_PORT:-4001} +API_PORT=${API_PORT:-8050} +API_HOST=${API_HOST:-127.0.0.1} +KUBELET_PORT=${KUBELET_PORT:-10250} + +# Start kube-apiserver +kube::log::status "Starting kube-apiserver" +"${KUBE_OUTPUT_HOSTBIN}/kube-apiserver" \ + --address="127.0.0.1" \ + --public_address_override="127.0.0.1" \ + --port="${API_PORT}" \ + --etcd_servers="http://${ETCD_HOST}:${ETCD_PORT}" \ + --public_address_override="127.0.0.1" \ + --kubelet_port=${KUBELET_PORT} \ + --runtime_config=api/v1beta3 \ + --portal_net="10.0.0.0/24" 1>&2 & +APISERVER_PID=$! + +kube::util::wait_for_url "http://127.0.0.1:${API_PORT}/healthz" "apiserver: " + +SWAGGER_API_PATH="http://127.0.0.1:${API_PORT}/swaggerapi/" +kube::log::status "Updating " ${SWAGGER_ROOT_DIR} +curl ${SWAGGER_API_PATH} > ${SWAGGER_ROOT_DIR}/resourceListing.json +curl ${SWAGGER_API_PATH}version > ${SWAGGER_ROOT_DIR}/version.json +curl ${SWAGGER_API_PATH}api > ${SWAGGER_ROOT_DIR}/api.json +curl ${SWAGGER_API_PATH}api/v1beta1 > ${SWAGGER_ROOT_DIR}/v1beta1.json +curl ${SWAGGER_API_PATH}api/v1beta2 > ${SWAGGER_ROOT_DIR}/v1beta2.json +curl ${SWAGGER_API_PATH}api/v1beta3 > ${SWAGGER_ROOT_DIR}/v1beta3.json + +kube::log::status "SUCCESS" diff --git a/pkg/api/errors/etcd/etcd.go b/pkg/api/errors/etcd/etcd.go index dee022828f5..379b7873afe 100644 --- a/pkg/api/errors/etcd/etcd.go +++ b/pkg/api/errors/etcd/etcd.go @@ -43,7 +43,7 @@ func InterpretCreateError(err error, kind, name string) error { } } -// InterpretUpdateError converts a generic etcd error on a create +// InterpretUpdateError converts a generic etcd error on a update // operation into the appropriate API error. func InterpretUpdateError(err error, kind, name string) error { switch { @@ -54,7 +54,7 @@ func InterpretUpdateError(err error, kind, name string) error { } } -// InterpretDeleteError converts a generic etcd error on a create +// InterpretDeleteError converts a generic etcd error on a delete // operation into the appropriate API error. func InterpretDeleteError(err error, kind, name string) error { switch { diff --git a/pkg/api/register.go b/pkg/api/register.go index b8638e442c2..8901111bb31 100644 --- a/pkg/api/register.go +++ b/pkg/api/register.go @@ -35,8 +35,6 @@ func init() { &NodeList{}, &Node{}, &Status{}, - &OperationList{}, - &Operation{}, &Endpoints{}, &EndpointsList{}, &Binding{}, @@ -56,8 +54,6 @@ func init() { // Legacy names are supported Scheme.AddKnownTypeWithName("", "Minion", &Node{}) Scheme.AddKnownTypeWithName("", "MinionList", &NodeList{}) - Scheme.AddKnownTypeWithName("", "ServerOp", &Operation{}) - Scheme.AddKnownTypeWithName("", "ServerOpList", &OperationList{}) } func (*Pod) IsAnAPIObject() {} @@ -73,8 +69,6 @@ func (*Node) IsAnAPIObject() {} func (*NodeList) IsAnAPIObject() {} func (*Binding) IsAnAPIObject() {} func (*Status) IsAnAPIObject() {} -func (*Operation) IsAnAPIObject() {} -func (*OperationList) IsAnAPIObject() {} func (*Event) IsAnAPIObject() {} func (*EventList) IsAnAPIObject() {} func (*ContainerManifest) IsAnAPIObject() {} diff --git a/pkg/api/types.go b/pkg/api/types.go index f78b1d7d460..eda37ecb074 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -292,6 +292,8 @@ type Probe struct { Handler `json:",inline"` // Length of time before health checking is activated. In seconds. InitialDelaySeconds int64 `json:"initialDelaySeconds,omitempty"` + // Length of time before health checking times out. In seconds. + TimeoutSeconds int64 `json:"timeoutSeconds,omitempty"` } // PullPolicy describes a policy for if/when to pull a container image @@ -1028,20 +1030,6 @@ const ( CauseTypeFieldValueNotSupported CauseType = "FieldValueNotSupported" ) -// Operation is an operation delivered to API clients. -type Operation struct { - TypeMeta `json:",inline"` - ObjectMeta `json:"metadata,omitempty"` -} - -// OperationList is a list of operations, as delivered to API clients. -type OperationList struct { - TypeMeta `json:",inline"` - ListMeta `json:"metadata,omitempty"` - - Items []Operation `json:"items"` -} - // ObjectReference contains enough information to let you inspect or modify the referred object. type ObjectReference struct { Kind string `json:"kind,omitempty"` diff --git a/pkg/api/v1beta1/conversion.go b/pkg/api/v1beta1/conversion.go index 5d7d02bb796..40cefb37056 100644 --- a/pkg/api/v1beta1/conversion.go +++ b/pkg/api/v1beta1/conversion.go @@ -1050,6 +1050,7 @@ func init() { return err } out.InitialDelaySeconds = in.InitialDelaySeconds + out.TimeoutSeconds = in.TimeoutSeconds return nil }, func(in *LivenessProbe, out *newer.Probe, s conversion.Scope) error { @@ -1063,6 +1064,7 @@ func init() { return err } out.InitialDelaySeconds = in.InitialDelaySeconds + out.TimeoutSeconds = in.TimeoutSeconds return nil }, ) diff --git a/pkg/api/v1beta1/register.go b/pkg/api/v1beta1/register.go index 17c917a4860..d3f8a91a651 100644 --- a/pkg/api/v1beta1/register.go +++ b/pkg/api/v1beta1/register.go @@ -39,8 +39,6 @@ func init() { &MinionList{}, &Binding{}, &Status{}, - &ServerOp{}, - &ServerOpList{}, &Event{}, &EventList{}, &ContainerManifest{}, @@ -57,8 +55,6 @@ func init() { // Future names are supported api.Scheme.AddKnownTypeWithName("v1beta1", "Node", &Minion{}) api.Scheme.AddKnownTypeWithName("v1beta1", "NodeList", &MinionList{}) - api.Scheme.AddKnownTypeWithName("v1beta1", "Operation", &ServerOp{}) - api.Scheme.AddKnownTypeWithName("v1beta1", "OperationList", &ServerOpList{}) } func (*Pod) IsAnAPIObject() {} @@ -74,8 +70,6 @@ func (*Minion) IsAnAPIObject() {} func (*MinionList) IsAnAPIObject() {} func (*Binding) IsAnAPIObject() {} func (*Status) IsAnAPIObject() {} -func (*ServerOp) IsAnAPIObject() {} -func (*ServerOpList) IsAnAPIObject() {} func (*Event) IsAnAPIObject() {} func (*EventList) IsAnAPIObject() {} func (*ContainerManifest) IsAnAPIObject() {} diff --git a/pkg/api/v1beta1/types.go b/pkg/api/v1beta1/types.go index 6efaea08f14..0586ae2f3b7 100644 --- a/pkg/api/v1beta1/types.go +++ b/pkg/api/v1beta1/types.go @@ -232,6 +232,8 @@ type LivenessProbe struct { Exec *ExecAction `json:"exec,omitempty" description:"parameters for exec-based liveness probe"` // Length of time before health checking is activated. In seconds. InitialDelaySeconds int64 `json:"initialDelaySeconds,omitempty" description:"number of seconds after the container has started before liveness probes are initiated"` + // Length of time before health checking times out. In seconds. + TimeoutSeconds int64 `json:"timeoutSeconds,omitempty" description:"number of seconds after which liveness probes timeout; defaults to 1 second"` } // PullPolicy describes a policy for if/when to pull a container image @@ -808,17 +810,6 @@ const ( CauseTypeFieldValueNotSupported CauseType = "FieldValueNotSupported" ) -// ServerOp is an operation delivered to API clients. -type ServerOp struct { - TypeMeta `json:",inline"` -} - -// ServerOpList is a list of operations, as delivered to API clients. -type ServerOpList struct { - TypeMeta `json:",inline"` - Items []ServerOp `json:"items" description:"list of operations"` -} - // ObjectReference contains enough information to let you inspect or modify the referred object. type ObjectReference struct { Kind string `json:"kind,omitempty" description:"kind of the referent"` diff --git a/pkg/api/v1beta2/conversion.go b/pkg/api/v1beta2/conversion.go index 74c383139fc..095c91037f8 100644 --- a/pkg/api/v1beta2/conversion.go +++ b/pkg/api/v1beta2/conversion.go @@ -966,6 +966,7 @@ func init() { return err } out.InitialDelaySeconds = in.InitialDelaySeconds + out.TimeoutSeconds = in.TimeoutSeconds return nil }, func(in *LivenessProbe, out *newer.Probe, s conversion.Scope) error { @@ -979,6 +980,7 @@ func init() { return err } out.InitialDelaySeconds = in.InitialDelaySeconds + out.TimeoutSeconds = in.TimeoutSeconds return nil }, ) diff --git a/pkg/api/v1beta2/register.go b/pkg/api/v1beta2/register.go index ad447476c23..88fe96e700d 100644 --- a/pkg/api/v1beta2/register.go +++ b/pkg/api/v1beta2/register.go @@ -39,8 +39,6 @@ func init() { &MinionList{}, &Binding{}, &Status{}, - &ServerOp{}, - &ServerOpList{}, &Event{}, &EventList{}, &ContainerManifest{}, @@ -57,8 +55,6 @@ func init() { // Future names are supported api.Scheme.AddKnownTypeWithName("v1beta2", "Node", &Minion{}) api.Scheme.AddKnownTypeWithName("v1beta2", "NodeList", &MinionList{}) - api.Scheme.AddKnownTypeWithName("v1beta2", "Operation", &ServerOp{}) - api.Scheme.AddKnownTypeWithName("v1beta2", "OperationList", &ServerOpList{}) } func (*Pod) IsAnAPIObject() {} @@ -74,8 +70,6 @@ func (*Minion) IsAnAPIObject() {} func (*MinionList) IsAnAPIObject() {} func (*Binding) IsAnAPIObject() {} func (*Status) IsAnAPIObject() {} -func (*ServerOp) IsAnAPIObject() {} -func (*ServerOpList) IsAnAPIObject() {} func (*Event) IsAnAPIObject() {} func (*EventList) IsAnAPIObject() {} func (*ContainerManifest) IsAnAPIObject() {} diff --git a/pkg/api/v1beta2/types.go b/pkg/api/v1beta2/types.go index fe52e819285..47d83b9d00f 100644 --- a/pkg/api/v1beta2/types.go +++ b/pkg/api/v1beta2/types.go @@ -191,6 +191,8 @@ type LivenessProbe struct { Exec *ExecAction `json:"exec,omitempty" description:"parameters for exec-based liveness probe"` // Length of time before health checking is activated. In seconds. InitialDelaySeconds int64 `json:"initialDelaySeconds,omitempty" description:"number of seconds after the container has started before liveness probes are initiated"` + // Length of time before health checking times out. In seconds. + TimeoutSeconds int64 `json:"timeoutSeconds,omitempty" description:"number of seconds after which liveness probes timeout; defaults to 1 second"` } // PullPolicy describes a policy for if/when to pull a container image @@ -782,17 +784,6 @@ const ( CauseTypeFieldValueNotSupported CauseType = "FieldValueNotSupported" ) -// ServerOp is an operation delivered to API clients. -type ServerOp struct { - TypeMeta `json:",inline"` -} - -// ServerOpList is a list of operations, as delivered to API clients. -type ServerOpList struct { - TypeMeta `json:",inline"` - Items []ServerOp `json:"items" description:"list of operations"` -} - // ObjectReference contains enough information to let you inspect or modify the referred object. type ObjectReference struct { Kind string `json:"kind,omitempty" description:"kind of the referent"` diff --git a/pkg/api/v1beta3/register.go b/pkg/api/v1beta3/register.go index a1956cdc67b..da801ab73b0 100644 --- a/pkg/api/v1beta3/register.go +++ b/pkg/api/v1beta3/register.go @@ -43,8 +43,6 @@ func init() { &NodeList{}, &Binding{}, &Status{}, - &Operation{}, - &OperationList{}, &Event{}, &EventList{}, &List{}, @@ -57,8 +55,6 @@ func init() { // Legacy names are supported api.Scheme.AddKnownTypeWithName("v1beta3", "Minion", &Node{}) api.Scheme.AddKnownTypeWithName("v1beta3", "MinionList", &NodeList{}) - api.Scheme.AddKnownTypeWithName("v1beta3", "ServerOp", &Operation{}) - api.Scheme.AddKnownTypeWithName("v1beta3", "ServerOpList", &OperationList{}) } func (*Pod) IsAnAPIObject() {} @@ -78,8 +74,6 @@ func (*Node) IsAnAPIObject() {} func (*NodeList) IsAnAPIObject() {} func (*Binding) IsAnAPIObject() {} func (*Status) IsAnAPIObject() {} -func (*Operation) IsAnAPIObject() {} -func (*OperationList) IsAnAPIObject() {} func (*Event) IsAnAPIObject() {} func (*EventList) IsAnAPIObject() {} func (*List) IsAnAPIObject() {} diff --git a/pkg/api/v1beta3/types.go b/pkg/api/v1beta3/types.go index 5b24abc1a88..94aa6326e0f 100644 --- a/pkg/api/v1beta3/types.go +++ b/pkg/api/v1beta3/types.go @@ -310,6 +310,8 @@ type Probe struct { Handler `json:",inline"` // Length of time before health checking is activated. In seconds. InitialDelaySeconds int64 `json:"initialDelaySeconds,omitempty"` + // Length of time before health checking times out. In seconds. + TimeoutSeconds int64 `json:"timeoutSeconds,omitempty"` } // PullPolicy describes a policy for if/when to pull a container image @@ -1008,22 +1010,6 @@ const ( CauseTypeFieldValueNotSupported CauseType = "FieldValueNotSupported" ) -// Operation is a request from a client that has not yet been satisfied. The name of an -// Operation is assigned by the server when an operation is started, and can be used by -// clients to retrieve the final result of the operation at a later time. -type Operation struct { - TypeMeta `json:",inline"` - ObjectMeta `json:"metadata"` -} - -// OperationList is a list of operations, as delivered to API clients. -type OperationList struct { - TypeMeta `json:",inline"` - ListMeta `json:"metadata,omitempty"` - - Items []Operation `json:"items"` -} - // ObjectReference contains enough information to let you inspect or modify the referred object. type ObjectReference struct { Kind string `json:"kind,omitempty"` diff --git a/pkg/api/validation/validation_test.go b/pkg/api/validation/validation_test.go index 92ded41f7ad..df0ab23adf2 100644 --- a/pkg/api/validation/validation_test.go +++ b/pkg/api/validation/validation_test.go @@ -214,7 +214,7 @@ func TestValidatePorts(t *testing.T) { "invalid container port": {[]api.Port{{ContainerPort: 65536, Protocol: "TCP"}}, errors.ValidationErrorTypeInvalid, "[0].containerPort"}, "invalid host port": {[]api.Port{{ContainerPort: 80, HostPort: 65536, Protocol: "TCP"}}, errors.ValidationErrorTypeInvalid, "[0].hostPort"}, "invalid protocol": {[]api.Port{{ContainerPort: 80, Protocol: "ICMP"}}, errors.ValidationErrorTypeNotSupported, "[0].protocol"}, - "protocol required": {[]api.Port{{Name: "abc", ContainerPort: 80}}, errors.ValidationErrorTypeRequired, "[0].protocol"}, //yjhong + "protocol required": {[]api.Port{{Name: "abc", ContainerPort: 80}}, errors.ValidationErrorTypeRequired, "[0].protocol"}, } for k, v := range errorCases { errs := validatePorts(v.P) @@ -371,23 +371,26 @@ func TestValidateContainers(t *testing.T) { AllowPrivileged: false, }) errorCases := map[string][]api.Container{ - "zero-length name": {{Name: "", Image: "image"}}, - "name > 63 characters": {{Name: strings.Repeat("a", 64), Image: "image"}}, - "name not a DNS label": {{Name: "a.b.c", Image: "image"}}, + "zero-length name": {{Name: "", Image: "image", ImagePullPolicy: "IfNotPresent"}}, + "name > 63 characters": {{Name: strings.Repeat("a", 64), Image: "image", ImagePullPolicy: "IfNotPresent"}}, + "name not a DNS label": {{Name: "a.b.c", Image: "image", ImagePullPolicy: "IfNotPresent"}}, "name not unique": { - {Name: "abc", Image: "image"}, - {Name: "abc", Image: "image"}, + {Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}, + {Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}, }, - "zero-length image": {{Name: "abc", Image: ""}}, + "zero-length image": {{Name: "abc", Image: "", ImagePullPolicy: "IfNotPresent"}}, "host port not unique": { - {Name: "abc", Image: "image", Ports: []api.Port{{ContainerPort: 80, HostPort: 80}}}, - {Name: "def", Image: "image", Ports: []api.Port{{ContainerPort: 81, HostPort: 80}}}, + {Name: "abc", Image: "image", Ports: []api.Port{{ContainerPort: 80, HostPort: 80, Protocol: "TCP"}}, + ImagePullPolicy: "IfNotPresent"}, + {Name: "def", Image: "image", Ports: []api.Port{{ContainerPort: 81, HostPort: 80, Protocol: "TCP"}}, + ImagePullPolicy: "IfNotPresent"}, }, "invalid env var name": { - {Name: "abc", Image: "image", Env: []api.EnvVar{{Name: "ev.1"}}}, + {Name: "abc", Image: "image", Env: []api.EnvVar{{Name: "ev.1"}}, ImagePullPolicy: "IfNotPresent"}, }, "unknown volume name": { - {Name: "abc", Image: "image", VolumeMounts: []api.VolumeMount{{Name: "anything", MountPath: "/foo"}}}, + {Name: "abc", Image: "image", VolumeMounts: []api.VolumeMount{{Name: "anything", MountPath: "/foo"}}, + ImagePullPolicy: "IfNotPresent"}, }, "invalid lifecycle, no exec command.": { { @@ -398,6 +401,7 @@ func TestValidateContainers(t *testing.T) { Exec: &api.ExecAction{}, }, }, + ImagePullPolicy: "IfNotPresent", }, }, "invalid lifecycle, no http path.": { @@ -409,6 +413,7 @@ func TestValidateContainers(t *testing.T) { HTTPGet: &api.HTTPGetAction{}, }, }, + ImagePullPolicy: "IfNotPresent", }, }, "invalid lifecycle, no action.": { @@ -418,6 +423,7 @@ func TestValidateContainers(t *testing.T) { Lifecycle: &api.Lifecycle{ PreStop: &api.Handler{}, }, + ImagePullPolicy: "IfNotPresent", }, }, "privilege disabled": { @@ -432,6 +438,7 @@ func TestValidateContainers(t *testing.T) { "disk": resource.MustParse("10G"), }, }, + ImagePullPolicy: "IfNotPresent", }, }, "Resource CPU invalid": { @@ -441,6 +448,7 @@ func TestValidateContainers(t *testing.T) { Resources: api.ResourceRequirementSpec{ Limits: getResourceLimits("-10", "0"), }, + ImagePullPolicy: "IfNotPresent", }, }, "Resource Memory invalid": { @@ -450,6 +458,7 @@ func TestValidateContainers(t *testing.T) { Resources: api.ResourceRequirementSpec{ Limits: getResourceLimits("0", "-10"), }, + ImagePullPolicy: "IfNotPresent", }, }, } @@ -553,17 +562,26 @@ func TestValidateManifest(t *testing.T) { } errorCases := map[string]api.ContainerManifest{ - "empty version": {Version: "", ID: "abc"}, - "invalid version": {Version: "bogus", ID: "abc"}, + "empty version": {Version: "", ID: "abc", + RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, + DNSPolicy: api.DNSClusterFirst}, + "invalid version": {Version: "bogus", ID: "abc", + RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, + DNSPolicy: api.DNSClusterFirst}, "invalid volume name": { - Version: "v1beta1", - ID: "abc", - Volumes: []api.Volume{{Name: "vol.1"}}, + Version: "v1beta1", + ID: "abc", + Volumes: []api.Volume{{Name: "vol.1", Source: api.VolumeSource{EmptyDir: &api.EmptyDir{}}}}, + RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, + DNSPolicy: api.DNSClusterFirst, }, "invalid container name": { - Version: "v1beta1", - ID: "abc", - Containers: []api.Container{{Name: "ctr.1", Image: "image"}}, + Version: "v1beta1", + ID: "abc", + Containers: []api.Container{{Name: "ctr.1", Image: "image", ImagePullPolicy: "IfNotPresent", + TerminationMessagePath: "/foo/bar"}}, + RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, + DNSPolicy: api.DNSClusterFirst, }, } for k, v := range errorCases { @@ -602,13 +620,22 @@ func TestValidatePodSpec(t *testing.T) { failureCases := map[string]api.PodSpec{ "bad volume": { - Volumes: []api.Volume{{}}, + Volumes: []api.Volume{{}}, + RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, + DNSPolicy: api.DNSClusterFirst, }, "bad container": { - Containers: []api.Container{{}}, + Containers: []api.Container{{}}, + RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, + DNSPolicy: api.DNSClusterFirst, }, "bad DNS policy": { - DNSPolicy: api.DNSPolicy("invalid"), + DNSPolicy: api.DNSPolicy("invalid"), + RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, + }, + "bad restart policy": { + RestartPolicy: api.RestartPolicy{}, + DNSPolicy: api.DNSClusterFirst, }, } for k, v := range failureCases { @@ -652,8 +679,20 @@ func TestValidatePod(t *testing.T) { } errorCases := map[string]api.Pod{ - "bad name": {ObjectMeta: api.ObjectMeta{Name: "", Namespace: "ns"}}, - "bad namespace": {ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: ""}}, + "bad name": { + ObjectMeta: api.ObjectMeta{Name: "", Namespace: "ns"}, + Spec: api.PodSpec{ + RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, + DNSPolicy: api.DNSClusterFirst, + }, + }, + "bad namespace": { + ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: ""}, + Spec: api.PodSpec{ + RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, + DNSPolicy: api.DNSClusterFirst, + }, + }, "bad spec": { ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "ns"}, Spec: api.PodSpec{ @@ -668,6 +707,10 @@ func TestValidatePod(t *testing.T) { "NoUppercaseOrSpecialCharsLike=Equals": "bar", }, }, + Spec: api.PodSpec{ + RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, + DNSPolicy: api.DNSClusterFirst, + }, }, "bad annotation": { ObjectMeta: api.ObjectMeta{ @@ -677,6 +720,10 @@ func TestValidatePod(t *testing.T) { "NoUppercaseOrSpecialCharsLike=Equals": "bar", }, }, + Spec: api.PodSpec{ + RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, + DNSPolicy: api.DNSClusterFirst, + }, }, } for k, v := range errorCases { @@ -857,6 +904,26 @@ func TestValidatePodUpdate(t *testing.T) { false, "port change", }, + { + api.Pod{ + ObjectMeta: api.ObjectMeta{ + Name: "foo", + Labels: map[string]string{ + "foo": "bar", + }, + }, + }, + api.Pod{ + ObjectMeta: api.ObjectMeta{ + Name: "foo", + Labels: map[string]string{ + "Bar": "foo", + }, + }, + }, + true, + "bad label change", + }, } for _, test := range tests { @@ -914,18 +981,53 @@ func TestValidateBoundPods(t *testing.T) { } errorCases := map[string]api.Pod{ - "bad name": {ObjectMeta: api.ObjectMeta{Name: "", Namespace: "ns"}}, - "bad namespace": {ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: ""}}, + "zero-length name": { + ObjectMeta: api.ObjectMeta{Name: "", Namespace: "ns"}, + Spec: api.PodSpec{ + RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, + DNSPolicy: api.DNSClusterFirst, + }, + }, + "bad namespace": { + ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: ""}, + Spec: api.PodSpec{ + RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, + DNSPolicy: api.DNSClusterFirst, + }, + }, "bad spec": { ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "ns"}, Spec: api.PodSpec{ - Containers: []api.Container{{}}, + Containers: []api.Container{{Name: "name", ImagePullPolicy: "IfNotPresent"}}, + RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, + DNSPolicy: api.DNSClusterFirst, + }, + }, + "name > 253 characters": { + ObjectMeta: api.ObjectMeta{Name: strings.Repeat("a", 254), Namespace: "ns"}, + Spec: api.PodSpec{ + RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, + DNSPolicy: api.DNSClusterFirst, + }, + }, + "name not a DNS subdomain": { + ObjectMeta: api.ObjectMeta{Name: "a..b.c", Namespace: "ns"}, + Spec: api.PodSpec{ + RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, + DNSPolicy: api.DNSClusterFirst, + }, + }, + "name with underscore": { + ObjectMeta: api.ObjectMeta{Name: "a_b_c", Namespace: "ns"}, + Spec: api.PodSpec{ + RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, + DNSPolicy: api.DNSClusterFirst, }, }, } for k, v := range errorCases { - if errs := ValidatePod(&v); len(errs) == 0 { - t.Errorf("expected failure for %s", k) + if errs := ValidatePod(&v); len(errs) != 1 { + t.Errorf("expected one failure for %s; got %d: %s", k, len(errs), errs) } } } @@ -1314,7 +1416,9 @@ func TestValidateReplicationController(t *testing.T) { invalidVolumePodTemplate := api.PodTemplate{ Spec: api.PodTemplateSpec{ Spec: api.PodSpec{ - Volumes: []api.Volume{{Name: "gcepd", Source: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDisk{"my-PD", "ext4", 1, false}}}}, + Volumes: []api.Volume{{Name: "gcepd", Source: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDisk{"my-PD", "ext4", 1, false}}}}, + RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, + DNSPolicy: api.DNSClusterFirst, }, }, } @@ -1502,24 +1606,6 @@ func TestValidateReplicationController(t *testing.T) { } } -func TestValidateBoundPodNoName(t *testing.T) { - errorCases := map[string]api.BoundPod{ - // manifest is tested in api/validation_test.go, ensure it is invoked - "empty version": {ObjectMeta: api.ObjectMeta{Name: "test"}, Spec: api.PodSpec{Containers: []api.Container{{Name: ""}}}}, - - // Name - "zero-length name": {ObjectMeta: api.ObjectMeta{Name: ""}}, - "name > 255 characters": {ObjectMeta: api.ObjectMeta{Name: strings.Repeat("a", 256)}}, - "name not a DNS subdomain": {ObjectMeta: api.ObjectMeta{Name: "a.b.c."}}, - "name with underscore": {ObjectMeta: api.ObjectMeta{Name: "a_b_c"}}, - } - for k, v := range errorCases { - if errs := ValidateBoundPod(&v); len(errs) == 0 { - t.Errorf("expected failure for %s", k) - } - } -} - func TestValidateMinion(t *testing.T) { validSelector := map[string]string{"a": "b"} invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"} @@ -1692,6 +1778,17 @@ func TestValidateMinionUpdate(t *testing.T) { Labels: map[string]string{"bar": "fooobaz"}, }, }, true}, + {api.Node{ + ObjectMeta: api.ObjectMeta{ + Name: "foo", + Labels: map[string]string{"foo": "baz"}, + }, + }, api.Node{ + ObjectMeta: api.ObjectMeta{ + Name: "foo", + Labels: map[string]string{"Foo": "baz"}, + }, + }, false}, } for i, test := range tests { errs := ValidateMinionUpdate(&test.oldMinion, &test.minion) @@ -1848,6 +1945,19 @@ func TestValidateServiceUpdate(t *testing.T) { PortalIP: "127.0.0.2", }, }, false}, + { // 10 + api.Service{ + ObjectMeta: api.ObjectMeta{ + Name: "foo", + Labels: map[string]string{"foo": "baz"}, + }, + }, + api.Service{ + ObjectMeta: api.ObjectMeta{ + Name: "foo", + Labels: map[string]string{"Foo": "baz"}, + }, + }, false}, } for i, test := range tests { errs := ValidateServiceUpdate(&test.oldService, &test.service) diff --git a/pkg/apiserver/operation.go b/pkg/apiserver/operation.go index 8d073499472..f0c88de6cfb 100644 --- a/pkg/apiserver/operation.go +++ b/pkg/apiserver/operation.go @@ -17,7 +17,6 @@ limitations under the License. package apiserver import ( - "sort" "strconv" "sync" "sync/atomic" @@ -79,23 +78,6 @@ func (ops *Operations) insert(op *Operation) { ops.ops[op.ID] = op } -// List lists operations for an API client. -func (ops *Operations) List() *api.OperationList { - ops.lock.Lock() - defer ops.lock.Unlock() - - ids := []string{} - for id := range ops.ops { - ids = append(ids, id) - } - sort.StringSlice(ids).Sort() - ol := &api.OperationList{} - for _, id := range ids { - ol.Items = append(ol.Items, api.Operation{ObjectMeta: api.ObjectMeta{Name: id}}) - } - return ol -} - // Get returns the operation with the given ID, or nil. func (ops *Operations) Get(id string) *Operation { ops.lock.Lock() diff --git a/pkg/apiserver/validator.go b/pkg/apiserver/validator.go index e1c47803cb9..d73a418c530 100644 --- a/pkg/apiserver/validator.go +++ b/pkg/apiserver/validator.go @@ -46,7 +46,7 @@ type validator struct { } // TODO: can this use pkg/probe/http -func (s *Server) check(client httpGet) (probe.Status, string, error) { +func (s *Server) check(client httpGet) (probe.Result, string, error) { resp, err := client.Get("http://" + net.JoinHostPort(s.Addr, strconv.Itoa(s.Port)) + s.Path) if err != nil { return probe.Unknown, "", err @@ -66,7 +66,7 @@ func (s *Server) check(client httpGet) (probe.Status, string, error) { type ServerStatus struct { Component string `json:"component,omitempty"` Health string `json:"health,omitempty"` - HealthCode probe.Status `json:"healthCode,omitempty"` + HealthCode probe.Result `json:"healthCode,omitempty"` Msg string `json:"msg,omitempty"` Err string `json:"err,omitempty"` } diff --git a/pkg/apiserver/validator_test.go b/pkg/apiserver/validator_test.go index 0a9477135a2..35b991aee0e 100644 --- a/pkg/apiserver/validator_test.go +++ b/pkg/apiserver/validator_test.go @@ -54,7 +54,7 @@ func TestValidate(t *testing.T) { tests := []struct { err error data string - expectedStatus probe.Status + expectedStatus probe.Result code int expectErr bool }{ diff --git a/pkg/client/kubelet.go b/pkg/client/kubelet.go index f5754bb91b9..72882b5af7a 100644 --- a/pkg/client/kubelet.go +++ b/pkg/client/kubelet.go @@ -41,7 +41,7 @@ type KubeletClient interface { // KubeletHealthchecker is an interface for healthchecking kubelets type KubeletHealthChecker interface { - HealthCheck(host string) (probe.Status, error) + HealthCheck(host string) (probe.Result, error) } // PodInfoGetter is an interface for things that can get information about a pod's containers. @@ -134,7 +134,7 @@ func (c *HTTPKubeletClient) GetPodStatus(host, podNamespace, podID string) (api. return status, nil } -func (c *HTTPKubeletClient) HealthCheck(host string) (probe.Status, error) { +func (c *HTTPKubeletClient) HealthCheck(host string) (probe.Result, error) { return httprobe.DoHTTPProbe(fmt.Sprintf("%s/healthz", c.url(host)), c.Client) } @@ -148,6 +148,6 @@ func (c FakeKubeletClient) GetPodStatus(host, podNamespace string, podID string) return api.PodStatusResult{}, errors.New("Not Implemented") } -func (c FakeKubeletClient) HealthCheck(host string) (probe.Status, error) { +func (c FakeKubeletClient) HealthCheck(host string) (probe.Result, error) { return probe.Unknown, errors.New("Not Implemented") } diff --git a/pkg/cloudprovider/controller/nodecontroller_test.go b/pkg/cloudprovider/controller/nodecontroller_test.go index 4462a74fbcc..69f53cc0832 100644 --- a/pkg/cloudprovider/controller/nodecontroller_test.go +++ b/pkg/cloudprovider/controller/nodecontroller_test.go @@ -102,7 +102,7 @@ func (m *FakeNodeHandler) Update(node *api.Node) (*api.Node, error) { // FakeKubeletClient is a fake implementation of KubeletClient. type FakeKubeletClient struct { - Status probe.Status + Status probe.Result Err error } @@ -110,7 +110,7 @@ func (c *FakeKubeletClient) GetPodStatus(host, podNamespace, podID string) (api. return api.PodStatusResult{}, errors.New("Not Implemented") } -func (c *FakeKubeletClient) HealthCheck(host string) (probe.Status, error) { +func (c *FakeKubeletClient) HealthCheck(host string) (probe.Result, error) { return c.Status, c.Err } diff --git a/pkg/constraint/constraint.go b/pkg/constraint/constraint.go index 8acc8c073d8..430c1a85cb2 100644 --- a/pkg/constraint/constraint.go +++ b/pkg/constraint/constraint.go @@ -17,11 +17,17 @@ limitations under the License. package constraint import ( + "fmt" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api" ) // Allowed returns true if pods is a collection of bound pods // which can run without conflict on a single minion. -func Allowed(pods []api.BoundPod) bool { - return !PortsConflict(pods) +func Allowed(pods []api.BoundPod) []error { + errors := []error{} + for _, port := range hostPortsConflict(pods) { + errors = append(errors, fmt.Errorf("host port %v is already in use", port)) + } + return errors } diff --git a/pkg/constraint/constraint_test.go b/pkg/constraint/constraint_test.go index 1677d935df5..eae45221270 100644 --- a/pkg/constraint/constraint_test.go +++ b/pkg/constraint/constraint_test.go @@ -17,6 +17,7 @@ limitations under the License. package constraint import ( + "fmt" "testing" "github.com/GoogleCloudPlatform/kubernetes/pkg/api" @@ -40,11 +41,11 @@ func podWithContainers(containers ...api.Container) api.BoundPod { func TestAllowed(t *testing.T) { table := []struct { - allowed bool - pods []api.BoundPod + err string + pods []api.BoundPod }{ { - allowed: true, + err: "[]", pods: []api.BoundPod{ podWithContainers( containerWithHostPorts(1, 2, 3), @@ -57,7 +58,7 @@ func TestAllowed(t *testing.T) { }, }, { - allowed: true, + err: "[]", pods: []api.BoundPod{ podWithContainers( containerWithHostPorts(0, 0), @@ -70,7 +71,7 @@ func TestAllowed(t *testing.T) { }, }, { - allowed: false, + err: "[host port 3 is already in use]", pods: []api.BoundPod{ podWithContainers( containerWithHostPorts(3, 3), @@ -78,7 +79,7 @@ func TestAllowed(t *testing.T) { }, }, { - allowed: false, + err: "[host port 6 is already in use]", pods: []api.BoundPod{ podWithContainers( containerWithHostPorts(6), @@ -91,7 +92,7 @@ func TestAllowed(t *testing.T) { } for _, item := range table { - if e, a := item.allowed, Allowed(item.pods); e != a { + if e, a := item.err, Allowed(item.pods); e != fmt.Sprintf("%v", a) { t.Errorf("Expected %v, got %v: \n%v\v", e, a, item.pods) } } diff --git a/pkg/constraint/ports.go b/pkg/constraint/ports.go index f5c95f5fb2d..b7398a6ea78 100644 --- a/pkg/constraint/ports.go +++ b/pkg/constraint/ports.go @@ -20,10 +20,12 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" ) -// PortsConflict returns true iff two containers attempt to expose -// the same host port. -func PortsConflict(pods []api.BoundPod) bool { +// hostPortsConflict returns an array of host ports that at least two +// containers attempt to expose. The array is empty if no such port +// exists. +func hostPortsConflict(pods []api.BoundPod) []int { hostPorts := map[int]struct{}{} + conflictingPorts := []int{} for _, pod := range pods { for _, container := range pod.Spec.Containers { for _, port := range container.Ports { @@ -31,11 +33,11 @@ func PortsConflict(pods []api.BoundPod) bool { continue } if _, exists := hostPorts[port.HostPort]; exists { - return true + conflictingPorts = append(conflictingPorts, port.HostPort) } hostPorts[port.HostPort] = struct{}{} } } } - return false + return conflictingPorts } diff --git a/pkg/controller/replication_controller.go b/pkg/controller/replication_controller.go index 2f9c03221b5..df9cbec5c86 100644 --- a/pkg/controller/replication_controller.go +++ b/pkg/controller/replication_controller.go @@ -141,11 +141,24 @@ func (rm *ReplicationManager) watchControllers(resourceVersion *string) { } if event.Type == watch.Error { util.HandleError(fmt.Errorf("error from watch during sync: %v", errors.FromObject(event.Object))) + // Clear the resource version, this may cause us to skip some elements on the watch, + // but we'll catch them on the synchronize() call, so it works out. + *resourceVersion = "" continue } glog.V(4).Infof("Got watch: %#v", event) rc, ok := event.Object.(*api.ReplicationController) if !ok { + if status, ok := event.Object.(*api.Status); ok { + if status.Status == api.StatusFailure { + glog.Errorf("failed to watch: %v", status) + // Clear resource version here, as above, this won't hurt consistency, but we + // should consider introspecting more carefully here. (or make the apiserver smarter) + // "why not both?" + *resourceVersion = "" + continue + } + } util.HandleError(fmt.Errorf("unexpected object: %#v", event.Object)) continue } @@ -166,7 +179,8 @@ func FilterActivePods(pods []api.Pod) []api.Pod { var result []api.Pod for _, value := range pods { if api.PodSucceeded != value.Status.Phase && - api.PodFailed != value.Status.Phase { + api.PodFailed != value.Status.Phase && + api.PodUnknown != value.Status.Phase { result = append(result, value) } } diff --git a/pkg/kubectl/cmd/cmd.go b/pkg/kubectl/cmd/cmd.go index 53468cb0faf..2c186684a75 100644 --- a/pkg/kubectl/cmd/cmd.go +++ b/pkg/kubectl/cmd/cmd.go @@ -29,6 +29,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" cmdconfig "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/config" + cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" @@ -143,7 +144,7 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory { return kubectl.ReaperFor(mapping.Kind, client) }, Validator: func(cmd *cobra.Command) (validation.Schema, error) { - if GetFlagBool(cmd, "validate") { + if cmdutil.GetFlagBool(cmd, "validate") { client, err := clients.ClientForVersion("") if err != nil { return nil, err @@ -217,6 +218,62 @@ Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`, return cmds } +// PrintObject prints an api object given command line flags to modify the output format +func (f *Factory) PrintObject(cmd *cobra.Command, obj runtime.Object, out io.Writer) error { + mapper, _ := f.Object(cmd) + _, kind, err := api.Scheme.ObjectVersionAndKind(obj) + if err != nil { + return err + } + + mapping, err := mapper.RESTMapping(kind) + if err != nil { + return err + } + + printer, err := f.PrinterForMapping(cmd, mapping) + if err != nil { + return err + } + return printer.PrintObj(obj, out) +} + +// PrinterForMapping returns a printer suitable for displaying the provided resource type. +// Requires that printer flags have been added to cmd (see AddPrinterFlags). +func (f *Factory) PrinterForMapping(cmd *cobra.Command, mapping *meta.RESTMapping) (kubectl.ResourcePrinter, error) { + printer, ok, err := cmdutil.PrinterForCommand(cmd) + if err != nil { + return nil, err + } + if ok { + clientConfig, err := f.ClientConfig(cmd) + checkErr(err) + defaultVersion := clientConfig.Version + + version := cmdutil.OutputVersion(cmd, defaultVersion) + if len(version) == 0 { + version = mapping.APIVersion + } + if len(version) == 0 { + return nil, fmt.Errorf("you must specify an output-version when using this output format") + } + printer = kubectl.NewVersionedPrinter(printer, mapping.ObjectConvertor, version) + } else { + printer, err = f.Printer(cmd, mapping, cmdutil.GetFlagBool(cmd, "no-headers")) + if err != nil { + return nil, err + } + } + return printer, nil +} + +// ClientMapperForCommand returns a ClientMapper for the given command and factory. +func (f *Factory) ClientMapperForCommand(cmd *cobra.Command) resource.ClientMapper { + return resource.ClientMapperFunc(func(mapping *meta.RESTMapping) (resource.RESTClient, error) { + return f.RESTClient(cmd, mapping) + }) +} + // DefaultClientConfig creates a clientcmd.ClientConfig with the following hierarchy: // 1. Use the kubeconfig builder. The number of merges and overrides here gets a little crazy. Stay with me. // 1. Merge together the kubeconfig itself. This is done with the following hierarchy and merge rules: @@ -266,13 +323,6 @@ func DefaultClientConfig(flags *pflag.FlagSet) clientcmd.ClientConfig { return clientConfig } -// ClientMapperForCommand returns a ClientMapper for the given command and factory. -func ClientMapperForCommand(cmd *cobra.Command, f *Factory) resource.ClientMapper { - return resource.ClientMapperFunc(func(mapping *meta.RESTMapping) (resource.RESTClient, error) { - return f.RESTClient(cmd, mapping) - }) -} - func checkErr(err error) { if err != nil { glog.FatalDepth(1, err) diff --git a/pkg/kubectl/cmd/cmd_test.go b/pkg/kubectl/cmd/cmd_test.go index ef5dc0bc674..e813e9f7414 100644 --- a/pkg/kubectl/cmd/cmd_test.go +++ b/pkg/kubectl/cmd/cmd_test.go @@ -21,6 +21,7 @@ import ( "fmt" "io" "io/ioutil" + "os" "testing" "github.com/GoogleCloudPlatform/kubernetes/pkg/api" @@ -203,3 +204,43 @@ func TestClientVersions(t *testing.T) { } } } + +func ExamplePrintReplicationController() { + f, tf, codec := NewAPIFactory() + tf.Printer = kubectl.NewHumanReadablePrinter(false) + tf.Client = &client.FakeRESTClient{ + Codec: codec, + Client: nil, + } + cmd := f.NewCmdRunContainer(os.Stdout) + ctrl := &api.ReplicationController{ + ObjectMeta: api.ObjectMeta{ + Name: "foo", + Labels: map[string]string{"foo": "bar"}, + }, + Spec: api.ReplicationControllerSpec{ + Replicas: 1, + Selector: map[string]string{"foo": "bar"}, + Template: &api.PodTemplateSpec{ + ObjectMeta: api.ObjectMeta{ + Labels: map[string]string{"foo": "bar"}, + }, + Spec: api.PodSpec{ + Containers: []api.Container{ + { + Name: "foo", + Image: "someimage", + }, + }, + }, + }, + }, + } + err := f.PrintObject(cmd, ctrl, os.Stdout) + if err != nil { + fmt.Printf("Unexpected error: %v", err) + } + // Output: + // CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS + // foo foo someimage foo=bar 1 +} diff --git a/pkg/kubectl/cmd/config/view.go b/pkg/kubectl/cmd/config/view.go index 4f8c83fc50e..738746d9896 100644 --- a/pkg/kubectl/cmd/config/view.go +++ b/pkg/kubectl/cmd/config/view.go @@ -21,11 +21,12 @@ import ( "io" "os" - "github.com/ghodss/yaml" + "github.com/golang/glog" "github.com/spf13/cobra" "github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd" clientcmdapi "github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd/api" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" ) type viewOptions struct { @@ -38,40 +39,45 @@ func NewCmdConfigView(out io.Writer, pathOptions *pathOptions) *cobra.Command { cmd := &cobra.Command{ Use: "view", - Short: "displays the specified .kubeconfig file or a merged result", - Long: `displays the specified .kubeconfig file or a merged result`, + Short: "displays merged .kubeconfig settings or a specified .kubeconfig file.", + Long: `displays merged .kubeconfig settings or a specified .kubeconfig file. +Examples: + // Show merged .kubeconfig settings. + $ kubectl config view + + // Show only local ./.kubeconfig settings + $ kubectl config view --local`, Run: func(cmd *cobra.Command, args []string) { - err := options.run() + printer, _, err := util.PrinterForCommand(cmd) if err != nil { - fmt.Printf("%v\n", err) + glog.FatalDepth(1, err) + } + config, err := options.loadConfig() + if err != nil { + glog.FatalDepth(1, err) + } + err = printer.PrintObj(config, out) + if err != nil { + glog.FatalDepth(1, err) } }, } - cmd.Flags().BoolVar(&options.merge, "merge", false, "merge together the full hierarchy of .kubeconfig files") - + util.AddPrinterFlags(cmd) + // Default to yaml + cmd.Flags().Set("output", "yaml") + cmd.Flags().BoolVar(&options.merge, "merge", true, "merge together the full hierarchy of .kubeconfig files") return cmd } -func (o viewOptions) run() error { +func (o viewOptions) loadConfig() (*clientcmdapi.Config, error) { err := o.validate() if err != nil { - return err + return nil, err } config, _, err := o.getStartingConfig() - if err != nil { - return err - } - - content, err := yaml.Marshal(config) - if err != nil { - return err - } - - fmt.Printf("%v", string(content)) - - return nil + return config, err } func (o viewOptions) validate() error { diff --git a/pkg/kubectl/cmd/create.go b/pkg/kubectl/cmd/create.go index 1038560eed6..07fef112291 100644 --- a/pkg/kubectl/cmd/create.go +++ b/pkg/kubectl/cmd/create.go @@ -51,7 +51,7 @@ Examples: checkErr(err) mapper, typer := f.Object(cmd) - r := resource.NewBuilder(mapper, typer, ClientMapperForCommand(cmd, f)). + r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)). ContinueOnError(). NamespaceParam(cmdNamespace).RequireNamespace(). FilenameParam(flags.Filenames...). diff --git a/pkg/kubectl/cmd/delete.go b/pkg/kubectl/cmd/delete.go index 94704056388..753ecf69314 100644 --- a/pkg/kubectl/cmd/delete.go +++ b/pkg/kubectl/cmd/delete.go @@ -23,6 +23,7 @@ import ( "github.com/spf13/cobra" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" + cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" ) @@ -62,11 +63,11 @@ Examples: checkErr(err) mapper, typer := f.Object(cmd) - r := resource.NewBuilder(mapper, typer, ClientMapperForCommand(cmd, f)). + r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(flags.Filenames...). - SelectorParam(GetFlagString(cmd, "selector")). + SelectorParam(cmdutil.GetFlagString(cmd, "selector")). ResourceTypeOrNameArgs(args...). Flatten(). Do() diff --git a/pkg/kubectl/cmd/describe.go b/pkg/kubectl/cmd/describe.go index 7950d57cb73..a8770afda7e 100644 --- a/pkg/kubectl/cmd/describe.go +++ b/pkg/kubectl/cmd/describe.go @@ -20,6 +20,7 @@ import ( "fmt" "io" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/spf13/cobra" ) @@ -36,7 +37,7 @@ given resource.`, checkErr(err) mapper, _ := f.Object(cmd) - mapping, namespace, name := ResourceFromArgs(cmd, args, mapper, cmdNamespace) + mapping, namespace, name := util.ResourceFromArgs(cmd, args, mapper, cmdNamespace) describer, err := f.Describer(cmd, mapping) checkErr(err) diff --git a/pkg/kubectl/cmd/expose.go b/pkg/kubectl/cmd/expose.go index 956da11f3ba..d4ae9d268f0 100644 --- a/pkg/kubectl/cmd/expose.go +++ b/pkg/kubectl/cmd/expose.go @@ -22,6 +22,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/spf13/cobra" ) @@ -51,27 +52,28 @@ $ kubectl expose streamer --port=4100 --protocol=udp --service-name=video-stream client, err := f.Client(cmd) checkErr(err) - generatorName := GetFlagString(cmd, "generator") + generatorName := util.GetFlagString(cmd, "generator") + generator, found := kubectl.Generators[generatorName] if !found { usageError(cmd, fmt.Sprintf("Generator: %s not found.", generator)) } - if GetFlagInt(cmd, "port") < 1 { + if util.GetFlagInt(cmd, "port") < 1 { usageError(cmd, "--port is required and must be a positive integer.") } names := generator.ParamNames() params := kubectl.MakeParams(cmd, names) - if len(GetFlagString(cmd, "service-name")) == 0 { + if len(util.GetFlagString(cmd, "service-name")) == 0 { params["name"] = args[0] } else { - params["name"] = GetFlagString(cmd, "service-name") + params["name"] = util.GetFlagString(cmd, "service-name") } if _, found := params["selector"]; !found { rc, err := client.ReplicationControllers(namespace).Get(args[0]) checkErr(err) params["selector"] = kubectl.MakeLabels(rc.Spec.Selector) } - if GetFlagBool(cmd, "create-external-load-balancer") { + if util.GetFlagBool(cmd, "create-external-load-balancer") { params["create-external-load-balancer"] = "true" } @@ -81,22 +83,22 @@ $ kubectl expose streamer --port=4100 --protocol=udp --service-name=video-stream service, err := generator.Generate(params) checkErr(err) - inline := GetFlagString(cmd, "overrides") + inline := util.GetFlagString(cmd, "overrides") if len(inline) > 0 { - Merge(service, inline, "Service") + util.Merge(service, inline, "Service") } // TODO: extract this flag to a central location, when such a location exists. - if !GetFlagBool(cmd, "dry-run") { + if !util.GetFlagBool(cmd, "dry-run") { service, err = client.Services(namespace).Create(service.(*api.Service)) checkErr(err) } - err = PrintObject(cmd, service, f, out) + err = f.PrintObject(cmd, service, out) checkErr(err) }, } - AddPrinterFlags(cmd) + util.AddPrinterFlags(cmd) cmd.Flags().String("generator", "service/v1", "The name of the api generator that you want to use. Default 'service/v1'") cmd.Flags().String("protocol", "TCP", "The network protocol for the service you want to be created. Default 'tcp'") cmd.Flags().Int("port", -1, "The port that the service should serve on. Required.") diff --git a/pkg/kubectl/cmd/get.go b/pkg/kubectl/cmd/get.go index 273fc1d8688..25977c31ab4 100644 --- a/pkg/kubectl/cmd/get.go +++ b/pkg/kubectl/cmd/get.go @@ -23,6 +23,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource" "github.com/GoogleCloudPlatform/kubernetes/pkg/watch" @@ -59,7 +60,7 @@ Examples: RunGet(f, out, cmd, args) }, } - AddPrinterFlags(cmd) + util.AddPrinterFlags(cmd) cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on") cmd.Flags().BoolP("watch", "w", false, "After listing/getting the requested object, watch for changes.") cmd.Flags().Bool("watch-only", false, "Watch for changes to the requested object(s), without listing/getting first.") @@ -70,16 +71,16 @@ Examples: // TODO: convert all direct flag accessors to a struct and pass that instead of cmd // TODO: return an error instead of using glog.Fatal and checkErr func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) { - selector := GetFlagString(cmd, "selector") + selector := util.GetFlagString(cmd, "selector") mapper, typer := f.Object(cmd) cmdNamespace, err := f.DefaultNamespace(cmd) checkErr(err) // handle watch separately since we cannot watch multiple resource types - isWatch, isWatchOnly := GetFlagBool(cmd, "watch"), GetFlagBool(cmd, "watch-only") + isWatch, isWatchOnly := util.GetFlagBool(cmd, "watch"), util.GetFlagBool(cmd, "watch-only") if isWatch || isWatchOnly { - r := resource.NewBuilder(mapper, typer, ClientMapperForCommand(cmd, f)). + r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)). NamespaceParam(cmdNamespace).DefaultNamespace(). SelectorParam(selector). ResourceTypeOrNameArgs(args...). @@ -89,7 +90,7 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) { mapping, err := r.ResourceMapping() checkErr(err) - printer, err := PrinterForMapping(f, cmd, mapping) + printer, err := f.PrinterForMapping(cmd, mapping) checkErr(err) obj, err := r.Object() @@ -115,12 +116,12 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) { return } - b := resource.NewBuilder(mapper, typer, ClientMapperForCommand(cmd, f)). + b := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)). NamespaceParam(cmdNamespace).DefaultNamespace(). SelectorParam(selector). ResourceTypeOrNameArgs(args...). Latest() - printer, generic, err := PrinterForCommand(cmd) + printer, generic, err := util.PrinterForCommand(cmd) checkErr(err) if generic { @@ -129,7 +130,7 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) { defaultVersion := clientConfig.Version // the outermost object will be converted to the output-version - version := outputVersion(cmd, defaultVersion) + version := util.OutputVersion(cmd, defaultVersion) if len(version) == 0 { // TODO: add a new ResourceBuilder mode for Object() that attempts to ensure the objects // are in the appropriate version if one exists (and if not, use the best effort). @@ -149,7 +150,7 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) { // use the default printer for each object err = b.Do().Visit(func(r *resource.Info) error { - printer, err := PrinterForMapping(f, cmd, r.Mapping) + printer, err := f.PrinterForMapping(cmd, r.Mapping) if err != nil { return err } diff --git a/pkg/kubectl/cmd/log.go b/pkg/kubectl/cmd/log.go index f1067172b5d..7a8f768ce34 100644 --- a/pkg/kubectl/cmd/log.go +++ b/pkg/kubectl/cmd/log.go @@ -20,6 +20,7 @@ import ( "io" "strconv" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/spf13/cobra" ) @@ -66,7 +67,7 @@ Examples: } follow := false - if GetFlagBool(cmd, "follow") { + if util.GetFlagBool(cmd, "follow") { follow = true } diff --git a/pkg/kubectl/cmd/printing_test.go b/pkg/kubectl/cmd/printing_test.go deleted file mode 100644 index 9dc8d06d99b..00000000000 --- a/pkg/kubectl/cmd/printing_test.go +++ /dev/null @@ -1,67 +0,0 @@ -/* -Copyright 2014 Google Inc. All rights reserved. - -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. -*/ - -package cmd_test - -import ( - "fmt" - "os" - - "github.com/GoogleCloudPlatform/kubernetes/pkg/api" - "github.com/GoogleCloudPlatform/kubernetes/pkg/client" - "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" - . "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd" -) - -func ExamplePrintReplicationController() { - f, tf, codec := NewAPIFactory() - tf.Printer = kubectl.NewHumanReadablePrinter(false) - tf.Client = &client.FakeRESTClient{ - Codec: codec, - Client: nil, - } - cmd := f.NewCmdRunContainer(os.Stdout) - ctrl := &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"foo": "bar"}, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 1, - Selector: map[string]string{"foo": "bar"}, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"foo": "bar"}, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - }, - }, - }, - }, - }, - } - err := PrintObject(cmd, ctrl, f, os.Stdout) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - // Output: - // CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS - // foo foo someimage foo=bar 1 -} diff --git a/pkg/kubectl/cmd/proxy.go b/pkg/kubectl/cmd/proxy.go index 920562a62ea..4896be6f5f8 100644 --- a/pkg/kubectl/cmd/proxy.go +++ b/pkg/kubectl/cmd/proxy.go @@ -18,8 +18,10 @@ package cmd import ( "io" + "strings" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/golang/glog" "github.com/spf13/cobra" ) @@ -30,18 +32,23 @@ func (f *Factory) NewCmdProxy(out io.Writer) *cobra.Command { Short: "Run a proxy to the Kubernetes API server", Long: `Run a proxy to the Kubernetes API server.`, Run: func(cmd *cobra.Command, args []string) { - port := GetFlagInt(cmd, "port") + port := util.GetFlagInt(cmd, "port") glog.Infof("Starting to serve on localhost:%d", port) clientConfig, err := f.ClientConfig(cmd) checkErr(err) - server, err := kubectl.NewProxyServer(GetFlagString(cmd, "www"), clientConfig) + staticPrefix := util.GetFlagString(cmd, "www-prefix") + if !strings.HasSuffix(staticPrefix, "/") { + staticPrefix += "/" + } + server, err := kubectl.NewProxyServer(util.GetFlagString(cmd, "www"), staticPrefix, clientConfig) checkErr(err) glog.Fatal(server.Serve(port)) }, } - cmd.Flags().StringP("www", "w", "", "Also serve static files from the given directory under the prefix /static") + cmd.Flags().StringP("www", "w", "", "Also serve static files from the given directory under the specified prefix") + cmd.Flags().StringP("www-prefix", "P", "/static/", "Prefix to serve static files under, if static file dir is specified") cmd.Flags().IntP("port", "p", 8001, "The port on which to run the proxy") return cmd } diff --git a/pkg/kubectl/cmd/resize.go b/pkg/kubectl/cmd/resize.go index 2a547663427..d04c564498a 100644 --- a/pkg/kubectl/cmd/resize.go +++ b/pkg/kubectl/cmd/resize.go @@ -21,6 +21,7 @@ import ( "io" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/spf13/cobra" ) @@ -44,7 +45,7 @@ Examples: $ kubectl resize --current-replicas=2 --replicas=3 replicationcontrollers foo `, Run: func(cmd *cobra.Command, args []string) { - count := GetFlagInt(cmd, "replicas") + count := util.GetFlagInt(cmd, "replicas") if len(args) != 2 || count < 0 { usageError(cmd, "--replicas= ") } @@ -53,13 +54,13 @@ Examples: checkErr(err) mapper, _ := f.Object(cmd) - mapping, namespace, name := ResourceFromArgs(cmd, args, mapper, cmdNamespace) + mapping, namespace, name := util.ResourceFromArgs(cmd, args, mapper, cmdNamespace) resizer, err := f.Resizer(cmd, mapping) checkErr(err) - resourceVersion := GetFlagString(cmd, "resource-version") - currentSize := GetFlagInt(cmd, "current-replicas") + resourceVersion := util.GetFlagString(cmd, "resource-version") + currentSize := util.GetFlagInt(cmd, "current-replicas") s, err := resizer.Resize(namespace, name, &kubectl.ResizePrecondition{currentSize, resourceVersion}, uint(count)) checkErr(err) fmt.Fprintf(out, "%s\n", s) diff --git a/pkg/kubectl/cmd/rollingupdate.go b/pkg/kubectl/cmd/rollingupdate.go index 4cf57c565ba..8abcba5b801 100644 --- a/pkg/kubectl/cmd/rollingupdate.go +++ b/pkg/kubectl/cmd/rollingupdate.go @@ -22,6 +22,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/spf13/cobra" ) @@ -48,13 +49,13 @@ $ kubectl rollingupdate frontend-v1 -f frontend-v2.json $ cat frontend-v2.json | kubectl rollingupdate frontend-v1 -f - `, Run: func(cmd *cobra.Command, args []string) { - filename := GetFlagString(cmd, "filename") + filename := util.GetFlagString(cmd, "filename") if len(filename) == 0 { usageError(cmd, "Must specify filename for new controller") } - period := GetFlagDuration(cmd, "update-period") - interval := GetFlagDuration(cmd, "poll-interval") - timeout := GetFlagDuration(cmd, "timeout") + period := util.GetFlagDuration(cmd, "update-period") + interval := util.GetFlagDuration(cmd, "poll-interval") + timeout := util.GetFlagDuration(cmd, "timeout") if len(args) != 1 { usageError(cmd, "Must specify the controller to update") } @@ -67,7 +68,7 @@ $ cat frontend-v2.json | kubectl rollingupdate frontend-v1 -f - cmdApiVersion := clientConfig.Version mapper, typer := f.Object(cmd) - mapping, namespace, newName, data := ResourceFromFile(filename, typer, mapper, schema, cmdApiVersion) + mapping, namespace, newName, data := util.ResourceFromFile(filename, typer, mapper, schema, cmdApiVersion) if mapping.Kind != "ReplicationController" { usageError(cmd, "%s does not specify a valid ReplicationController", filename) } @@ -78,7 +79,7 @@ $ cat frontend-v2.json | kubectl rollingupdate frontend-v1 -f - cmdNamespace, err := f.DefaultNamespace(cmd) checkErr(err) - err = CompareNamespace(cmdNamespace, namespace) + err = util.CompareNamespace(cmdNamespace, namespace) checkErr(err) client, err := f.Client(cmd) diff --git a/pkg/kubectl/cmd/run.go b/pkg/kubectl/cmd/run.go index dc96df3959d..3b6bcab5adf 100644 --- a/pkg/kubectl/cmd/run.go +++ b/pkg/kubectl/cmd/run.go @@ -22,6 +22,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/spf13/cobra" ) @@ -55,7 +56,7 @@ Examples: client, err := f.Client(cmd) checkErr(err) - generatorName := GetFlagString(cmd, "generator") + generatorName := util.GetFlagString(cmd, "generator") generator, found := kubectl.Generators[generatorName] if !found { usageError(cmd, fmt.Sprintf("Generator: %s not found.", generator)) @@ -70,22 +71,22 @@ Examples: controller, err := generator.Generate(params) checkErr(err) - inline := GetFlagString(cmd, "overrides") + inline := util.GetFlagString(cmd, "overrides") if len(inline) > 0 { - Merge(controller, inline, "ReplicationController") + util.Merge(controller, inline, "ReplicationController") } // TODO: extract this flag to a central location, when such a location exists. - if !GetFlagBool(cmd, "dry-run") { + if !util.GetFlagBool(cmd, "dry-run") { controller, err = client.ReplicationControllers(namespace).Create(controller.(*api.ReplicationController)) checkErr(err) } - err = PrintObject(cmd, controller, f, out) + err = f.PrintObject(cmd, controller, out) checkErr(err) }, } - AddPrinterFlags(cmd) + util.AddPrinterFlags(cmd) cmd.Flags().String("generator", "run-container/v1", "The name of the api generator that you want to use. Default 'run-container-controller/v1'") cmd.Flags().String("image", "", "The image for the container you wish to run.") cmd.Flags().IntP("replicas", "r", 1, "Number of replicas to create for this container. Default 1") diff --git a/pkg/kubectl/cmd/stop.go b/pkg/kubectl/cmd/stop.go index 17e2782f3d0..3da95bf67a3 100644 --- a/pkg/kubectl/cmd/stop.go +++ b/pkg/kubectl/cmd/stop.go @@ -20,6 +20,7 @@ import ( "fmt" "io" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/spf13/cobra" ) @@ -42,7 +43,7 @@ Examples: } cmdNamespace, err := f.DefaultNamespace(cmd) mapper, _ := f.Object(cmd) - mapping, namespace, name := ResourceFromArgs(cmd, args, mapper, cmdNamespace) + mapping, namespace, name := util.ResourceFromArgs(cmd, args, mapper, cmdNamespace) reaper, err := f.Reaper(cmd, mapping) checkErr(err) diff --git a/pkg/kubectl/cmd/update.go b/pkg/kubectl/cmd/update.go index 69ebb5b19a4..83c239355f0 100644 --- a/pkg/kubectl/cmd/update.go +++ b/pkg/kubectl/cmd/update.go @@ -20,6 +20,7 @@ import ( "fmt" "io" + cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/spf13/cobra" @@ -53,14 +54,14 @@ Examples: checkErr(err) mapper, typer := f.Object(cmd) - r := resource.NewBuilder(mapper, typer, ClientMapperForCommand(cmd, f)). + r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)). ContinueOnError(). NamespaceParam(cmdNamespace).RequireNamespace(). FilenameParam(flags.Filenames...). Flatten(). Do() - patch := GetFlagString(cmd, "patch") + patch := cmdutil.GetFlagString(cmd, "patch") if len(flags.Filenames) == 0 && len(patch) == 0 { usageError(cmd, "Must specify --filename or --patch to update") } @@ -102,7 +103,7 @@ func updateWithPatch(cmd *cobra.Command, args []string, f *Factory, patch string checkErr(err) mapper, _ := f.Object(cmd) - mapping, namespace, name := ResourceFromArgs(cmd, args, mapper, cmdNamespace) + mapping, namespace, name := cmdutil.ResourceFromArgs(cmd, args, mapper, cmdNamespace) client, err := f.RESTClient(cmd, mapping) checkErr(err) @@ -110,7 +111,7 @@ func updateWithPatch(cmd *cobra.Command, args []string, f *Factory, patch string obj, err := helper.Get(namespace, name) checkErr(err) - Merge(obj, patch, mapping.Kind) + cmdutil.Merge(obj, patch, mapping.Kind) data, err := helper.Codec.Encode(obj) checkErr(err) diff --git a/pkg/kubectl/cmd/helpers.go b/pkg/kubectl/cmd/util/helpers.go similarity index 95% rename from pkg/kubectl/cmd/helpers.go rename to pkg/kubectl/cmd/util/helpers.go index aa3c7053cdc..d3001c059d4 100644 --- a/pkg/kubectl/cmd/helpers.go +++ b/pkg/kubectl/cmd/util/helpers.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package util import ( "encoding/json" @@ -34,6 +34,18 @@ import ( "github.com/spf13/cobra" ) +func checkErr(err error) { + if err != nil { + glog.FatalDepth(1, err) + } +} + +func usageError(cmd *cobra.Command, format string, args ...interface{}) { + glog.Errorf(format, args...) + glog.Errorf("See '%s -h' for help.", cmd.CommandPath()) + os.Exit(1) +} + func GetFlagString(cmd *cobra.Command, flag string) string { f := cmd.Flags().Lookup(flag) if f == nil { diff --git a/pkg/kubectl/cmd/helpers_test.go b/pkg/kubectl/cmd/util/helpers_test.go similarity index 99% rename from pkg/kubectl/cmd/helpers_test.go rename to pkg/kubectl/cmd/util/helpers_test.go index ed0ec504ea3..32673373c74 100644 --- a/pkg/kubectl/cmd/helpers_test.go +++ b/pkg/kubectl/cmd/util/helpers_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package util import ( "reflect" diff --git a/pkg/kubectl/cmd/printing.go b/pkg/kubectl/cmd/util/printing.go similarity index 50% rename from pkg/kubectl/cmd/printing.go rename to pkg/kubectl/cmd/util/printing.go index 3f3b5ad5bae..284b5442c00 100644 --- a/pkg/kubectl/cmd/printing.go +++ b/pkg/kubectl/cmd/util/printing.go @@ -14,16 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package util import ( - "fmt" - "io" - - "github.com/GoogleCloudPlatform/kubernetes/pkg/api" - "github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" - "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/spf13/cobra" ) @@ -35,28 +29,8 @@ func AddPrinterFlags(cmd *cobra.Command) { cmd.Flags().StringP("template", "t", "", "Template string or path to template file to use when -o=template or -o=templatefile.") } -// PrintObject prints an api object given command line flags to modify the output format -func PrintObject(cmd *cobra.Command, obj runtime.Object, f *Factory, out io.Writer) error { - mapper, _ := f.Object(cmd) - _, kind, err := api.Scheme.ObjectVersionAndKind(obj) - if err != nil { - return err - } - - mapping, err := mapper.RESTMapping(kind) - if err != nil { - return err - } - - printer, err := PrinterForMapping(f, cmd, mapping) - if err != nil { - return err - } - return printer.PrintObj(obj, out) -} - -// outputVersion returns the preferred output version for generic content (JSON, YAML, or templates) -func outputVersion(cmd *cobra.Command, defaultVersion string) string { +// OutputVersion returns the preferred output version for generic content (JSON, YAML, or templates) +func OutputVersion(cmd *cobra.Command, defaultVersion string) string { outputVersion := GetFlagString(cmd, "output-version") if len(outputVersion) == 0 { outputVersion = defaultVersion @@ -75,32 +49,3 @@ func PrinterForCommand(cmd *cobra.Command) (kubectl.ResourcePrinter, bool, error return kubectl.GetPrinter(outputFormat, templateFile) } - -// PrinterForMapping returns a printer suitable for displaying the provided resource type. -// Requires that printer flags have been added to cmd (see AddPrinterFlags). -func PrinterForMapping(f *Factory, cmd *cobra.Command, mapping *meta.RESTMapping) (kubectl.ResourcePrinter, error) { - printer, ok, err := PrinterForCommand(cmd) - if err != nil { - return nil, err - } - if ok { - clientConfig, err := f.ClientConfig(cmd) - checkErr(err) - defaultVersion := clientConfig.Version - - version := outputVersion(cmd, defaultVersion) - if len(version) == 0 { - version = mapping.APIVersion - } - if len(version) == 0 { - return nil, fmt.Errorf("you must specify an output-version when using this output format") - } - printer = kubectl.NewVersionedPrinter(printer, mapping.ObjectConvertor, version) - } else { - printer, err = f.Printer(cmd, mapping, GetFlagBool(cmd, "no-headers")) - if err != nil { - return nil, err - } - } - return printer, nil -} diff --git a/pkg/kubectl/cmd/resource.go b/pkg/kubectl/cmd/util/resource.go similarity index 99% rename from pkg/kubectl/cmd/resource.go rename to pkg/kubectl/cmd/util/resource.go index ab440996786..a4f4ca9310b 100644 --- a/pkg/kubectl/cmd/resource.go +++ b/pkg/kubectl/cmd/util/resource.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package util import ( "fmt" diff --git a/pkg/kubectl/cmd/version.go b/pkg/kubectl/cmd/version.go index 5e434a58e16..0a8282ec5b3 100644 --- a/pkg/kubectl/cmd/version.go +++ b/pkg/kubectl/cmd/version.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" ) func (f *Factory) NewCmdVersion(out io.Writer) *cobra.Command { @@ -29,7 +30,7 @@ func (f *Factory) NewCmdVersion(out io.Writer) *cobra.Command { Use: "version", Short: "Print version of client and server", Run: func(cmd *cobra.Command, args []string) { - if GetFlagBool(cmd, "client") { + if util.GetFlagBool(cmd, "client") { kubectl.GetClientVersion(out) return } diff --git a/pkg/kubectl/proxy_server.go b/pkg/kubectl/proxy_server.go index a92e0485c4f..29498a80d83 100644 --- a/pkg/kubectl/proxy_server.go +++ b/pkg/kubectl/proxy_server.go @@ -33,7 +33,7 @@ type ProxyServer struct { // NewProxyServer creates and installs a new ProxyServer. // It automatically registers the created ProxyServer to http.DefaultServeMux. -func NewProxyServer(filebase string, cfg *client.Config) (*ProxyServer, error) { +func NewProxyServer(filebase string, staticPrefix string, cfg *client.Config) (*ProxyServer, error) { prefix := cfg.Prefix if prefix == "" { prefix = "/api" @@ -47,7 +47,7 @@ func NewProxyServer(filebase string, cfg *client.Config) (*ProxyServer, error) { return nil, err } http.Handle("/api/", http.StripPrefix("/api/", proxy)) - http.Handle("/static/", newFileHandler("/static/", filebase)) + http.Handle(staticPrefix, newFileHandler(staticPrefix, filebase)) return proxy, nil } diff --git a/pkg/kubelet/dockertools/docker.go b/pkg/kubelet/dockertools/docker.go index ff07c19528e..41e5a98ef66 100644 --- a/pkg/kubelet/dockertools/docker.go +++ b/pkg/kubelet/dockertools/docker.go @@ -25,6 +25,7 @@ import ( "io" "io/ioutil" "math/rand" + "os" "os/exec" "strconv" "strings" @@ -104,7 +105,7 @@ type dockerContainerCommandRunner struct { var dockerAPIVersionWithExec = []uint{1, 15} // Returns the major and minor version numbers of docker server. -func (d *dockerContainerCommandRunner) getDockerServerVersion() ([]uint, error) { +func (d *dockerContainerCommandRunner) GetDockerServerVersion() ([]uint, error) { env, err := d.client.Version() if err != nil { return nil, fmt.Errorf("failed to get docker server version - %v", err) @@ -127,7 +128,7 @@ func (d *dockerContainerCommandRunner) getDockerServerVersion() ([]uint, error) } func (d *dockerContainerCommandRunner) nativeExecSupportExists() (bool, error) { - version, err := d.getDockerServerVersion() + version, err := d.GetDockerServerVersion() if err != nil { return false, err } @@ -641,6 +642,35 @@ func parseImageName(image string) (string, string) { return image, tag } +// Get a docker endpoint, either from the string passed in, or $DOCKER_HOST environment variables +func getDockerEndpoint(dockerEndpoint string) string { + var endpoint string + if len(dockerEndpoint) > 0 { + endpoint = dockerEndpoint + } else if len(os.Getenv("DOCKER_HOST")) > 0 { + endpoint = os.Getenv("DOCKER_HOST") + } else { + endpoint = "unix:///var/run/docker.sock" + } + glog.Infof("Connecting to docker on %s", endpoint) + + return endpoint +} + +func ConnectToDockerOrDie(dockerEndpoint string) DockerInterface { + if dockerEndpoint == "fake://" { + return &FakeDockerClient{ + VersionInfo: []string{"apiVersion=1.16"}, + } + } + client, err := docker.NewClient(getDockerEndpoint(dockerEndpoint)) + if err != nil { + glog.Fatal("Couldn't connect to docker.") + } + return client +} + type ContainerCommandRunner interface { RunInContainer(containerID string, cmd []string) ([]byte, error) + GetDockerServerVersion() ([]uint, error) } diff --git a/pkg/kubelet/dockertools/docker_test.go b/pkg/kubelet/dockertools/docker_test.go index 55035aa0159..2402d25c5a7 100644 --- a/pkg/kubelet/dockertools/docker_test.go +++ b/pkg/kubelet/dockertools/docker_test.go @@ -123,7 +123,7 @@ func TestContainerManifestNaming(t *testing.T) { func TestGetDockerServerVersion(t *testing.T) { fakeDocker := &FakeDockerClient{VersionInfo: docker.Env{"Client version=1.2", "Server version=1.1.3", "Server API version=1.15"}} runner := dockerContainerCommandRunner{fakeDocker} - version, err := runner.getDockerServerVersion() + version, err := runner.GetDockerServerVersion() if err != nil { t.Errorf("got error while getting docker server version - %s", err) } diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index 88942797e17..815e15395a9 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -55,6 +55,7 @@ const defaultChanSize = 1024 const minShares = 2 const sharesPerCPU = 1024 const milliCPUToCPU = 1000 +const maxRetries int = 3 // SyncHandler is an interface implemented by Kubelet, for testability type SyncHandler interface { @@ -1380,6 +1381,15 @@ func (kl *Kubelet) syncLoop(updates <-chan PodUpdate, handler SyncHandler) { } } +// Returns Docker version for this Kubelet. +func (kl *Kubelet) GetDockerVersion() ([]uint, error) { + if kl.dockerClient == nil { + return nil, fmt.Errorf("no Docker client") + } + dockerRunner := dockertools.NewDockerContainerCommandRunner(kl.dockerClient) + return dockerRunner.GetDockerServerVersion() +} + // GetKubeletContainerLogs returns logs from the container // The second parameter of GetPodStatus and FindPodContainer methods represents pod UUID, which is allowed to be blank // TODO: this method is returning logs of random container attempts, when it should be returning the most recent attempt @@ -1436,7 +1446,7 @@ func (kl *Kubelet) GetPodStatus(podFullName string, uid types.UID) (api.PodStatu return podStatus, err } -func (kl *Kubelet) probeLiveness(podFullName string, podUID types.UID, status api.PodStatus, container api.Container, dockerContainer *docker.APIContainers) (probe.Status, error) { +func (kl *Kubelet) probeLiveness(podFullName string, podUID types.UID, status api.PodStatus, container api.Container, dockerContainer *docker.APIContainers) (healthStatus probe.Result, err error) { // Give the container 60 seconds to start up. if container.LivenessProbe == nil { return probe.Success, nil @@ -1444,7 +1454,13 @@ func (kl *Kubelet) probeLiveness(podFullName string, podUID types.UID, status ap if time.Now().Unix()-dockerContainer.Created < container.LivenessProbe.InitialDelaySeconds { return probe.Success, nil } - return kl.probeContainer(container.LivenessProbe, podFullName, podUID, status, container) + for i := 0; i < maxRetries; i++ { + healthStatus, err = kl.probeContainer(container.LivenessProbe, podFullName, podUID, status, container) + if healthStatus == probe.Success { + return + } + } + return healthStatus, err } // Returns logs of current machine. diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index 8734fa79bb1..e0a7c976c2f 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -1367,6 +1367,10 @@ func (f *fakeContainerCommandRunner) RunInContainer(id string, cmd []string) ([] return []byte{}, f.E } +func (f *fakeContainerCommandRunner) GetDockerServerVersion() ([]uint, error) { + return nil, nil +} + func TestRunInContainerNoSuchPod(t *testing.T) { fakeCommandRunner := fakeContainerCommandRunner{} kubelet, fakeDocker := newTestKubelet(t) diff --git a/pkg/kubelet/probe.go b/pkg/kubelet/probe.go index 8d107872d70..a3dc573ad85 100644 --- a/pkg/kubelet/probe.go +++ b/pkg/kubelet/probe.go @@ -19,6 +19,7 @@ package kubelet import ( "fmt" "strconv" + "time" "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/probe" @@ -38,7 +39,14 @@ var ( tcprober = tcprobe.New() ) -func (kl *Kubelet) probeContainer(p *api.Probe, podFullName string, podUID types.UID, status api.PodStatus, container api.Container) (probe.Status, error) { +func (kl *Kubelet) probeContainer(p *api.Probe, podFullName string, podUID types.UID, status api.PodStatus, container api.Container) (probe.Result, error) { + var timeout time.Duration + secs := container.LivenessProbe.TimeoutSeconds + if secs > 0 { + timeout = time.Duration(secs) * time.Second + } else { + timeout = 1 * time.Second + } if p.Exec != nil { return execprober.Probe(kl.newExecInContainer(podFullName, podUID, container)) } @@ -47,14 +55,15 @@ func (kl *Kubelet) probeContainer(p *api.Probe, podFullName string, podUID types if err != nil { return probe.Unknown, err } - return httprober.Probe(extractGetParams(p.HTTPGet, status, port)) + host, port, path := extractGetParams(p.HTTPGet, status, port) + return httprober.Probe(host, port, path, timeout) } if p.TCPSocket != nil { port, err := extractPort(p.TCPSocket.Port, container) if err != nil { return probe.Unknown, err } - return tcprober.Probe(status.PodIP, port) + return tcprober.Probe(status.PodIP, port, timeout) } glog.Warningf("Failed to find probe builder for %s %+v", container.Name, container.LivenessProbe) return probe.Unknown, nil diff --git a/pkg/kubelet/server.go b/pkg/kubelet/server.go index 222cedb52e2..35953a15bf8 100644 --- a/pkg/kubelet/server.go +++ b/pkg/kubelet/server.go @@ -31,7 +31,6 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest" - "github.com/GoogleCloudPlatform/kubernetes/pkg/healthz" "github.com/GoogleCloudPlatform/kubernetes/pkg/httplog" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/types" @@ -64,6 +63,7 @@ func ListenAndServeKubeletServer(host HostInterface, address net.IP, port uint, type HostInterface interface { GetContainerInfo(podFullName string, uid types.UID, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error) GetRootInfo(req *info.ContainerInfoRequest) (*info.ContainerInfo, error) + GetDockerVersion() ([]uint, error) GetMachineInfo() (*info.MachineInfo, error) GetBoundPods() ([]api.BoundPod, error) GetPodByName(namespace, name string) (*api.BoundPod, bool) @@ -88,7 +88,7 @@ func NewServer(host HostInterface, enableDebuggingHandlers bool) Server { // InstallDefaultHandlers registers the default set of supported HTTP request patterns with the mux. func (s *Server) InstallDefaultHandlers() { - healthz.InstallHandler(s.mux) + s.mux.HandleFunc("/healthz", s.handleHealthz) s.mux.HandleFunc("/podInfo", s.handlePodInfoOld) s.mux.HandleFunc("/api/v1beta1/podInfo", s.handlePodInfoVersioned) s.mux.HandleFunc("/boundPods", s.handleBoundPods) @@ -109,6 +109,42 @@ func (s *Server) error(w http.ResponseWriter, err error) { http.Error(w, fmt.Sprintf("Internal Error: %v", err), http.StatusInternalServerError) } +func isValidDockerVersion(ver []uint) (bool, string) { + minAllowedVersion := []uint{1, 15} + for i := 0; i < len(ver) && i < len(minAllowedVersion); i++ { + if ver[i] != minAllowedVersion[i] { + if ver[i] < minAllowedVersion[i] { + versions := make([]string, len(ver)) + for i, v := range ver { + versions[i] = fmt.Sprint(v) + } + return false, strings.Join(versions, ".") + } + return true, "" + } + } + return true, "" +} + +// handleHealthz handles /healthz request and checks Docker version +func (s *Server) handleHealthz(w http.ResponseWriter, req *http.Request) { + versions, err := s.host.GetDockerVersion() + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("unknown Docker version")) + return + } + valid, version := isValidDockerVersion(versions) + if !valid { + w.WriteHeader(http.StatusInternalServerError) + msg := "Docker version is too old (" + version + ")" + w.Write([]byte(msg)) + return + } + w.WriteHeader(http.StatusOK) + w.Write([]byte("ok")) +} + // handleContainerLogs handles containerLogs request against the Kubelet func (s *Server) handleContainerLogs(w http.ResponseWriter, req *http.Request) { defer req.Body.Close() diff --git a/pkg/kubelet/server/server.go b/pkg/kubelet/server/server.go index 943e6da99c0..13860d6ad8e 100644 --- a/pkg/kubelet/server/server.go +++ b/pkg/kubelet/server/server.go @@ -203,7 +203,7 @@ func (s *KubeletServer) Run(_ []string) error { CAdvisorPort: s.CAdvisorPort, EnableServer: s.EnableServer, EnableDebuggingHandlers: s.EnableDebuggingHandlers, - DockerClient: util.ConnectToDockerOrDie(s.DockerEndpoint), + DockerClient: dockertools.ConnectToDockerOrDie(s.DockerEndpoint), KubeClient: client, EtcdClient: kubelet.EtcdClientOrDie(s.EtcdServerList, s.EtcdConfigFile), MasterServiceNamespace: s.MasterServiceNamespace, diff --git a/pkg/kubelet/server_test.go b/pkg/kubelet/server_test.go index 69dd77eeb12..32c5f9967e9 100644 --- a/pkg/kubelet/server_test.go +++ b/pkg/kubelet/server_test.go @@ -42,6 +42,7 @@ type fakeKubelet struct { boundPodsFunc func() ([]api.BoundPod, error) logFunc func(w http.ResponseWriter, req *http.Request) runFunc func(podFullName string, uid types.UID, containerName string, cmd []string) ([]byte, error) + dockerVersionFunc func() ([]uint, error) containerLogsFunc func(podFullName, containerName, tail string, follow bool, stdout, stderr io.Writer) error } @@ -61,6 +62,10 @@ func (fk *fakeKubelet) GetRootInfo(req *info.ContainerInfoRequest) (*info.Contai return fk.rootInfoFunc(req) } +func (fk *fakeKubelet) GetDockerVersion() ([]uint, error) { + return fk.dockerVersionFunc() +} + func (fk *fakeKubelet) GetMachineInfo() (*info.MachineInfo, error) { return fk.machineInfoFunc() } diff --git a/pkg/master/pod_cache.go b/pkg/master/pod_cache.go index d9d1ed3a614..70cf92da24c 100644 --- a/pkg/master/pod_cache.go +++ b/pkg/master/pod_cache.go @@ -135,6 +135,12 @@ func (p *PodCache) getNodeStatus(name string) (*api.NodeStatus, error) { return &node.Status, nil } +func (p *PodCache) clearNodeStatus() { + p.lock.Lock() + defer p.lock.Unlock() + p.currentNodes = map[objKey]api.NodeStatus{} +} + // TODO: once Host gets moved to spec, this can take a podSpec + metadata instead of an // entire pod? func (p *PodCache) updatePodStatus(pod *api.Pod) error { @@ -221,6 +227,10 @@ func (p *PodCache) GarbageCollectPodStatus() { // calling again, or risk having new info getting clobbered by delayed // old info. func (p *PodCache) UpdateAllContainers() { + // TODO: this is silly, we should pro-actively update the pod status when + // the API server makes changes. + p.clearNodeStatus() + ctx := api.NewContext() pods, err := p.pods.ListPods(ctx, labels.Everything()) if err != nil { diff --git a/pkg/master/pod_cache_test.go b/pkg/master/pod_cache_test.go index b87c985fe30..302f44393d0 100644 --- a/pkg/master/pod_cache_test.go +++ b/pkg/master/pod_cache_test.go @@ -254,6 +254,35 @@ func makeUnhealthyNode(name string) *api.Node { } } +func TestPodUpdateAllContainersClearsNodeStatus(t *testing.T) { + node := makeHealthyNode("machine", "1.2.3.5") + pod1 := makePod(api.NamespaceDefault, "foo", "machine", "bar") + pod2 := makePod(api.NamespaceDefault, "baz", "machine", "qux") + config := podCacheTestConfig{ + kubeletContainerInfo: api.PodStatus{ + Info: api.PodInfo{"bar": api.ContainerStatus{}}}, + nodes: []api.Node{*node}, + pods: []api.Pod{*pod1, *pod2}, + } + cache := config.Construct() + + if len(cache.currentNodes) != 0 { + t.Errorf("unexpected node cache: %v", cache.currentNodes) + } + key := objKey{"", "machine"} + cache.currentNodes[key] = makeUnhealthyNode("machine").Status + + cache.UpdateAllContainers() + + if len(cache.currentNodes) != 1 { + t.Errorf("unexpected empty node cache: %v", cache.currentNodes) + } + + if !reflect.DeepEqual(cache.currentNodes[key], node.Status) { + t.Errorf("unexpected status:\n%#v\nexpected:\n%#v\n", cache.currentNodes[key], node.Status) + } +} + func TestPodUpdateAllContainers(t *testing.T) { pod1 := makePod(api.NamespaceDefault, "foo", "machine", "bar") pod2 := makePod(api.NamespaceDefault, "baz", "machine", "qux") diff --git a/pkg/probe/exec/exec.go b/pkg/probe/exec/exec.go index ac5a0f2ccc6..f44c1f111b5 100644 --- a/pkg/probe/exec/exec.go +++ b/pkg/probe/exec/exec.go @@ -33,7 +33,7 @@ func New() ExecProber { type ExecProber struct{} -func (pr ExecProber) Probe(e uexec.Cmd) (probe.Status, error) { +func (pr ExecProber) Probe(e uexec.Cmd) (probe.Result, error) { data, err := e.CombinedOutput() glog.V(4).Infof("health check response: %s", string(data)) if err != nil { diff --git a/pkg/probe/exec/exec_test.go b/pkg/probe/exec/exec_test.go index a2f21365abd..22e7e9b1f54 100644 --- a/pkg/probe/exec/exec_test.go +++ b/pkg/probe/exec/exec_test.go @@ -35,7 +35,7 @@ func (f *FakeCmd) CombinedOutput() ([]byte, error) { func (f *FakeCmd) SetDir(dir string) {} type healthCheckTest struct { - expectedStatus probe.Status + expectedStatus probe.Result expectError bool output []byte err error diff --git a/pkg/probe/http/http.go b/pkg/probe/http/http.go index e3e7898dbc2..65252973198 100644 --- a/pkg/probe/http/http.go +++ b/pkg/probe/http/http.go @@ -21,6 +21,7 @@ import ( "net/http" "net/url" "strconv" + "time" "github.com/GoogleCloudPlatform/kubernetes/pkg/probe" @@ -28,16 +29,17 @@ import ( ) func New() HTTPProber { - return HTTPProber{&http.Client{}} + transport := &http.Transport{} + return HTTPProber{transport} } type HTTPProber struct { - client HTTPGetInterface + transport *http.Transport } // Probe returns a ProbeRunner capable of running an http check. -func (pr *HTTPProber) Probe(host string, port int, path string) (probe.Status, error) { - return DoHTTPProbe(formatURL(host, port, path), pr.client) +func (pr *HTTPProber) Probe(host string, port int, path string, timeout time.Duration) (probe.Result, error) { + return DoHTTPProbe(formatURL(host, port, path), &http.Client{Timeout: timeout, Transport: pr.transport}) } type HTTPGetInterface interface { @@ -48,7 +50,7 @@ type HTTPGetInterface interface { // If the HTTP response code is successful (i.e. 400 > code >= 200), it returns Success. // If the HTTP response code is unsuccessful or HTTP communication fails, it returns Failure. // This is exported because some other packages may want to do direct HTTP probes. -func DoHTTPProbe(url string, client HTTPGetInterface) (probe.Status, error) { +func DoHTTPProbe(url string, client HTTPGetInterface) (probe.Result, error) { res, err := client.Get(url) if err != nil { glog.V(1).Infof("HTTP probe error: %v", err) diff --git a/pkg/probe/http/http_test.go b/pkg/probe/http/http_test.go index fd9009f6615..7d1392d4f19 100644 --- a/pkg/probe/http/http_test.go +++ b/pkg/probe/http/http_test.go @@ -23,6 +23,7 @@ import ( "net/url" "strconv" "testing" + "time" "github.com/GoogleCloudPlatform/kubernetes/pkg/probe" ) @@ -46,20 +47,25 @@ func TestFormatURL(t *testing.T) { } func TestHTTPProbeChecker(t *testing.T) { + handleReq := func(s int) func(w http.ResponseWriter) { + return func(w http.ResponseWriter) { w.WriteHeader(s) } + } + prober := New() testCases := []struct { - status int - health probe.Status + handler func(w http.ResponseWriter) + health probe.Result }{ // The probe will be filled in below. This is primarily testing that an HTTP GET happens. - {http.StatusOK, probe.Success}, - {-1, probe.Failure}, + {handleReq(http.StatusOK), probe.Success}, + {handleReq(-1), probe.Failure}, + {func(w http.ResponseWriter) { time.Sleep(3 * time.Second) }, probe.Failure}, } for _, test := range testCases { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(test.status) + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + test.handler(w) })) - u, err := url.Parse(ts.URL) + u, err := url.Parse(server.URL) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -71,7 +77,7 @@ func TestHTTPProbeChecker(t *testing.T) { if err != nil { t.Errorf("Unexpected error: %v", err) } - health, err := prober.Probe(host, p, "") + health, err := prober.Probe(host, p, "", 1*time.Second) if test.health == probe.Unknown && err == nil { t.Errorf("Expected error") } diff --git a/pkg/probe/probe.go b/pkg/probe/probe.go index b9d1a363a38..72111d4eea2 100644 --- a/pkg/probe/probe.go +++ b/pkg/probe/probe.go @@ -16,16 +16,16 @@ limitations under the License. package probe -type Status int +type Result int // Status values must be one of these constants. const ( - Success Status = iota + Success Result = iota Failure Unknown ) -func (s Status) String() string { +func (s Result) String() string { switch s { case Success: return "success" diff --git a/pkg/probe/tcp/tcp.go b/pkg/probe/tcp/tcp.go index a452a802c74..b1925d26e3f 100644 --- a/pkg/probe/tcp/tcp.go +++ b/pkg/probe/tcp/tcp.go @@ -19,6 +19,7 @@ package tcp import ( "net" "strconv" + "time" "github.com/GoogleCloudPlatform/kubernetes/pkg/probe" @@ -31,16 +32,16 @@ func New() TCPProber { type TCPProber struct{} -func (pr TCPProber) Probe(host string, port int) (probe.Status, error) { - return DoTCPProbe(net.JoinHostPort(host, strconv.Itoa(port))) +func (pr TCPProber) Probe(host string, port int, timeout time.Duration) (probe.Result, error) { + return DoTCPProbe(net.JoinHostPort(host, strconv.Itoa(port)), timeout) } // DoTCPProbe checks that a TCP socket to the address can be opened. // If the socket can be opened, it returns Success // If the socket fails to open, it returns Failure. // This is exported because some other packages may want to do direct TCP probes. -func DoTCPProbe(addr string) (probe.Status, error) { - conn, err := net.Dial("tcp", addr) +func DoTCPProbe(addr string, timeout time.Duration) (probe.Result, error) { + conn, err := net.DialTimeout("tcp", addr, timeout) if err != nil { return probe.Failure, nil } diff --git a/pkg/probe/tcp/tcp_test.go b/pkg/probe/tcp/tcp_test.go index bd8f61fdac0..47b93eb796a 100644 --- a/pkg/probe/tcp/tcp_test.go +++ b/pkg/probe/tcp/tcp_test.go @@ -23,6 +23,7 @@ import ( "net/url" "strconv" "testing" + "time" "github.com/GoogleCloudPlatform/kubernetes/pkg/probe" ) @@ -30,7 +31,7 @@ import ( func TestTcpHealthChecker(t *testing.T) { prober := New() tests := []struct { - expectedStatus probe.Status + expectedStatus probe.Result usePort bool expectError bool }{ @@ -59,7 +60,7 @@ func TestTcpHealthChecker(t *testing.T) { if !test.usePort { p = -1 } - status, err := prober.Probe(host, p) + status, err := prober.Probe(host, p, 1*time.Second) if status != test.expectedStatus { t.Errorf("expected: %v, got: %v", test.expectedStatus, status) } diff --git a/pkg/registry/etcd/etcd.go b/pkg/registry/etcd/etcd.go index d2bd576cb52..0cb49c0246b 100644 --- a/pkg/registry/etcd/etcd.go +++ b/pkg/registry/etcd/etcd.go @@ -214,8 +214,8 @@ func (r *Registry) assignPod(ctx api.Context, podID string, machine string) erro err = r.AtomicUpdate(contKey, &api.BoundPods{}, func(in runtime.Object) (runtime.Object, error) { boundPodList := in.(*api.BoundPods) boundPodList.Items = append(boundPodList.Items, *boundPod) - if !constraint.Allowed(boundPodList.Items) { - return nil, fmt.Errorf("the assignment would cause a constraint violation") + if errors := constraint.Allowed(boundPodList.Items); len(errors) > 0 { + return nil, fmt.Errorf("the assignment would cause the following constraints violation: %v", errors) } return boundPodList, nil }) @@ -251,7 +251,7 @@ func (r *Registry) UpdatePod(ctx api.Context, pod *api.Pod) error { } // There's no race with the scheduler, because either this write will fail because the host // has been updated, or the host update will fail because this pod has been updated. - err = r.EtcdHelper.SetObj(podKey, pod) + err = r.EtcdHelper.SetObj(podKey, pod, 0 /* ttl */) if err != nil { return err } @@ -404,7 +404,7 @@ func (r *Registry) UpdateController(ctx api.Context, controller *api.Replication if err != nil { return err } - err = r.SetObj(key, controller) + err = r.SetObj(key, controller, 0 /* ttl */) return etcderr.InterpretUpdateError(err, "replicationController", controller.Name) } @@ -512,7 +512,7 @@ func (r *Registry) UpdateService(ctx api.Context, svc *api.Service) error { if err != nil { return err } - err = r.SetObj(key, svc) + err = r.SetObj(key, svc, 0 /* ttl */) return etcderr.InterpretUpdateError(err, "service", svc.Name) } @@ -605,7 +605,7 @@ func (r *Registry) CreateMinion(ctx api.Context, minion *api.Node) error { func (r *Registry) UpdateMinion(ctx api.Context, minion *api.Node) error { // TODO: Add some validations. - err := r.SetObj(makeNodeKey(minion.Name), minion) + err := r.SetObj(makeNodeKey(minion.Name), minion, 0 /* ttl */) return etcderr.InterpretUpdateError(err, "minion", minion.Name) } diff --git a/pkg/registry/event/registry.go b/pkg/registry/event/registry.go index 247639158e2..47436046b75 100644 --- a/pkg/registry/event/registry.go +++ b/pkg/registry/event/registry.go @@ -41,6 +41,17 @@ func (r registry) Create(ctx api.Context, id string, obj runtime.Object) error { return etcderr.InterpretCreateError(err, r.Etcd.EndpointName, id) } +// Update replaces an existing instance of the object, and sets a ttl so that the event +// doesn't stay in the system forever. +func (r registry) Update(ctx api.Context, id string, obj runtime.Object) error { + key, err := r.Etcd.KeyFunc(ctx, id) + if err != nil { + return err + } + err = r.Etcd.Helper.SetObj(key, obj, r.ttl) + return etcderr.InterpretUpdateError(err, r.Etcd.EndpointName, id) +} + // NewEtcdRegistry returns a registry which will store Events in the given // EtcdHelper. ttl is the time that Events will be retained by the system. func NewEtcdRegistry(h tools.EtcdHelper, ttl uint64) generic.Registry { diff --git a/pkg/registry/event/registry_test.go b/pkg/registry/event/registry_test.go index d85f23d23d3..3389af8cae6 100644 --- a/pkg/registry/event/registry_test.go +++ b/pkg/registry/event/registry_test.go @@ -108,3 +108,105 @@ func TestEventCreate(t *testing.T) { } } } + +func TestEventUpdate(t *testing.T) { + eventA := &api.Event{ + ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: api.NamespaceDefault}, + Reason: "forTesting", + } + eventB := &api.Event{ + ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: api.NamespaceDefault}, + Reason: "for testing again", + } + eventC := &api.Event{ + ObjectMeta: api.ObjectMeta{Name: "pan", Namespace: api.NamespaceDefault, ResourceVersion: "1"}, + Reason: "for testing again something else", + } + + nodeWithEventA := tools.EtcdResponseWithError{ + R: &etcd.Response{ + Node: &etcd.Node{ + Value: runtime.EncodeOrDie(testapi.Codec(), eventA), + ModifiedIndex: 1, + CreatedIndex: 1, + TTL: int64(testTTL), + }, + }, + E: nil, + } + + nodeWithEventB := tools.EtcdResponseWithError{ + R: &etcd.Response{ + Node: &etcd.Node{ + Value: runtime.EncodeOrDie(testapi.Codec(), eventB), + ModifiedIndex: 1, + CreatedIndex: 1, + TTL: int64(testTTL), + }, + }, + E: nil, + } + + nodeWithEventC := tools.EtcdResponseWithError{ + R: &etcd.Response{ + Node: &etcd.Node{ + Value: runtime.EncodeOrDie(testapi.Codec(), eventC), + ModifiedIndex: 1, + CreatedIndex: 1, + TTL: int64(testTTL), + }, + }, + E: nil, + } + + emptyNode := tools.EtcdResponseWithError{ + R: &etcd.Response{}, + E: tools.EtcdErrorNotFound, + } + + ctx := api.NewDefaultContext() + key := "foo" + path, err := etcdgeneric.NamespaceKeyFunc(ctx, "/registry/events", key) + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + + table := map[string]struct { + existing tools.EtcdResponseWithError + expect tools.EtcdResponseWithError + toUpdate runtime.Object + errOK func(error) bool + }{ + "doesNotExist": { + existing: emptyNode, + expect: nodeWithEventA, + toUpdate: eventA, + errOK: func(err error) bool { return err == nil }, + }, + "doesNotExist2": { + existing: emptyNode, + expect: nodeWithEventB, + toUpdate: eventB, + errOK: func(err error) bool { return err == nil }, + }, + "replaceExisting": { + existing: nodeWithEventA, + expect: nodeWithEventC, + toUpdate: eventC, + errOK: func(err error) bool { return err == nil }, + }, + } + + for name, item := range table { + fakeClient, registry := NewTestEventEtcdRegistry(t) + fakeClient.Data[path] = item.existing + err := registry.Update(ctx, key, item.toUpdate) + if !item.errOK(err) { + t.Errorf("%v: unexpected error: %v", name, err) + } + + if e, a := item.expect, fakeClient.Data[path]; !reflect.DeepEqual(e, a) { + t.Errorf("%v:\n%s", name, util.ObjectGoPrintDiff(e, a)) + } + } +} diff --git a/pkg/registry/event/rest.go b/pkg/registry/event/rest.go index b3651163843..b736c466beb 100644 --- a/pkg/registry/event/rest.go +++ b/pkg/registry/event/rest.go @@ -66,6 +66,31 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE }), nil } +// Update replaces an existing Event instance in storage.registry, with the given instance. +func (rs *REST) Update(ctx api.Context, obj runtime.Object) (<-chan apiserver.RESTResult, error) { + event, ok := obj.(*api.Event) + if !ok { + return nil, fmt.Errorf("not an event object: %#v", obj) + } + if api.Namespace(ctx) != "" { + if !api.ValidNamespace(ctx, &event.ObjectMeta) { + return nil, errors.NewConflict("event", event.Namespace, fmt.Errorf("event.namespace does not match the provided context")) + } + } + if errs := validation.ValidateEvent(event); len(errs) > 0 { + return nil, errors.NewInvalid("event", event.Name, errs) + } + api.FillObjectMetaSystemFields(ctx, &event.ObjectMeta) + + return apiserver.MakeAsync(func() (runtime.Object, error) { + err := rs.registry.Update(ctx, event.Name, event) + if err != nil { + return nil, err + } + return rs.registry.Get(ctx, event.Name) + }), nil +} + func (rs *REST) Delete(ctx api.Context, id string) (<-chan apiserver.RESTResult, error) { obj, err := rs.registry.Get(ctx, id) if err != nil { diff --git a/pkg/registry/event/rest_test.go b/pkg/registry/event/rest_test.go index c2b60b499df..f59feb993ae 100644 --- a/pkg/registry/event/rest_test.go +++ b/pkg/registry/event/rest_test.go @@ -97,6 +97,37 @@ func TestRESTCreate(t *testing.T) { } } +func TestRESTUpdate(t *testing.T) { + _, rest := NewTestREST() + eventA := testEvent("foo") + c, err := rest.Create(api.NewDefaultContext(), eventA) + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + <-c + got, err := rest.Get(api.NewDefaultContext(), eventA.Name) + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + if e, a := eventA, got; !reflect.DeepEqual(e, a) { + t.Errorf("diff: %s", util.ObjectDiff(e, a)) + } + eventB := testEvent("bar") + u, err := rest.Update(api.NewDefaultContext(), eventB) + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + <-u + got2, err := rest.Get(api.NewDefaultContext(), eventB.Name) + if err != nil { + t.Fatalf("Unexpected error %v", err) + } + if e, a := eventB, got2; !reflect.DeepEqual(e, a) { + t.Errorf("diff: %s", util.ObjectDiff(e, a)) + } + +} + func TestRESTDelete(t *testing.T) { _, rest := NewTestREST() eventA := testEvent("foo") diff --git a/pkg/registry/generic/etcd/etcd.go b/pkg/registry/generic/etcd/etcd.go index 8dfda348fc9..f2c02e80f60 100644 --- a/pkg/registry/generic/etcd/etcd.go +++ b/pkg/registry/generic/etcd/etcd.go @@ -103,7 +103,7 @@ func (e *Etcd) Update(ctx api.Context, id string, obj runtime.Object) error { return err } // TODO: verify that SetObj checks ResourceVersion before succeeding. - err = e.Helper.SetObj(key, obj) + err = e.Helper.SetObj(key, obj, 0 /* ttl */) return etcderr.InterpretUpdateError(err, e.EndpointName, id) } diff --git a/pkg/registry/service/rest_test.go b/pkg/registry/service/rest_test.go index 8e0a42def87..8d228844734 100644 --- a/pkg/registry/service/rest_test.go +++ b/pkg/registry/service/rest_test.go @@ -96,7 +96,7 @@ func TestServiceStorageValidatesCreate(t *testing.T) { SessionAffinity: api.AffinityTypeNone, }, }, - "empty selector": { + "empty port": { ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, diff --git a/pkg/service/endpoints_controller.go b/pkg/service/endpoints_controller.go index d205914a3cc..3801972bb22 100644 --- a/pkg/service/endpoints_controller.go +++ b/pkg/service/endpoints_controller.go @@ -30,7 +30,7 @@ import ( "github.com/golang/glog" ) -// EndpointController manages service endpoints. +// EndpointController manages selector-based service endpoints. type EndpointController struct { client *client.Client } @@ -42,7 +42,7 @@ func NewEndpointController(client *client.Client) *EndpointController { } } -// SyncServiceEndpoints syncs service endpoints. +// SyncServiceEndpoints syncs endpoints for services with selectors. func (e *EndpointController) SyncServiceEndpoints() error { services, err := e.client.Services(api.NamespaceAll).List(labels.Everything()) if err != nil { @@ -52,7 +52,8 @@ func (e *EndpointController) SyncServiceEndpoints() error { var resultErr error for _, service := range services.Items { if service.Spec.Selector == nil { - // services without a selector receive no endpoints. The last endpoint will be used. + // services without a selector receive no endpoints from this controller; + // these services will receive the endpoints that are created out-of-band via the REST API. continue } diff --git a/pkg/tools/etcd_tools.go b/pkg/tools/etcd_tools.go index 430f50ae8bb..1e5e8324231 100644 --- a/pkg/tools/etcd_tools.go +++ b/pkg/tools/etcd_tools.go @@ -281,22 +281,22 @@ func (h *EtcdHelper) Delete(key string, recursive bool) error { return err } -// SetObj marshals obj via json, and stores under key. Will do an -// atomic update if obj's ResourceVersion field is set. -func (h *EtcdHelper) SetObj(key string, obj runtime.Object) error { +// SetObj marshals obj via json, and stores under key. Will do an atomic update if obj's ResourceVersion +// field is set. 'ttl' is time-to-live in seconds, and 0 means forever. +func (h *EtcdHelper) SetObj(key string, obj runtime.Object, ttl uint64) error { data, err := h.Codec.Encode(obj) if err != nil { return err } if h.ResourceVersioner != nil { if version, err := h.ResourceVersioner.ResourceVersion(obj); err == nil && version != 0 { - _, err = h.Client.CompareAndSwap(key, string(data), 0, "", version) + _, err = h.Client.CompareAndSwap(key, string(data), ttl, "", version) return err // err is shadowed! } } // Create will fail if a key already exists. - _, err = h.Client.Create(key, string(data), 0) + _, err = h.Client.Create(key, string(data), ttl) return err } diff --git a/pkg/tools/etcd_tools_test.go b/pkg/tools/etcd_tools_test.go index 0961aa60bf0..fadcd062024 100644 --- a/pkg/tools/etcd_tools_test.go +++ b/pkg/tools/etcd_tools_test.go @@ -375,7 +375,7 @@ func TestSetObj(t *testing.T) { obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} fakeClient := NewFakeEtcdClient(t) helper := EtcdHelper{fakeClient, testapi.Codec(), versioner} - err := helper.SetObj("/some/key", obj) + err := helper.SetObj("/some/key", obj, 5) if err != nil { t.Errorf("Unexpected error %#v", err) } @@ -388,6 +388,10 @@ func TestSetObj(t *testing.T) { if expect != got { t.Errorf("Wanted %v, got %v", expect, got) } + if e, a := uint64(5), fakeClient.LastSetTTL; e != a { + t.Errorf("Wanted %v, got %v", e, a) + } + } func TestSetObjWithVersion(t *testing.T) { @@ -404,7 +408,7 @@ func TestSetObjWithVersion(t *testing.T) { } helper := EtcdHelper{fakeClient, testapi.Codec(), versioner} - err := helper.SetObj("/some/key", obj) + err := helper.SetObj("/some/key", obj, 7) if err != nil { t.Fatalf("Unexpected error %#v", err) } @@ -417,13 +421,16 @@ func TestSetObjWithVersion(t *testing.T) { if expect != got { t.Errorf("Wanted %v, got %v", expect, got) } + if e, a := uint64(7), fakeClient.LastSetTTL; e != a { + t.Errorf("Wanted %v, got %v", e, a) + } } func TestSetObjWithoutResourceVersioner(t *testing.T) { obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} fakeClient := NewFakeEtcdClient(t) helper := EtcdHelper{fakeClient, testapi.Codec(), nil} - err := helper.SetObj("/some/key", obj) + err := helper.SetObj("/some/key", obj, 3) if err != nil { t.Errorf("Unexpected error %#v", err) } @@ -436,6 +443,9 @@ func TestSetObjWithoutResourceVersioner(t *testing.T) { if expect != got { t.Errorf("Wanted %v, got %v", expect, got) } + if e, a := uint64(3), fakeClient.LastSetTTL; e != a { + t.Errorf("Wanted %v, got %v", e, a) + } } func TestAtomicUpdate(t *testing.T) { diff --git a/pkg/tools/fake_etcd_client.go b/pkg/tools/fake_etcd_client.go index 5250187cc97..fade54a45b7 100644 --- a/pkg/tools/fake_etcd_client.go +++ b/pkg/tools/fake_etcd_client.go @@ -173,6 +173,7 @@ func (f *FakeEtcdClient) setLocked(key, value string, ttl uint64) (*etcd.Respons Value: value, CreatedIndex: createdIndex, ModifiedIndex: i, + TTL: int64(ttl), }, }, } diff --git a/pkg/util/node.go b/pkg/util/node.go index e427394b166..4db7ae99772 100644 --- a/pkg/util/node.go +++ b/pkg/util/node.go @@ -17,11 +17,9 @@ limitations under the License. package util import ( - "os" "os/exec" "strings" - "github.com/fsouza/go-dockerclient" "github.com/golang/glog" ) @@ -38,26 +36,3 @@ func GetHostname(hostnameOverride string) string { } return strings.TrimSpace(string(hostname)) } - -// Get a docker endpoint, either from the string passed in, or $DOCKER_HOST environment variables -func GetDockerEndpoint(dockerEndpoint string) string { - var endpoint string - if len(dockerEndpoint) > 0 { - endpoint = dockerEndpoint - } else if len(os.Getenv("DOCKER_HOST")) > 0 { - endpoint = os.Getenv("DOCKER_HOST") - } else { - endpoint = "unix:///var/run/docker.sock" - } - glog.Infof("Connecting to docker on %s", endpoint) - - return endpoint -} - -func ConnectToDockerOrDie(dockerEndpoint string) *docker.Client { - client, err := docker.NewClient(GetDockerEndpoint(dockerEndpoint)) - if err != nil { - glog.Fatal("Couldn't connect to docker.") - } - return client -} diff --git a/test/e2e/cluster_dns.go b/test/e2e/cluster_dns.go deleted file mode 100644 index b64da904e7b..00000000000 --- a/test/e2e/cluster_dns.go +++ /dev/null @@ -1,154 +0,0 @@ -/* -Copyright 2014 Google Inc. All rights reserved. - -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. -*/ - -package e2e - -import ( - "fmt" - "time" - - "github.com/GoogleCloudPlatform/kubernetes/pkg/api" - "github.com/GoogleCloudPlatform/kubernetes/pkg/client" - "github.com/GoogleCloudPlatform/kubernetes/pkg/util" - "github.com/golang/glog" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -// TestClusterDNS checks that cluster DNS works. -func TestClusterDNS(c *client.Client) bool { - if testContext.provider == "vagrant" { - glog.Infof("Skipping test which is broken for vagrant (See https://github.com/GoogleCloudPlatform/kubernetes/issues/3580)") - return true - } - - podClient := c.Pods(api.NamespaceDefault) - - //TODO: Wait for skyDNS - - // All the names we need to be able to resolve. - namesToResolve := []string{ - "kubernetes-ro", - "kubernetes-ro.default", - "kubernetes-ro.default.kubernetes.local", - "google.com", - } - - probeCmd := "for i in `seq 1 600`; do " - for _, name := range namesToResolve { - probeCmd += fmt.Sprintf("wget -O /dev/null %s && echo OK > /results/%s;", name, name) - } - probeCmd += "sleep 1; done" - - // Run a pod which probes DNS and exposes the results by HTTP. - pod := &api.Pod{ - TypeMeta: api.TypeMeta{ - Kind: "Pod", - APIVersion: "v1beta1", - }, - ObjectMeta: api.ObjectMeta{ - Name: "dns-test-" + string(util.NewUUID()), - }, - Spec: api.PodSpec{ - Volumes: []api.Volume{ - { - Name: "results", - Source: api.VolumeSource{ - EmptyDir: &api.EmptyDir{}, - }, - }, - }, - Containers: []api.Container{ - { - Name: "webserver", - Image: "kubernetes/test-webserver", - VolumeMounts: []api.VolumeMount{ - { - Name: "results", - MountPath: "/results", - }, - }, - }, - { - Name: "pinger", - Image: "busybox", - Command: []string{"sh", "-c", probeCmd}, - VolumeMounts: []api.VolumeMount{ - { - Name: "results", - MountPath: "/results", - }, - }, - }, - }, - }, - } - _, err := podClient.Create(pod) - if err != nil { - glog.Errorf("Failed to create %s pod: %v", pod.Name, err) - return false - } - defer podClient.Delete(pod.Name) - - waitForPodRunning(c, pod.Name) - pod, err = podClient.Get(pod.Name) - if err != nil { - glog.Errorf("Failed to get pod %s: %v", pod.Name, err) - return false - } - - // Try to find results for each expected name. - var failed []string - for try := 1; try < 100; try++ { - failed = []string{} - for _, name := range namesToResolve { - _, err := c.Get(). - Prefix("proxy"). - Resource("pods"). - Namespace("default"). - Name(pod.Name). - Suffix("results", name). - Do().Raw() - if err != nil { - failed = append(failed, name) - glog.V(4).Infof("Lookup using %s for %s failed: %v", pod.Name, name, err) - } - } - if len(failed) == 0 { - break - } - glog.Infof("lookups using %s failed for: %v", pod.Name, failed) - time.Sleep(10 * time.Second) - } - if len(failed) != 0 { - glog.Errorf("DNS using %s failed for: %v", pod.Name, failed) - return false - } - - // TODO: probe from the host, too. - - glog.Infof("DNS probes using %s succeeded", pod.Name) - return true -} - -var _ = Describe("TestClusterDNS", func() { - It("should pass", func() { - // TODO: Instead of OrDie, client should Fail the test if there's a problem. - // In general tests should Fail() instead of glog.Fatalf(). - Expect(TestClusterDNS(loadClientOrDie())).To(BeTrue()) - }) -}) diff --git a/test/e2e/driver.go b/test/e2e/driver.go index 7f2664f2ebb..95c4b84e0f8 100644 --- a/test/e2e/driver.go +++ b/test/e2e/driver.go @@ -20,7 +20,6 @@ import ( "path" "regexp" "strings" - "time" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/golang/glog" @@ -48,17 +47,6 @@ func RunE2ETests(authConfig, certDir, host, repoRoot, provider string, orderseed util.InitLogs() defer util.FlushLogs() - // TODO: Associate a timeout with each test individually. - go func() { - defer util.FlushLogs() - // TODO: We should modify testSpec to include an estimated running time - // for each test and use that information to estimate a timeout - // value. Until then, as we add more tests (and before we move to - // parallel testing) we need to adjust this value as we add more tests. - time.Sleep(40 * time.Minute) - glog.Fatalf("This test has timed out. Cleanup not guaranteed.") - }() - if len(testList) != 0 { if config.GinkgoConfig.FocusString != "" || config.GinkgoConfig.SkipString != "" { glog.Fatal("Either specify --test/-t or --ginkgo.focus/--ginkgo.skip but not both.") diff --git a/test/e2e/endpoints.go b/test/e2e/endpoints.go new file mode 100644 index 00000000000..19c220077b3 --- /dev/null +++ b/test/e2e/endpoints.go @@ -0,0 +1,196 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +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. +*/ + +package e2e + +import ( + "net" + "time" + + "github.com/GoogleCloudPlatform/kubernetes/pkg/api" + "github.com/GoogleCloudPlatform/kubernetes/pkg/client" + "github.com/GoogleCloudPlatform/kubernetes/pkg/util" + "github.com/golang/glog" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +func validateIPs(c *client.Client, ns, expectedPort string, expectedEndpoints []string, endpoints *api.Endpoints) bool { + ips := util.StringSet{} + for _, spec := range endpoints.Endpoints { + host, port, err := net.SplitHostPort(spec) + if err != nil { + glog.Warningf("invalid endpoint spec: %s", spec) + return false + } + if port != expectedPort { + glog.Warningf("invalid port, expected %s, got %s", expectedPort, port) + return false + } + ips.Insert(host) + } + + for _, name := range expectedEndpoints { + pod, err := c.Pods(ns).Get(name) + if err != nil { + glog.Warningf("failed to get pod %s, that's pretty weird. validation failed.", name) + return false + } + if !ips.Has(pod.Status.PodIP) { + glog.Warningf("ip validation failed, expected: %v, saw: %v", ips, pod.Status.PodIP) + return false + } + } + return true +} + +func validateEndpoints(c *client.Client, ns, serviceName, expectedPort string, expectedEndpoints []string) bool { + done := make(chan bool) + running := true + go func() { + ok := true + for running { + endpoints, err := c.Endpoints(ns).Get(serviceName) + if err == nil { + if len(endpoints.Endpoints) != len(expectedEndpoints) { + glog.Warningf("Unexpected endpoints: %#v, expected %v", endpoints, expectedEndpoints) + } else if validateIPs(c, ns, expectedPort, expectedEndpoints, endpoints) { + break + } + } else { + glog.Warningf("Failed to get endpoints: %v", err) + } + time.Sleep(time.Second) + } + done <- ok + }() + + select { + case result := <-done: + return result + case <-time.After(60 * time.Second): + glog.Errorf("Timed out waiting for endpoints.") + running = false + return false + } +} + +func addPod(c *client.Client, ns, name string, labels map[string]string) error { + pod := &api.Pod{ + ObjectMeta: api.ObjectMeta{ + Name: name, + Labels: labels, + }, + Spec: api.PodSpec{ + Containers: []api.Container{ + { + Name: "test", + Image: "kubernetes/pause", + Ports: []api.Port{{ContainerPort: 80}}, + }, + }, + }, + } + _, err := c.Pods(ns).Create(pod) + return err +} + +func TestEndpoints(c *client.Client) bool { + serviceName := "endpoint-test" + ns := api.NamespaceDefault + labels := map[string]string{ + "foo": "bar", + "baz": "blah", + } + + defer func() { + err := c.Services(ns).Delete(serviceName) + if err != nil { + glog.Errorf("Failed to delete service: %v (%v)", serviceName, err) + } + }() + + service := &api.Service{ + ObjectMeta: api.ObjectMeta{ + Name: serviceName, + }, + Spec: api.ServiceSpec{ + Port: 80, + Selector: labels, + ContainerPort: util.NewIntOrStringFromInt(80), + }, + } + if _, err := c.Services(ns).Create(service); err != nil { + glog.Errorf("Failed to create endpoint test service: %v", err) + return false + } + expectedPort := "80" + + if !validateEndpoints(c, ns, serviceName, expectedPort, []string{}) { + return false + } + + name1 := "test1" + if err := addPod(c, ns, name1, labels); err != nil { + glog.Errorf("Failed to create pod: %v", err) + return false + } + names := []string{name1} + defer func() { + for _, name := range names { + err := c.Pods(ns).Delete(name) + if err != nil { + glog.Errorf("Failed to delete pod: %v (%v)", name, err) + } + } + }() + + if !validateEndpoints(c, ns, serviceName, expectedPort, names) { + return false + } + + name2 := "test2" + if err := addPod(c, ns, name2, labels); err != nil { + glog.Errorf("Failed to create pod: %v", err) + return false + } + names = append(names, name2) + + if !validateEndpoints(c, ns, serviceName, expectedPort, names) { + return false + } + + if err := c.Pods(ns).Delete(name1); err != nil { + glog.Errorf("Failed to delete pod: %s", name1) + return false + } + names = []string{name2} + + if !validateEndpoints(c, ns, serviceName, expectedPort, names) { + return false + } + + return true +} + +var _ = Describe("TestEndpoints", func() { + It("should pass", func() { + // TODO: Instead of OrDie, client should Fail the test if there's a problem. + // In general tests should Fail() instead of glog.Fatalf(). + Expect(TestEndpoints(loadClientOrDie())).To(BeTrue()) + }) +}) diff --git a/test/e2e/roservice.go b/test/e2e/roservice.go deleted file mode 100644 index a631fbcdb9c..00000000000 --- a/test/e2e/roservice.go +++ /dev/null @@ -1,66 +0,0 @@ -/* -Copyright 2014 Google Inc. All rights reserved. - -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. -*/ - -package e2e - -import ( - "github.com/GoogleCloudPlatform/kubernetes/pkg/api" - "github.com/GoogleCloudPlatform/kubernetes/pkg/client" - "github.com/golang/glog" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -func TestKubernetesROService(c *client.Client) bool { - svc := api.ServiceList{} - err := c.Get(). - Namespace("default"). - AbsPath("/api/v1beta1/proxy/services/kubernetes-ro/api/v1beta1/services"). - Do(). - Into(&svc) - if err != nil { - glog.Errorf("unexpected error listing services using ro service: %v", err) - return false - } - var foundRW, foundRO bool - for i := range svc.Items { - if svc.Items[i].Name == "kubernetes" { - foundRW = true - } - if svc.Items[i].Name == "kubernetes-ro" { - foundRO = true - } - } - if !foundRW { - glog.Error("no RW service found") - } - if !foundRO { - glog.Error("no RO service found") - } - if !foundRW || !foundRO { - return false - } - return true -} - -var _ = Describe("TestKubernetesROService", func() { - It("should pass", func() { - // TODO: Instead of OrDie, client should Fail the test if there's a problem. - // In general tests should Fail() instead of glog.Fatalf(). - Expect(TestKubernetesROService(loadClientOrDie())).To(BeTrue()) - }) -}) diff --git a/test/e2e/service.go b/test/e2e/service.go new file mode 100644 index 00000000000..c993e86dc43 --- /dev/null +++ b/test/e2e/service.go @@ -0,0 +1,180 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +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. +*/ + +package e2e + +import ( + "fmt" + "time" + + "github.com/GoogleCloudPlatform/kubernetes/pkg/api" + "github.com/GoogleCloudPlatform/kubernetes/pkg/client" + "github.com/GoogleCloudPlatform/kubernetes/pkg/util" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Services", func() { + var c *client.Client + + BeforeEach(func() { + c = loadClientOrDie() + }) + + It("should provide DNS for the cluster", func() { + if testContext.provider == "vagrant" { + By("Skipping test which is broken for vagrant (See https://github.com/GoogleCloudPlatform/kubernetes/issues/3580)") + return + } + + podClient := c.Pods(api.NamespaceDefault) + + //TODO: Wait for skyDNS + + // All the names we need to be able to resolve. + namesToResolve := []string{ + "kubernetes-ro", + "kubernetes-ro.default", + "kubernetes-ro.default.kubernetes.local", + "google.com", + } + + probeCmd := "for i in `seq 1 600`; do " + for _, name := range namesToResolve { + probeCmd += fmt.Sprintf("wget -O /dev/null %s && echo OK > /results/%s;", name, name) + } + probeCmd += "sleep 1; done" + + // Run a pod which probes DNS and exposes the results by HTTP. + By("creating a pod to probe DNS") + pod := &api.Pod{ + TypeMeta: api.TypeMeta{ + Kind: "Pod", + APIVersion: "v1beta1", + }, + ObjectMeta: api.ObjectMeta{ + Name: "dns-test-" + string(util.NewUUID()), + }, + Spec: api.PodSpec{ + Volumes: []api.Volume{ + { + Name: "results", + Source: api.VolumeSource{ + EmptyDir: &api.EmptyDir{}, + }, + }, + }, + Containers: []api.Container{ + { + Name: "webserver", + Image: "kubernetes/test-webserver", + VolumeMounts: []api.VolumeMount{ + { + Name: "results", + MountPath: "/results", + }, + }, + }, + { + Name: "pinger", + Image: "busybox", + Command: []string{"sh", "-c", probeCmd}, + VolumeMounts: []api.VolumeMount{ + { + Name: "results", + MountPath: "/results", + }, + }, + }, + }, + }, + } + + By("submitting the pod to kuberenetes") + _, err := podClient.Create(pod) + if err != nil { + Fail(fmt.Sprintf("Failed to create %s pod: %v", pod.Name, err)) + } + defer func() { + By("deleting the pod") + defer GinkgoRecover() + podClient.Delete(pod.Name) + }() + + By("waiting for the pod to start running") + waitForPodRunning(c, pod.Name) + + By("retrieving the pod") + pod, err = podClient.Get(pod.Name) + if err != nil { + Fail(fmt.Sprintf("Failed to get pod %s: %v", pod.Name, err)) + } + + // Try to find results for each expected name. + By("looking for the results for each expected name") + var failed []string + for try := 1; try < 100; try++ { + failed = []string{} + for _, name := range namesToResolve { + _, err := c.Get(). + Prefix("proxy"). + Resource("pods"). + Namespace("default"). + Name(pod.Name). + Suffix("results", name). + Do().Raw() + if err != nil { + failed = append(failed, name) + fmt.Printf("Lookup using %s for %s failed: %v\n", pod.Name, name, err) + } + } + if len(failed) == 0 { + break + } + fmt.Printf("lookups using %s failed for: %v\n", pod.Name, failed) + time.Sleep(10 * time.Second) + } + Expect(len(failed)).To(Equal(0)) + + // TODO: probe from the host, too. + + fmt.Printf("DNS probes using %s succeeded\n", pod.Name) + }) + + It("should provide RW and RO services", func() { + svc := api.ServiceList{} + err := c.Get(). + Namespace("default"). + AbsPath("/api/v1beta1/proxy/services/kubernetes-ro/api/v1beta1/services"). + Do(). + Into(&svc) + if err != nil { + Fail(fmt.Sprintf("unexpected error listing services using ro service: %v", err)) + } + var foundRW, foundRO bool + for i := range svc.Items { + if svc.Items[i].Name == "kubernetes" { + foundRW = true + } + if svc.Items[i].Name == "kubernetes-ro" { + foundRO = true + } + } + Expect(foundRW).To(Equal(true)) + Expect(foundRO).To(Equal(true)) + }) +}) diff --git a/test/e2e/shell.go b/test/e2e/shell.go new file mode 100644 index 00000000000..a91dad1faa3 --- /dev/null +++ b/test/e2e/shell.go @@ -0,0 +1,71 @@ +/* +Copyright 2015 Google Inc. All rights reserved. + +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. +*/ + +package e2e + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "os/exec" + "path" + "path/filepath" + + . "github.com/onsi/ginkgo" +) + +var ( + root = absOrDie(filepath.Clean(filepath.Join(path.Base(os.Args[0]), ".."))) +) + +var _ = Describe("Shell", func() { + // Slurp up all the tests in hack/e2e-suite + bashE2ERoot := filepath.Join(root, "hack/e2e-suite") + files, err := ioutil.ReadDir(bashE2ERoot) + if err != nil { + Fail(err.Error()) + } + + for _, file := range files { + fileName := file.Name() // Make a copy + It(fmt.Sprintf("tests that %v passes", fileName), func() { + runCmdTest(filepath.Join(bashE2ERoot, fileName)) + }) + } +}) + +func absOrDie(path string) string { + out, err := filepath.Abs(path) + if err != nil { + panic(err) + } + return out +} + +// Runs the given cmd test. +func runCmdTest(path string) { + By(fmt.Sprintf("Running %v", path)) + cmd := exec.Command(path) + cmd.Stdout = bytes.NewBuffer(nil) + cmd.Stderr = cmd.Stdout + + if err := cmd.Run(); err != nil { + Fail(fmt.Sprintf("Error running %v:\nCommand output:\n%v\n", cmd, cmd.Stdout)) + return + } + return +} diff --git a/test/integration/auth_test.go b/test/integration/auth_test.go index d4fde99808b..397c2c4b020 100644 --- a/test/integration/auth_test.go +++ b/test/integration/auth_test.go @@ -24,12 +24,14 @@ package integration import ( "bytes" + "encoding/json" "errors" "fmt" "io/ioutil" "net/http" "net/http/httptest" "os" + "strings" "testing" "github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" @@ -73,7 +75,7 @@ var aPod string = ` "id": "a", "containers": [{ "name": "foo", "image": "bar/foo", }] } - }, + }%s } ` var aRC string = ` @@ -97,7 +99,7 @@ var aRC string = ` }, "labels": {"name": "a"} }}, - "labels": {"name": "a"} + "labels": {"name": "a"}%s } ` var aService string = ` @@ -108,7 +110,7 @@ var aService string = ` "port": 8000, "portalIP": "10.0.0.100", "labels": { "name": "a" }, - "selector": { "name": "a" } + "selector": { "name": "a" }%s } ` var aMinion string = ` @@ -116,7 +118,7 @@ var aMinion string = ` "kind": "Minion", "apiVersion": "v1beta1", "id": "a", - "hostIP": "10.10.10.10", + "hostIP": "10.10.10.10"%s } ` @@ -131,7 +133,7 @@ var aEvent string = ` "name": "a", "namespace": "default", "apiVersion": "v1beta1", - } + }%s } ` @@ -141,7 +143,7 @@ var aBinding string = ` "apiVersion": "v1beta1", "id": "a", "host": "10.10.10.10", - "podID": "a" + "podID": "a"%s } ` @@ -150,7 +152,7 @@ var aEndpoints string = ` "kind": "Endpoints", "apiVersion": "v1beta1", "id": "a", - "endpoints": ["10.10.1.1:1909"], + "endpoints": ["10.10.1.1:1909"]%s } ` @@ -183,7 +185,7 @@ func getTestRequests() []struct { // Normal methods on pods {"GET", "/api/v1beta1/pods", "", code200}, {"POST", "/api/v1beta1/pods" + timeoutFlag, aPod, code200}, - {"PUT", "/api/v1beta1/pods/a" + timeoutFlag, aPod, code500}, // See #2114 about why 500 + {"PUT", "/api/v1beta1/pods/a" + timeoutFlag, aPod, code200}, {"GET", "/api/v1beta1/pods", "", code200}, {"GET", "/api/v1beta1/pods/a", "", code200}, {"DELETE", "/api/v1beta1/pods/a" + timeoutFlag, "", code200}, @@ -203,7 +205,7 @@ func getTestRequests() []struct { // Normal methods on services {"GET", "/api/v1beta1/services", "", code200}, {"POST", "/api/v1beta1/services" + timeoutFlag, aService, code200}, - {"PUT", "/api/v1beta1/services/a" + timeoutFlag, aService, code409}, // See #2115 about why 409 + {"PUT", "/api/v1beta1/services/a" + timeoutFlag, aService, code200}, {"GET", "/api/v1beta1/services", "", code200}, {"GET", "/api/v1beta1/services/a", "", code200}, {"DELETE", "/api/v1beta1/services/a" + timeoutFlag, "", code200}, @@ -211,7 +213,7 @@ func getTestRequests() []struct { // Normal methods on replicationControllers {"GET", "/api/v1beta1/replicationControllers", "", code200}, {"POST", "/api/v1beta1/replicationControllers" + timeoutFlag, aRC, code200}, - {"PUT", "/api/v1beta1/replicationControllers/a" + timeoutFlag, aRC, code409}, // See #2115 about why 409 + {"PUT", "/api/v1beta1/replicationControllers/a" + timeoutFlag, aRC, code200}, {"GET", "/api/v1beta1/replicationControllers", "", code200}, {"GET", "/api/v1beta1/replicationControllers/a", "", code200}, {"DELETE", "/api/v1beta1/replicationControllers/a" + timeoutFlag, "", code200}, @@ -235,7 +237,7 @@ func getTestRequests() []struct { // Normal methods on events {"GET", "/api/v1beta1/events", "", code200}, {"POST", "/api/v1beta1/events" + timeoutFlag, aEvent, code200}, - {"PUT", "/api/v1beta1/events/a" + timeoutFlag, aEvent, code405}, + {"PUT", "/api/v1beta1/events/a" + timeoutFlag, aEvent, code200}, {"GET", "/api/v1beta1/events", "", code200}, {"GET", "/api/v1beta1/events", "", code200}, {"GET", "/api/v1beta1/events/a", "", code200}, @@ -308,10 +310,22 @@ func TestAuthModeAlwaysAllow(t *testing.T) { }) transport := http.DefaultTransport + previousResourceVersion := make(map[string]float64) for _, r := range getTestRequests() { t.Logf("case %v", r) - bodyBytes := bytes.NewReader([]byte(r.body)) + var bodyStr string + if r.body != "" { + bodyStr = fmt.Sprintf(r.body, "") + if r.verb == "PUT" && r.body != "" { + // For update operations, insert previous resource version + if resVersion := previousResourceVersion[getPreviousResourceVersionKey(r.URL, "")]; resVersion != 0 { + resourceVersionJson := fmt.Sprintf(",\r\n\"resourceVersion\": %v", resVersion) + bodyStr = fmt.Sprintf(r.body, resourceVersionJson) + } + } + } + bodyBytes := bytes.NewReader([]byte(bodyStr)) req, err := http.NewRequest(r.verb, s.URL+r.URL, bodyBytes) if err != nil { t.Fatalf("unexpected error: %v", err) @@ -322,15 +336,50 @@ func TestAuthModeAlwaysAllow(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } + b, _ := ioutil.ReadAll(resp.Body) if _, ok := r.statusCodes[resp.StatusCode]; !ok { t.Errorf("Expected status one of %v, but got %v", r.statusCodes, resp.StatusCode) - b, _ := ioutil.ReadAll(resp.Body) t.Errorf("Body: %v", string(b)) + } else { + if r.verb == "POST" { + // For successful create operations, extract resourceVersion + id, currentResourceVersion, err := parseResourceVersion(b) + if err == nil { + key := getPreviousResourceVersionKey(r.URL, id) + previousResourceVersion[key] = currentResourceVersion + } + } } }() } } +func parseResourceVersion(response []byte) (string, float64, error) { + var resultBodyMap map[string]interface{} + err := json.Unmarshal(response, &resultBodyMap) + if err != nil { + return "", 0, fmt.Errorf("unexpected error unmarshaling resultBody: %v", err) + } + id, ok := resultBodyMap["id"].(string) + if !ok { + return "", 0, fmt.Errorf("unexpected error, id not found in JSON response: %v", string(response)) + } + resourceVersion, ok := resultBodyMap["resourceVersion"].(float64) + if !ok { + return "", 0, fmt.Errorf("unexpected error, resourceVersion not found in JSON response: %v", string(response)) + } + return id, resourceVersion, nil +} + +func getPreviousResourceVersionKey(url, id string) string { + baseUrl := strings.Split(url, "?")[0] + key := baseUrl + if id != "" { + key = fmt.Sprintf("%s/%v", baseUrl, id) + } + return key +} + func TestAuthModeAlwaysDeny(t *testing.T) { deleteAllEtcdKeys() @@ -426,12 +475,24 @@ func TestAliceNotForbiddenOrUnauthorized(t *testing.T) { AdmissionControl: admit.NewAlwaysAdmit(), }) + previousResourceVersion := make(map[string]float64) transport := http.DefaultTransport for _, r := range getTestRequests() { token := AliceToken t.Logf("case %v", r) - bodyBytes := bytes.NewReader([]byte(r.body)) + var bodyStr string + if r.body != "" { + bodyStr = fmt.Sprintf(r.body, "") + if r.verb == "PUT" && r.body != "" { + // For update operations, insert previous resource version + if resVersion := previousResourceVersion[getPreviousResourceVersionKey(r.URL, "")]; resVersion != 0 { + resourceVersionJson := fmt.Sprintf(",\r\n\"resourceVersion\": %v", resVersion) + bodyStr = fmt.Sprintf(r.body, resourceVersionJson) + } + } + } + bodyBytes := bytes.NewReader([]byte(bodyStr)) req, err := http.NewRequest(r.verb, s.URL+r.URL, bodyBytes) if err != nil { t.Fatalf("unexpected error: %v", err) @@ -444,11 +505,21 @@ func TestAliceNotForbiddenOrUnauthorized(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } + b, _ := ioutil.ReadAll(resp.Body) if _, ok := r.statusCodes[resp.StatusCode]; !ok { t.Errorf("Expected status one of %v, but got %v", r.statusCodes, resp.StatusCode) - b, _ := ioutil.ReadAll(resp.Body) t.Errorf("Body: %v", string(b)) + } else { + if r.verb == "POST" { + // For successful create operations, extract resourceVersion + id, currentResourceVersion, err := parseResourceVersion(b) + if err == nil { + key := getPreviousResourceVersionKey(r.URL, id) + previousResourceVersion[key] = currentResourceVersion + } + } } + }() } } @@ -628,6 +699,7 @@ func TestNamespaceAuthorization(t *testing.T) { AdmissionControl: admit.NewAlwaysAdmit(), }) + previousResourceVersion := make(map[string]float64) transport := http.DefaultTransport requests := []struct { @@ -656,7 +728,18 @@ func TestNamespaceAuthorization(t *testing.T) { for _, r := range requests { token := BobToken t.Logf("case %v", r) - bodyBytes := bytes.NewReader([]byte(r.body)) + var bodyStr string + if r.body != "" { + bodyStr = fmt.Sprintf(r.body, "") + if r.verb == "PUT" && r.body != "" { + // For update operations, insert previous resource version + if resVersion := previousResourceVersion[getPreviousResourceVersionKey(r.URL, "")]; resVersion != 0 { + resourceVersionJson := fmt.Sprintf(",\r\n\"resourceVersion\": %v", resVersion) + bodyStr = fmt.Sprintf(r.body, resourceVersionJson) + } + } + } + bodyBytes := bytes.NewReader([]byte(bodyStr)) req, err := http.NewRequest(r.verb, s.URL+r.URL, bodyBytes) if err != nil { t.Fatalf("unexpected error: %v", err) @@ -668,11 +751,21 @@ func TestNamespaceAuthorization(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } + b, _ := ioutil.ReadAll(resp.Body) if _, ok := r.statusCodes[resp.StatusCode]; !ok { t.Errorf("Expected status one of %v, but got %v", r.statusCodes, resp.StatusCode) - b, _ := ioutil.ReadAll(resp.Body) t.Errorf("Body: %v", string(b)) + } else { + if r.verb == "POST" { + // For successful create operations, extract resourceVersion + id, currentResourceVersion, err := parseResourceVersion(b) + if err == nil { + key := getPreviousResourceVersionKey(r.URL, id) + previousResourceVersion[key] = currentResourceVersion + } + } } + }() } } @@ -713,6 +806,7 @@ func TestKindAuthorization(t *testing.T) { AdmissionControl: admit.NewAlwaysAdmit(), }) + previousResourceVersion := make(map[string]float64) transport := http.DefaultTransport requests := []struct { @@ -735,7 +829,18 @@ func TestKindAuthorization(t *testing.T) { for _, r := range requests { token := BobToken t.Logf("case %v", r) - bodyBytes := bytes.NewReader([]byte(r.body)) + var bodyStr string + if r.body != "" { + bodyStr = fmt.Sprintf(r.body, "") + if r.verb == "PUT" && r.body != "" { + // For update operations, insert previous resource version + if resVersion := previousResourceVersion[getPreviousResourceVersionKey(r.URL, "")]; resVersion != 0 { + resourceVersionJson := fmt.Sprintf(",\r\n\"resourceVersion\": %v", resVersion) + bodyStr = fmt.Sprintf(r.body, resourceVersionJson) + } + } + } + bodyBytes := bytes.NewReader([]byte(bodyStr)) req, err := http.NewRequest(r.verb, s.URL+r.URL, bodyBytes) if err != nil { t.Fatalf("unexpected error: %v", err) @@ -747,11 +852,21 @@ func TestKindAuthorization(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } + b, _ := ioutil.ReadAll(resp.Body) if _, ok := r.statusCodes[resp.StatusCode]; !ok { t.Errorf("Expected status one of %v, but got %v", r.statusCodes, resp.StatusCode) - b, _ := ioutil.ReadAll(resp.Body) t.Errorf("Body: %v", string(b)) + } else { + if r.verb == "POST" { + // For successful create operations, extract resourceVersion + id, currentResourceVersion, err := parseResourceVersion(b) + if err == nil { + key := getPreviousResourceVersionKey(r.URL, id) + previousResourceVersion[key] = currentResourceVersion + } + } } + } } } diff --git a/test/integration/etcd_tools_test.go b/test/integration/etcd_tools_test.go index 0a621fe092f..66c009cc6b3 100644 --- a/test/integration/etcd_tools_test.go +++ b/test/integration/etcd_tools_test.go @@ -60,7 +60,7 @@ func TestSetObj(t *testing.T) { helper := tools.EtcdHelper{Client: client, Codec: stringCodec{}} withEtcdKey(func(key string) { fakeObject := fakeAPIObject("object") - if err := helper.SetObj(key, &fakeObject); err != nil { + if err := helper.SetObj(key, &fakeObject, 0 /* ttl */); err != nil { t.Fatalf("unexpected error: %v", err) } resp, err := client.Get(key, false, false)