mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-03 09:22:44 +00:00
Merge pull request #5012 from smarterclayton/podtemplates
Pod templates as their own type
This commit is contained in:
commit
97302af015
@ -4742,21 +4742,40 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/api/v1beta1/pods/{name}/exec",
|
||||||
|
"description": "API at /api/v1beta1 version v1beta1",
|
||||||
|
"operations": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "GET",
|
||||||
|
"summary": "connect GET requests to Pod",
|
||||||
|
"nickname": "connectGETPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/api/v1beta1/pods/{name}/log",
|
"path": "/api/v1beta1/pods/{name}/log",
|
||||||
"description": "API at /api/v1beta1 version v1beta1",
|
"description": "API at /api/v1beta1 version v1beta1",
|
||||||
"operations": [
|
"operations": [
|
||||||
{
|
{
|
||||||
"type": "v1beta1.PodLogOptions",
|
"type": "v1beta1.Pod",
|
||||||
"method": "GET",
|
"method": "GET",
|
||||||
"summary": "read the specified PodLogOptions",
|
"summary": "read the specified Pod",
|
||||||
"nickname": "readPodLogOptions",
|
"nickname": "readPod",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"paramType": "path",
|
"paramType": "path",
|
||||||
"name": "name",
|
"name": "name",
|
||||||
"description": "name of the PodLogOptions",
|
"description": "name of the Pod",
|
||||||
"required": true,
|
"required": true,
|
||||||
"allowMultiple": false
|
"allowMultiple": false
|
||||||
},
|
},
|
||||||
@ -4773,7 +4792,7 @@
|
|||||||
{
|
{
|
||||||
"code": 200,
|
"code": 200,
|
||||||
"message": "OK",
|
"message": "OK",
|
||||||
"responseModel": "v1beta1.PodLogOptions"
|
"responseModel": "v1beta1.Pod"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@ -4785,6 +4804,193 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/api/v1beta1/pods/{name}/portforward",
|
||||||
|
"description": "API at /api/v1beta1 version v1beta1",
|
||||||
|
"operations": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "GET",
|
||||||
|
"summary": "connect GET requests to Pod",
|
||||||
|
"nickname": "connectGETPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/api/v1beta1/pods/{name}/proxy",
|
||||||
|
"description": "API at /api/v1beta1 version v1beta1",
|
||||||
|
"operations": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "GET",
|
||||||
|
"summary": "connect GET requests to Pod",
|
||||||
|
"nickname": "connectGETPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "POST",
|
||||||
|
"summary": "connect POST requests to Pod",
|
||||||
|
"nickname": "connectPOSTPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "PUT",
|
||||||
|
"summary": "connect PUT requests to Pod",
|
||||||
|
"nickname": "connectPUTPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "DELETE",
|
||||||
|
"summary": "connect DELETE requests to Pod",
|
||||||
|
"nickname": "connectDELETEPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "HEAD",
|
||||||
|
"summary": "connect HEAD requests to Pod",
|
||||||
|
"nickname": "connectHEADPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "OPTIONS",
|
||||||
|
"summary": "connect OPTIONS requests to Pod",
|
||||||
|
"nickname": "connectOPTIONSPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/api/v1beta1/pods/{name}/proxy/{path:*}",
|
||||||
|
"description": "API at /api/v1beta1 version v1beta1",
|
||||||
|
"operations": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "GET",
|
||||||
|
"summary": "connect GET requests to Pod",
|
||||||
|
"nickname": "connectGETPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "POST",
|
||||||
|
"summary": "connect POST requests to Pod",
|
||||||
|
"nickname": "connectPOSTPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "PUT",
|
||||||
|
"summary": "connect PUT requests to Pod",
|
||||||
|
"nickname": "connectPUTPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "DELETE",
|
||||||
|
"summary": "connect DELETE requests to Pod",
|
||||||
|
"nickname": "connectDELETEPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "HEAD",
|
||||||
|
"summary": "connect HEAD requests to Pod",
|
||||||
|
"nickname": "connectHEADPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "OPTIONS",
|
||||||
|
"summary": "connect OPTIONS requests to Pod",
|
||||||
|
"nickname": "connectOPTIONSPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/api/v1beta1/pods/{name}/status",
|
"path": "/api/v1beta1/pods/{name}/status",
|
||||||
"description": "API at /api/v1beta1 version v1beta1",
|
"description": "API at /api/v1beta1 version v1beta1",
|
||||||
@ -6914,6 +7120,31 @@
|
|||||||
"id": "",
|
"id": "",
|
||||||
"properties": null
|
"properties": null
|
||||||
},
|
},
|
||||||
|
"v1beta1.AWSElasticBlockStoreVolumeSource": {
|
||||||
|
"id": "v1beta1.AWSElasticBlockStoreVolumeSource",
|
||||||
|
"required": [
|
||||||
|
"volumeID"
|
||||||
|
],
|
||||||
|
"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"
|
||||||
|
},
|
||||||
|
"readOnly": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "read-only if true, read-write otherwise (false or unspecified)"
|
||||||
|
},
|
||||||
|
"volumeID": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "unique id of the PD resource in AWS"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"v1beta1.AccessModeType": {
|
"v1beta1.AccessModeType": {
|
||||||
"id": "v1beta1.AccessModeType",
|
"id": "v1beta1.AccessModeType",
|
||||||
"properties": {}
|
"properties": {}
|
||||||
@ -8668,6 +8899,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"v1beta1.PersistentVolumeClaimVolumeSource": {
|
||||||
|
"id": "v1beta1.PersistentVolumeClaimVolumeSource",
|
||||||
|
"properties": {
|
||||||
|
"claimName": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "the name of the claim in the same namespace to be mounted as a volume"
|
||||||
|
},
|
||||||
|
"readOnly": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "mount volume as read-only when true; default false"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"v1beta1.PersistentVolumeList": {
|
"v1beta1.PersistentVolumeList": {
|
||||||
"id": "v1beta1.PersistentVolumeList",
|
"id": "v1beta1.PersistentVolumeList",
|
||||||
"properties": {
|
"properties": {
|
||||||
@ -8727,9 +8971,10 @@
|
|||||||
"v1beta1.PersistentVolumeSpec": {
|
"v1beta1.PersistentVolumeSpec": {
|
||||||
"id": "v1beta1.PersistentVolumeSpec",
|
"id": "v1beta1.PersistentVolumeSpec",
|
||||||
"required": [
|
"required": [
|
||||||
"persistentDisk",
|
|
||||||
"hostPath",
|
"hostPath",
|
||||||
"glusterfs"
|
"glusterfs",
|
||||||
|
"persistentDisk",
|
||||||
|
"awsElasticBlockStore"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"accessModes": {
|
"accessModes": {
|
||||||
@ -8739,6 +8984,10 @@
|
|||||||
},
|
},
|
||||||
"description": "all ways the volume can be mounted"
|
"description": "all ways the volume can be mounted"
|
||||||
},
|
},
|
||||||
|
"awsElasticBlockStore": {
|
||||||
|
"$ref": "v1beta1.AWSElasticBlockStoreVolumeSource",
|
||||||
|
"description": "AWS disk resource provisioned by an admin"
|
||||||
|
},
|
||||||
"capacity": {
|
"capacity": {
|
||||||
"type": "any",
|
"type": "any",
|
||||||
"description": "a description of the persistent volume's resources and capacity"
|
"description": "a description of the persistent volume's resources and capacity"
|
||||||
@ -8911,63 +9160,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"v1beta1.PodLogOptions": {
|
|
||||||
"id": "v1beta1.PodLogOptions",
|
|
||||||
"properties": {
|
|
||||||
"annotations": {
|
|
||||||
"type": "any",
|
|
||||||
"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"
|
|
||||||
},
|
|
||||||
"container": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "the container for which to stream logs; defaults to only container if there is one container in the pod"
|
|
||||||
},
|
|
||||||
"creationTimestamp": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "RFC 3339 date and time at which the object was created; populated by the system, read-only; null for lists"
|
|
||||||
},
|
|
||||||
"deletionTimestamp": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "RFC 3339 date and time at which the object will be deleted; populated by the system when a graceful deletion is requested, read-only; if not set, graceful deletion of the object has not been requested"
|
|
||||||
},
|
|
||||||
"follow": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "follow the log stream of the pod; defaults to false"
|
|
||||||
},
|
|
||||||
"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; cannot be updated"
|
|
||||||
},
|
|
||||||
"kind": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "kind of object, in CamelCase; cannot be updated"
|
|
||||||
},
|
|
||||||
"namespace": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default; cannot be updated"
|
|
||||||
},
|
|
||||||
"resourceVersion": {
|
|
||||||
"$ref": "uint64",
|
|
||||||
"description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; populated by the system, read-only; value must be treated as opaque by clients and passed unmodified back to the server: https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/api-conventions.md#concurrency-control-and-consistency"
|
|
||||||
},
|
|
||||||
"selfLink": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "URL for the object; populated by the system, read-only"
|
|
||||||
},
|
|
||||||
"uid": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "unique UUID across space and time; populated by the system, read-only; cannot be updated"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"v1beta1.PodState": {
|
"v1beta1.PodState": {
|
||||||
"id": "v1beta1.PodState",
|
"id": "v1beta1.PodState",
|
||||||
"properties": {
|
"properties": {
|
||||||
@ -9812,7 +10004,7 @@
|
|||||||
},
|
},
|
||||||
"source": {
|
"source": {
|
||||||
"$ref": "v1beta1.VolumeSource",
|
"$ref": "v1beta1.VolumeSource",
|
||||||
"description": "location and type of volume to mount; at most one of HostDir, EmptyDir, GCEPersistentDisk, or GitRepo; default is EmptyDir"
|
"description": "location and type of volume to mount; at most one of HostDir, EmptyDir, GCEPersistentDisk, AWSElasticBlockStore, or GitRepo; default is EmptyDir"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -9851,6 +10043,7 @@
|
|||||||
"hostDir",
|
"hostDir",
|
||||||
"emptyDir",
|
"emptyDir",
|
||||||
"persistentDisk",
|
"persistentDisk",
|
||||||
|
"awsElasticBlockStore",
|
||||||
"gitRepo",
|
"gitRepo",
|
||||||
"secret",
|
"secret",
|
||||||
"nfs",
|
"nfs",
|
||||||
@ -9858,6 +10051,10 @@
|
|||||||
"glusterfs"
|
"glusterfs"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"awsElasticBlockStore": {
|
||||||
|
"$ref": "v1beta1.AWSElasticBlockStoreVolumeSource",
|
||||||
|
"description": "AWS disk resource attached to the host machine on demand"
|
||||||
|
},
|
||||||
"emptyDir": {
|
"emptyDir": {
|
||||||
"$ref": "v1beta1.EmptyDirVolumeSource",
|
"$ref": "v1beta1.EmptyDirVolumeSource",
|
||||||
"description": "temporary directory that shares a pod's lifetime"
|
"description": "temporary directory that shares a pod's lifetime"
|
||||||
@ -9886,6 +10083,10 @@
|
|||||||
"$ref": "v1beta1.GCEPersistentDiskVolumeSource",
|
"$ref": "v1beta1.GCEPersistentDiskVolumeSource",
|
||||||
"description": "GCE disk resource attached to the host machine on demand"
|
"description": "GCE disk resource attached to the host machine on demand"
|
||||||
},
|
},
|
||||||
|
"persistentVolumeClaim": {
|
||||||
|
"$ref": "v1beta1.PersistentVolumeClaimVolumeSource",
|
||||||
|
"description": "a reference to a PersistentVolumeClaim in the same namespace"
|
||||||
|
},
|
||||||
"secret": {
|
"secret": {
|
||||||
"$ref": "v1beta1.SecretVolumeSource",
|
"$ref": "v1beta1.SecretVolumeSource",
|
||||||
"description": "secret to populate volume with"
|
"description": "secret to populate volume with"
|
||||||
|
@ -4742,21 +4742,40 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/api/v1beta2/pods/{name}/exec",
|
||||||
|
"description": "API at /api/v1beta2 version v1beta2",
|
||||||
|
"operations": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "GET",
|
||||||
|
"summary": "connect GET requests to Pod",
|
||||||
|
"nickname": "connectGETPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/api/v1beta2/pods/{name}/log",
|
"path": "/api/v1beta2/pods/{name}/log",
|
||||||
"description": "API at /api/v1beta2 version v1beta2",
|
"description": "API at /api/v1beta2 version v1beta2",
|
||||||
"operations": [
|
"operations": [
|
||||||
{
|
{
|
||||||
"type": "v1beta2.PodLogOptions",
|
"type": "v1beta2.Pod",
|
||||||
"method": "GET",
|
"method": "GET",
|
||||||
"summary": "read the specified PodLogOptions",
|
"summary": "read the specified Pod",
|
||||||
"nickname": "readPodLogOptions",
|
"nickname": "readPod",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"paramType": "path",
|
"paramType": "path",
|
||||||
"name": "name",
|
"name": "name",
|
||||||
"description": "name of the PodLogOptions",
|
"description": "name of the Pod",
|
||||||
"required": true,
|
"required": true,
|
||||||
"allowMultiple": false
|
"allowMultiple": false
|
||||||
},
|
},
|
||||||
@ -4773,7 +4792,7 @@
|
|||||||
{
|
{
|
||||||
"code": 200,
|
"code": 200,
|
||||||
"message": "OK",
|
"message": "OK",
|
||||||
"responseModel": "v1beta2.PodLogOptions"
|
"responseModel": "v1beta2.Pod"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@ -4785,6 +4804,193 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "/api/v1beta2/pods/{name}/portforward",
|
||||||
|
"description": "API at /api/v1beta2 version v1beta2",
|
||||||
|
"operations": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "GET",
|
||||||
|
"summary": "connect GET requests to Pod",
|
||||||
|
"nickname": "connectGETPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/api/v1beta2/pods/{name}/proxy",
|
||||||
|
"description": "API at /api/v1beta2 version v1beta2",
|
||||||
|
"operations": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "GET",
|
||||||
|
"summary": "connect GET requests to Pod",
|
||||||
|
"nickname": "connectGETPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "POST",
|
||||||
|
"summary": "connect POST requests to Pod",
|
||||||
|
"nickname": "connectPOSTPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "PUT",
|
||||||
|
"summary": "connect PUT requests to Pod",
|
||||||
|
"nickname": "connectPUTPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "DELETE",
|
||||||
|
"summary": "connect DELETE requests to Pod",
|
||||||
|
"nickname": "connectDELETEPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "HEAD",
|
||||||
|
"summary": "connect HEAD requests to Pod",
|
||||||
|
"nickname": "connectHEADPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "OPTIONS",
|
||||||
|
"summary": "connect OPTIONS requests to Pod",
|
||||||
|
"nickname": "connectOPTIONSPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/api/v1beta2/pods/{name}/proxy/{path:*}",
|
||||||
|
"description": "API at /api/v1beta2 version v1beta2",
|
||||||
|
"operations": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "GET",
|
||||||
|
"summary": "connect GET requests to Pod",
|
||||||
|
"nickname": "connectGETPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "POST",
|
||||||
|
"summary": "connect POST requests to Pod",
|
||||||
|
"nickname": "connectPOSTPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "PUT",
|
||||||
|
"summary": "connect PUT requests to Pod",
|
||||||
|
"nickname": "connectPUTPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "DELETE",
|
||||||
|
"summary": "connect DELETE requests to Pod",
|
||||||
|
"nickname": "connectDELETEPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "HEAD",
|
||||||
|
"summary": "connect HEAD requests to Pod",
|
||||||
|
"nickname": "connectHEADPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"method": "OPTIONS",
|
||||||
|
"summary": "connect OPTIONS requests to Pod",
|
||||||
|
"nickname": "connectOPTIONSPod",
|
||||||
|
"parameters": [],
|
||||||
|
"produces": [
|
||||||
|
"*/*"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"*/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "/api/v1beta2/pods/{name}/status",
|
"path": "/api/v1beta2/pods/{name}/status",
|
||||||
"description": "API at /api/v1beta2 version v1beta2",
|
"description": "API at /api/v1beta2 version v1beta2",
|
||||||
@ -6914,6 +7120,31 @@
|
|||||||
"id": "",
|
"id": "",
|
||||||
"properties": null
|
"properties": null
|
||||||
},
|
},
|
||||||
|
"v1beta2.AWSElasticBlockStoreVolumeSource": {
|
||||||
|
"id": "v1beta2.AWSElasticBlockStoreVolumeSource",
|
||||||
|
"required": [
|
||||||
|
"volumeID"
|
||||||
|
],
|
||||||
|
"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"
|
||||||
|
},
|
||||||
|
"readOnly": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "read-only if true, read-write otherwise (false or unspecified)"
|
||||||
|
},
|
||||||
|
"volumeID": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "unique id of the PD resource in AWS"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"v1beta2.AccessModeType": {
|
"v1beta2.AccessModeType": {
|
||||||
"id": "v1beta2.AccessModeType",
|
"id": "v1beta2.AccessModeType",
|
||||||
"properties": {}
|
"properties": {}
|
||||||
@ -8657,6 +8888,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"v1beta2.PersistentVolumeClaimVolumeSource": {
|
||||||
|
"id": "v1beta2.PersistentVolumeClaimVolumeSource",
|
||||||
|
"properties": {
|
||||||
|
"claimName": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "the name of the claim in the same namespace to be mounted as a volume"
|
||||||
|
},
|
||||||
|
"readOnly": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "mount volume as read-only when true; default false"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"v1beta2.PersistentVolumeList": {
|
"v1beta2.PersistentVolumeList": {
|
||||||
"id": "v1beta2.PersistentVolumeList",
|
"id": "v1beta2.PersistentVolumeList",
|
||||||
"properties": {
|
"properties": {
|
||||||
@ -8717,6 +8961,7 @@
|
|||||||
"id": "v1beta2.PersistentVolumeSpec",
|
"id": "v1beta2.PersistentVolumeSpec",
|
||||||
"required": [
|
"required": [
|
||||||
"persistentDisk",
|
"persistentDisk",
|
||||||
|
"awsElasticBlockStore",
|
||||||
"hostPath",
|
"hostPath",
|
||||||
"glusterfs"
|
"glusterfs"
|
||||||
],
|
],
|
||||||
@ -8728,6 +8973,10 @@
|
|||||||
},
|
},
|
||||||
"description": "all ways the volume can be mounted"
|
"description": "all ways the volume can be mounted"
|
||||||
},
|
},
|
||||||
|
"awsElasticBlockStore": {
|
||||||
|
"$ref": "v1beta2.AWSElasticBlockStoreVolumeSource",
|
||||||
|
"description": "AWS disk resource provisioned by an admin"
|
||||||
|
},
|
||||||
"capacity": {
|
"capacity": {
|
||||||
"type": "any",
|
"type": "any",
|
||||||
"description": "a description of the persistent volume's resources and capacity"
|
"description": "a description of the persistent volume's resources and capacity"
|
||||||
@ -8900,63 +9149,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"v1beta2.PodLogOptions": {
|
|
||||||
"id": "v1beta2.PodLogOptions",
|
|
||||||
"properties": {
|
|
||||||
"annotations": {
|
|
||||||
"type": "any",
|
|
||||||
"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"
|
|
||||||
},
|
|
||||||
"container": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "the container for which to stream logs; defaults to only container if there is one container in the pod"
|
|
||||||
},
|
|
||||||
"creationTimestamp": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "RFC 3339 date and time at which the object was created; populated by the system, read-only; null for lists"
|
|
||||||
},
|
|
||||||
"deletionTimestamp": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "RFC 3339 date and time at which the object will be deleted; populated by the system when a graceful deletion is requested, read-only; if not set, graceful deletion of the object has not been requested"
|
|
||||||
},
|
|
||||||
"follow": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "follow the log stream of the pod; defaults to false"
|
|
||||||
},
|
|
||||||
"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; cannot be updated"
|
|
||||||
},
|
|
||||||
"kind": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "kind of object, in CamelCase; cannot be updated"
|
|
||||||
},
|
|
||||||
"namespace": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "namespace to which the object belongs; must be a DNS_SUBDOMAIN; 'default' by default; cannot be updated"
|
|
||||||
},
|
|
||||||
"resourceVersion": {
|
|
||||||
"$ref": "uint64",
|
|
||||||
"description": "string that identifies the internal version of this object that can be used by clients to determine when objects have changed; populated by the system, read-only; value must be treated as opaque by clients and passed unmodified back to the server: https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/api-conventions.md#concurrency-control-and-consistency"
|
|
||||||
},
|
|
||||||
"selfLink": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "URL for the object; populated by the system, read-only"
|
|
||||||
},
|
|
||||||
"uid": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "unique UUID across space and time; populated by the system, read-only"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"v1beta2.PodState": {
|
"v1beta2.PodState": {
|
||||||
"id": "v1beta2.PodState",
|
"id": "v1beta2.PodState",
|
||||||
"properties": {
|
"properties": {
|
||||||
@ -9801,7 +9993,7 @@
|
|||||||
},
|
},
|
||||||
"source": {
|
"source": {
|
||||||
"$ref": "v1beta2.VolumeSource",
|
"$ref": "v1beta2.VolumeSource",
|
||||||
"description": "location and type of volume to mount; at most one of HostDir, EmptyDir, GCEPersistentDisk, or GitRepo; default is EmptyDir"
|
"description": "location and type of volume to mount; at most one of HostDir, EmptyDir, GCEPersistentDisk, AWSElasticBlockStore, or GitRepo; default is EmptyDir"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -9832,6 +10024,7 @@
|
|||||||
"hostDir",
|
"hostDir",
|
||||||
"emptyDir",
|
"emptyDir",
|
||||||
"persistentDisk",
|
"persistentDisk",
|
||||||
|
"awsElasticBlockStore",
|
||||||
"gitRepo",
|
"gitRepo",
|
||||||
"secret",
|
"secret",
|
||||||
"nfs",
|
"nfs",
|
||||||
@ -9839,6 +10032,10 @@
|
|||||||
"glusterfs"
|
"glusterfs"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"awsElasticBlockStore": {
|
||||||
|
"$ref": "v1beta2.AWSElasticBlockStoreVolumeSource",
|
||||||
|
"description": "AWS disk resource attached to the host machine on demand"
|
||||||
|
},
|
||||||
"emptyDir": {
|
"emptyDir": {
|
||||||
"$ref": "v1beta2.EmptyDirVolumeSource",
|
"$ref": "v1beta2.EmptyDirVolumeSource",
|
||||||
"description": "temporary directory that shares a pod's lifetime"
|
"description": "temporary directory that shares a pod's lifetime"
|
||||||
@ -9867,6 +10064,10 @@
|
|||||||
"$ref": "v1beta2.GCEPersistentDiskVolumeSource",
|
"$ref": "v1beta2.GCEPersistentDiskVolumeSource",
|
||||||
"description": "GCE disk resource attached to the host machine on demand"
|
"description": "GCE disk resource attached to the host machine on demand"
|
||||||
},
|
},
|
||||||
|
"persistentVolumeClaim": {
|
||||||
|
"$ref": "v1beta2.PersistentVolumeClaimVolumeSource",
|
||||||
|
"description": "a reference to a PersistentVolumeClaim in the same namespace"
|
||||||
|
},
|
||||||
"secret": {
|
"secret": {
|
||||||
"$ref": "v1beta2.SecretVolumeSource",
|
"$ref": "v1beta2.SecretVolumeSource",
|
||||||
"description": "secret to populate volume"
|
"description": "secret to populate volume"
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -251,6 +251,7 @@ _kubectl_get()
|
|||||||
must_have_one_noun+=("persistentvolume")
|
must_have_one_noun+=("persistentvolume")
|
||||||
must_have_one_noun+=("persistentvolumeclaim")
|
must_have_one_noun+=("persistentvolumeclaim")
|
||||||
must_have_one_noun+=("pod")
|
must_have_one_noun+=("pod")
|
||||||
|
must_have_one_noun+=("podtemplate")
|
||||||
must_have_one_noun+=("replicationcontroller")
|
must_have_one_noun+=("replicationcontroller")
|
||||||
must_have_one_noun+=("resourcequota")
|
must_have_one_noun+=("resourcequota")
|
||||||
must_have_one_noun+=("secret")
|
must_have_one_noun+=("secret")
|
||||||
|
@ -34,7 +34,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func validateObject(obj runtime.Object) (errors []error) {
|
func validateObject(obj runtime.Object) (errors []error) {
|
||||||
ctx := api.NewDefaultContext()
|
|
||||||
switch t := obj.(type) {
|
switch t := obj.(type) {
|
||||||
case *api.ReplicationController:
|
case *api.ReplicationController:
|
||||||
if t.Namespace == "" {
|
if t.Namespace == "" {
|
||||||
@ -49,7 +48,6 @@ func validateObject(obj runtime.Object) (errors []error) {
|
|||||||
if t.Namespace == "" {
|
if t.Namespace == "" {
|
||||||
t.Namespace = api.NamespaceDefault
|
t.Namespace = api.NamespaceDefault
|
||||||
}
|
}
|
||||||
api.ValidNamespace(ctx, &t.ObjectMeta)
|
|
||||||
errors = validation.ValidateService(t)
|
errors = validation.ValidateService(t)
|
||||||
case *api.ServiceList:
|
case *api.ServiceList:
|
||||||
for i := range t.Items {
|
for i := range t.Items {
|
||||||
@ -59,7 +57,6 @@ func validateObject(obj runtime.Object) (errors []error) {
|
|||||||
if t.Namespace == "" {
|
if t.Namespace == "" {
|
||||||
t.Namespace = api.NamespaceDefault
|
t.Namespace = api.NamespaceDefault
|
||||||
}
|
}
|
||||||
api.ValidNamespace(ctx, &t.ObjectMeta)
|
|
||||||
errors = validation.ValidatePod(t)
|
errors = validation.ValidatePod(t)
|
||||||
case *api.PodList:
|
case *api.PodList:
|
||||||
for i := range t.Items {
|
for i := range t.Items {
|
||||||
@ -68,8 +65,15 @@ func validateObject(obj runtime.Object) (errors []error) {
|
|||||||
case *api.PersistentVolume:
|
case *api.PersistentVolume:
|
||||||
errors = validation.ValidatePersistentVolume(t)
|
errors = validation.ValidatePersistentVolume(t)
|
||||||
case *api.PersistentVolumeClaim:
|
case *api.PersistentVolumeClaim:
|
||||||
api.ValidNamespace(ctx, &t.ObjectMeta)
|
if t.Namespace == "" {
|
||||||
|
t.Namespace = api.NamespaceDefault
|
||||||
|
}
|
||||||
errors = validation.ValidatePersistentVolumeClaim(t)
|
errors = validation.ValidatePersistentVolumeClaim(t)
|
||||||
|
case *api.PodTemplate:
|
||||||
|
if t.Namespace == "" {
|
||||||
|
t.Namespace = api.NamespaceDefault
|
||||||
|
}
|
||||||
|
errors = validation.ValidatePodTemplate(t)
|
||||||
default:
|
default:
|
||||||
return []error{fmt.Errorf("no validation defined for %#v", obj)}
|
return []error{fmt.Errorf("no validation defined for %#v", obj)}
|
||||||
}
|
}
|
||||||
@ -156,6 +160,7 @@ func TestExampleObjectSchemas(t *testing.T) {
|
|||||||
"pod-with-http-healthcheck": &api.Pod{},
|
"pod-with-http-healthcheck": &api.Pod{},
|
||||||
"service": &api.Service{},
|
"service": &api.Service{},
|
||||||
"replication-controller": &api.ReplicationController{},
|
"replication-controller": &api.ReplicationController{},
|
||||||
|
"podtemplate": &api.PodTemplate{},
|
||||||
},
|
},
|
||||||
"../examples/update-demo": {
|
"../examples/update-demo": {
|
||||||
"kitten-rc": &api.ReplicationController{},
|
"kitten-rc": &api.ReplicationController{},
|
||||||
|
22
examples/walkthrough/podtemplate.json
Normal file
22
examples/walkthrough/podtemplate.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"apiVersion": "v1beta3",
|
||||||
|
"kind": "PodTemplate",
|
||||||
|
"metadata": {
|
||||||
|
"name": "nginx"
|
||||||
|
},
|
||||||
|
"template": {
|
||||||
|
"metadata": {
|
||||||
|
"labels": {
|
||||||
|
"name": "nginx"
|
||||||
|
},
|
||||||
|
"generateName": "nginx-"
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
|
"containers": [{
|
||||||
|
"name": "nginx",
|
||||||
|
"image": "dockerfile/nginx",
|
||||||
|
"ports": [{"containerPort": 80}]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -358,6 +358,34 @@ for version in "${kube_api_versions[@]}"; do
|
|||||||
kube::test::get_object_assert 'pods --namespace=other' "{{range.items}}{{$id_field}}:{{end}}" ''
|
kube::test::get_object_assert 'pods --namespace=other' "{{range.items}}{{$id_field}}:{{end}}" ''
|
||||||
|
|
||||||
|
|
||||||
|
#################
|
||||||
|
# Pod templates #
|
||||||
|
#################
|
||||||
|
|
||||||
|
# Note: pod templates exist only in v1beta3 and above, so output will always be in that form
|
||||||
|
|
||||||
|
### Create PODTEMPLATE
|
||||||
|
# Pre-condition: no PODTEMPLATE
|
||||||
|
kube::test::get_object_assert podtemplates "{{range.items}}{{.metadata.name}}:{{end}}" ''
|
||||||
|
# Command
|
||||||
|
kubectl create -f examples/walkthrough/podtemplate.json "${kube_flags[@]}"
|
||||||
|
# Post-condition: nginx PODTEMPLATE is available
|
||||||
|
kube::test::get_object_assert podtemplates "{{range.items}}{{.metadata.name}}:{{end}}" 'nginx:'
|
||||||
|
|
||||||
|
### Printing pod templates works
|
||||||
|
kubectl get podtemplates "${kube_flags[@]}"
|
||||||
|
### Display of an object which doesn't existing in v1beta1 and v1beta2 works
|
||||||
|
[[ "$(kubectl get podtemplates -o yaml "${kube_flags[@]}" | grep nginx)" ]]
|
||||||
|
|
||||||
|
### Delete nginx pod template by name
|
||||||
|
# Pre-condition: nginx pod template is available
|
||||||
|
kube::test::get_object_assert podtemplates "{{range.items}}{{.metadata.name}}:{{end}}" 'nginx:'
|
||||||
|
# Command
|
||||||
|
kubectl delete podtemplate nginx "${kube_flags[@]}"
|
||||||
|
# Post-condition: No templates exist
|
||||||
|
kube::test::get_object_assert podtemplate "{{range.items}}{{.metadata.name}}:{{end}}" ''
|
||||||
|
|
||||||
|
|
||||||
############
|
############
|
||||||
# Services #
|
# Services #
|
||||||
############
|
############
|
||||||
|
@ -80,6 +80,10 @@ func TestRESTMapper(t *testing.T) {
|
|||||||
t.Errorf("unexpected version mapping: %s %s %v", v, k, err)
|
t.Errorf("unexpected version mapping: %s %s %v", v, k, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if m, err := RESTMapper.RESTMapping("PodTemplate", ""); err != nil || m.APIVersion != "v1beta3" || m.Resource != "podtemplates" {
|
||||||
|
t.Errorf("unexpected version mapping: %#v %v", m, err)
|
||||||
|
}
|
||||||
|
|
||||||
for _, version := range Versions {
|
for _, version := range Versions {
|
||||||
mapping, err := RESTMapper.RESTMapping("ReplicationController", version)
|
mapping, err := RESTMapper.RESTMapping("ReplicationController", version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -28,6 +28,8 @@ func init() {
|
|||||||
&Pod{},
|
&Pod{},
|
||||||
&PodList{},
|
&PodList{},
|
||||||
&PodStatusResult{},
|
&PodStatusResult{},
|
||||||
|
&PodTemplate{},
|
||||||
|
&PodTemplateList{},
|
||||||
&ReplicationControllerList{},
|
&ReplicationControllerList{},
|
||||||
&ReplicationController{},
|
&ReplicationController{},
|
||||||
&ServiceList{},
|
&ServiceList{},
|
||||||
@ -71,6 +73,8 @@ func init() {
|
|||||||
func (*Pod) IsAnAPIObject() {}
|
func (*Pod) IsAnAPIObject() {}
|
||||||
func (*PodList) IsAnAPIObject() {}
|
func (*PodList) IsAnAPIObject() {}
|
||||||
func (*PodStatusResult) IsAnAPIObject() {}
|
func (*PodStatusResult) IsAnAPIObject() {}
|
||||||
|
func (*PodTemplate) IsAnAPIObject() {}
|
||||||
|
func (*PodTemplateList) IsAnAPIObject() {}
|
||||||
func (*ReplicationController) IsAnAPIObject() {}
|
func (*ReplicationController) IsAnAPIObject() {}
|
||||||
func (*ReplicationControllerList) IsAnAPIObject() {}
|
func (*ReplicationControllerList) IsAnAPIObject() {}
|
||||||
func (*Service) IsAnAPIObject() {}
|
func (*Service) IsAnAPIObject() {}
|
||||||
|
@ -179,7 +179,7 @@ func (t *Tester) TestCreateRejectsMismatchedNamespace(valid runtime.Object) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("Expected an error, but we didn't get one")
|
t.Errorf("Expected an error, but we didn't get one")
|
||||||
} else if strings.Contains(err.Error(), "Controller.Namespace does not match the provided context") {
|
} else if strings.Contains(err.Error(), "Controller.Namespace does not match the provided context") {
|
||||||
t.Errorf("Expected 'Controller.Namespace does not match the provided context' error, got '%v'", err.Error())
|
t.Errorf("Expected 'Controller.Namespace does not match the provided context' error, got '%v'", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,7 +195,30 @@ func (t *Tester) TestCreateRejectsNamespace(valid runtime.Object) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("Expected an error, but we didn't get one")
|
t.Errorf("Expected an error, but we didn't get one")
|
||||||
} else if strings.Contains(err.Error(), "Controller.Namespace does not match the provided context") {
|
} else if strings.Contains(err.Error(), "Controller.Namespace does not match the provided context") {
|
||||||
t.Errorf("Expected 'Controller.Namespace does not match the provided context' error, got '%v'", err.Error())
|
t.Errorf("Expected 'Controller.Namespace does not match the provided context' error, got '%v'", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tester) TestUpdate(valid runtime.Object, existing, older runtime.Object) {
|
||||||
|
t.TestUpdateFailsOnNotFound(copyOrDie(valid))
|
||||||
|
t.TestUpdateFailsOnVersion(copyOrDie(older))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tester) TestUpdateFailsOnNotFound(valid runtime.Object) {
|
||||||
|
_, _, err := t.storage.(rest.Updater).Update(api.NewDefaultContext(), valid)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Expected an error, but we didn't get one")
|
||||||
|
} else if !errors.IsNotFound(err) {
|
||||||
|
t.Errorf("Expected NotFound error, got '%v'", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tester) TestUpdateFailsOnVersion(older runtime.Object) {
|
||||||
|
_, _, err := t.storage.(rest.Updater).Update(api.NewDefaultContext(), older)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Expected an error, but we didn't get one")
|
||||||
|
} else if !errors.IsConflict(err) {
|
||||||
|
t.Errorf("Expected Conflict error, got '%v'", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,13 +85,20 @@ func roundTrip(t *testing.T, codec runtime.Codec, item runtime.Object) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// roundTripSame verifies the same source object is tested in all API versions.
|
// roundTripSame verifies the same source object is tested in all API versions.
|
||||||
func roundTripSame(t *testing.T, item runtime.Object) {
|
func roundTripSame(t *testing.T, item runtime.Object, except ...string) {
|
||||||
|
set := util.NewStringSet(except...)
|
||||||
seed := rand.Int63()
|
seed := rand.Int63()
|
||||||
fuzzInternalObject(t, "", item, seed)
|
fuzzInternalObject(t, "", item, seed)
|
||||||
roundTrip(t, v1beta1.Codec, item)
|
if !set.Has("v1beta1") {
|
||||||
roundTrip(t, v1beta2.Codec, item)
|
roundTrip(t, v1beta1.Codec, item)
|
||||||
fuzzInternalObject(t, "v1beta3", item, seed)
|
}
|
||||||
roundTrip(t, v1beta3.Codec, item)
|
if !set.Has("v1beta2") {
|
||||||
|
roundTrip(t, v1beta2.Codec, item)
|
||||||
|
}
|
||||||
|
if !set.Has("v1beta3") {
|
||||||
|
fuzzInternalObject(t, "v1beta3", item, seed)
|
||||||
|
roundTrip(t, v1beta3.Codec, item)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func roundTripAll(t *testing.T, item runtime.Object) {
|
func roundTripAll(t *testing.T, item runtime.Object) {
|
||||||
@ -130,6 +137,10 @@ func TestList(t *testing.T) {
|
|||||||
|
|
||||||
var nonRoundTrippableTypes = util.NewStringSet("ContainerManifest", "ContainerManifestList")
|
var nonRoundTrippableTypes = util.NewStringSet("ContainerManifest", "ContainerManifestList")
|
||||||
var nonInternalRoundTrippableTypes = util.NewStringSet("List", "ListOptions", "PodExecOptions")
|
var nonInternalRoundTrippableTypes = util.NewStringSet("List", "ListOptions", "PodExecOptions")
|
||||||
|
var nonRoundTrippableTypesByVersion = map[string][]string{
|
||||||
|
"PodTemplate": {"v1beta1", "v1beta2"},
|
||||||
|
"PodTemplateList": {"v1beta1", "v1beta2"},
|
||||||
|
}
|
||||||
|
|
||||||
func TestRoundTripTypes(t *testing.T) {
|
func TestRoundTripTypes(t *testing.T) {
|
||||||
// api.Scheme.Log(t)
|
// api.Scheme.Log(t)
|
||||||
@ -148,7 +159,7 @@ func TestRoundTripTypes(t *testing.T) {
|
|||||||
if _, err := meta.TypeAccessor(item); err != nil {
|
if _, err := meta.TypeAccessor(item); err != nil {
|
||||||
t.Fatalf("%q is not a TypeMeta and cannot be tested - add it to nonRoundTrippableTypes: %v", kind, err)
|
t.Fatalf("%q is not a TypeMeta and cannot be tested - add it to nonRoundTrippableTypes: %v", kind, err)
|
||||||
}
|
}
|
||||||
roundTripSame(t, item)
|
roundTripSame(t, item, nonRoundTrippableTypesByVersion[kind]...)
|
||||||
if !nonInternalRoundTrippableTypes.Has(kind) {
|
if !nonInternalRoundTrippableTypes.Has(kind) {
|
||||||
roundTrip(t, api.Codec, fuzzInternalObject(t, "", item, rand.Int63()))
|
roundTrip(t, api.Codec, fuzzInternalObject(t, "", item, rand.Int63()))
|
||||||
}
|
}
|
||||||
|
@ -848,8 +848,8 @@ type PodTemplate struct {
|
|||||||
TypeMeta `json:",inline"`
|
TypeMeta `json:",inline"`
|
||||||
ObjectMeta `json:"metadata,omitempty"`
|
ObjectMeta `json:"metadata,omitempty"`
|
||||||
|
|
||||||
// Spec defines the pods that will be created from this template
|
// Template defines the pods that will be created from this pod template
|
||||||
Spec PodTemplateSpec `json:"spec,omitempty"`
|
Template PodTemplateSpec `json:"template,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PodTemplateList is a list of PodTemplates.
|
// PodTemplateList is a list of PodTemplates.
|
||||||
|
@ -854,8 +854,8 @@ type PodTemplate struct {
|
|||||||
TypeMeta `json:",inline"`
|
TypeMeta `json:",inline"`
|
||||||
ObjectMeta `json:"metadata,omitempty" description:"standard object metadata; see https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/api-conventions.md#metadata"`
|
ObjectMeta `json:"metadata,omitempty" description:"standard object metadata; see https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/api-conventions.md#metadata"`
|
||||||
|
|
||||||
// Spec defines the behavior of a pod.
|
// Template defines the pods that will be created from this pod template
|
||||||
Spec PodTemplateSpec `json:"spec,omitempty" description:"specification of the desired behavior of the pod; https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/api-conventions.md#spec-and-status"`
|
Template PodTemplateSpec `json:"template,omitempty" description:"the template of the desired behavior of the pod; https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/api-conventions.md#spec-and-status"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PodTemplateList is a list of PodTemplates.
|
// PodTemplateList is a list of PodTemplates.
|
||||||
|
@ -888,6 +888,24 @@ func ValidatePodStatusUpdate(newPod, oldPod *api.Pod) errs.ValidationErrorList {
|
|||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidatePodTemplate tests if required fields in the pod template are set.
|
||||||
|
func ValidatePodTemplate(pod *api.PodTemplate) errs.ValidationErrorList {
|
||||||
|
allErrs := errs.ValidationErrorList{}
|
||||||
|
allErrs = append(allErrs, ValidateObjectMeta(&pod.ObjectMeta, true, ValidatePodName).Prefix("metadata")...)
|
||||||
|
allErrs = append(allErrs, ValidatePodTemplateSpec(&pod.Template, 0).Prefix("template")...)
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidatePodTemplateUpdate tests to see if the update is legal for an end user to make. newPod is updated with fields
|
||||||
|
// that cannot be changed.
|
||||||
|
func ValidatePodTemplateUpdate(newPod, oldPod *api.PodTemplate) errs.ValidationErrorList {
|
||||||
|
allErrs := errs.ValidationErrorList{}
|
||||||
|
|
||||||
|
allErrs = append(allErrs, ValidateObjectMetaUpdate(&oldPod.ObjectMeta, &newPod.ObjectMeta).Prefix("metadata")...)
|
||||||
|
allErrs = append(allErrs, ValidatePodTemplateSpec(&newPod.Template, 0).Prefix("template")...)
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
var supportedSessionAffinityType = util.NewStringSet(string(api.AffinityTypeClientIP), string(api.AffinityTypeNone))
|
var supportedSessionAffinityType = util.NewStringSet(string(api.AffinityTypeClientIP), string(api.AffinityTypeNone))
|
||||||
|
|
||||||
// ValidateService tests if required fields in the service are set.
|
// ValidateService tests if required fields in the service are set.
|
||||||
|
@ -1676,7 +1676,7 @@ func TestValidateService(t *testing.T) {
|
|||||||
func TestValidateReplicationControllerUpdate(t *testing.T) {
|
func TestValidateReplicationControllerUpdate(t *testing.T) {
|
||||||
validSelector := map[string]string{"a": "b"}
|
validSelector := map[string]string{"a": "b"}
|
||||||
validPodTemplate := api.PodTemplate{
|
validPodTemplate := api.PodTemplate{
|
||||||
Spec: api.PodTemplateSpec{
|
Template: api.PodTemplateSpec{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Labels: validSelector,
|
Labels: validSelector,
|
||||||
},
|
},
|
||||||
@ -1688,7 +1688,7 @@ func TestValidateReplicationControllerUpdate(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
readWriteVolumePodTemplate := api.PodTemplate{
|
readWriteVolumePodTemplate := api.PodTemplate{
|
||||||
Spec: api.PodTemplateSpec{
|
Template: api.PodTemplateSpec{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Labels: validSelector,
|
Labels: validSelector,
|
||||||
},
|
},
|
||||||
@ -1702,7 +1702,7 @@ func TestValidateReplicationControllerUpdate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"}
|
invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"}
|
||||||
invalidPodTemplate := api.PodTemplate{
|
invalidPodTemplate := api.PodTemplate{
|
||||||
Spec: api.PodTemplateSpec{
|
Template: api.PodTemplateSpec{
|
||||||
Spec: api.PodSpec{
|
Spec: api.PodSpec{
|
||||||
RestartPolicy: api.RestartPolicyAlways,
|
RestartPolicy: api.RestartPolicyAlways,
|
||||||
DNSPolicy: api.DNSClusterFirst,
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
@ -1722,7 +1722,7 @@ func TestValidateReplicationControllerUpdate(t *testing.T) {
|
|||||||
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
|
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
|
||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Selector: validSelector,
|
Selector: validSelector,
|
||||||
Template: &validPodTemplate.Spec,
|
Template: &validPodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
update: api.ReplicationController{
|
update: api.ReplicationController{
|
||||||
@ -1730,7 +1730,7 @@ func TestValidateReplicationControllerUpdate(t *testing.T) {
|
|||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Replicas: 3,
|
Replicas: 3,
|
||||||
Selector: validSelector,
|
Selector: validSelector,
|
||||||
Template: &validPodTemplate.Spec,
|
Template: &validPodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1739,7 +1739,7 @@ func TestValidateReplicationControllerUpdate(t *testing.T) {
|
|||||||
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
|
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
|
||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Selector: validSelector,
|
Selector: validSelector,
|
||||||
Template: &validPodTemplate.Spec,
|
Template: &validPodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
update: api.ReplicationController{
|
update: api.ReplicationController{
|
||||||
@ -1747,7 +1747,7 @@ func TestValidateReplicationControllerUpdate(t *testing.T) {
|
|||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Replicas: 1,
|
Replicas: 1,
|
||||||
Selector: validSelector,
|
Selector: validSelector,
|
||||||
Template: &readWriteVolumePodTemplate.Spec,
|
Template: &readWriteVolumePodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1765,7 +1765,7 @@ func TestValidateReplicationControllerUpdate(t *testing.T) {
|
|||||||
ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault},
|
ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault},
|
||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Selector: validSelector,
|
Selector: validSelector,
|
||||||
Template: &validPodTemplate.Spec,
|
Template: &validPodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
update: api.ReplicationController{
|
update: api.ReplicationController{
|
||||||
@ -1773,7 +1773,7 @@ func TestValidateReplicationControllerUpdate(t *testing.T) {
|
|||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Replicas: 2,
|
Replicas: 2,
|
||||||
Selector: validSelector,
|
Selector: validSelector,
|
||||||
Template: &readWriteVolumePodTemplate.Spec,
|
Template: &readWriteVolumePodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1782,7 +1782,7 @@ func TestValidateReplicationControllerUpdate(t *testing.T) {
|
|||||||
ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault},
|
ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault},
|
||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Selector: validSelector,
|
Selector: validSelector,
|
||||||
Template: &validPodTemplate.Spec,
|
Template: &validPodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
update: api.ReplicationController{
|
update: api.ReplicationController{
|
||||||
@ -1790,7 +1790,7 @@ func TestValidateReplicationControllerUpdate(t *testing.T) {
|
|||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Replicas: 2,
|
Replicas: 2,
|
||||||
Selector: invalidSelector,
|
Selector: invalidSelector,
|
||||||
Template: &validPodTemplate.Spec,
|
Template: &validPodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1799,7 +1799,7 @@ func TestValidateReplicationControllerUpdate(t *testing.T) {
|
|||||||
ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault},
|
ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault},
|
||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Selector: validSelector,
|
Selector: validSelector,
|
||||||
Template: &validPodTemplate.Spec,
|
Template: &validPodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
update: api.ReplicationController{
|
update: api.ReplicationController{
|
||||||
@ -1807,7 +1807,7 @@ func TestValidateReplicationControllerUpdate(t *testing.T) {
|
|||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Replicas: 2,
|
Replicas: 2,
|
||||||
Selector: validSelector,
|
Selector: validSelector,
|
||||||
Template: &invalidPodTemplate.Spec,
|
Template: &invalidPodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1816,7 +1816,7 @@ func TestValidateReplicationControllerUpdate(t *testing.T) {
|
|||||||
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
|
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
|
||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Selector: validSelector,
|
Selector: validSelector,
|
||||||
Template: &validPodTemplate.Spec,
|
Template: &validPodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
update: api.ReplicationController{
|
update: api.ReplicationController{
|
||||||
@ -1824,7 +1824,7 @@ func TestValidateReplicationControllerUpdate(t *testing.T) {
|
|||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Replicas: -1,
|
Replicas: -1,
|
||||||
Selector: validSelector,
|
Selector: validSelector,
|
||||||
Template: &validPodTemplate.Spec,
|
Template: &validPodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1840,7 +1840,7 @@ func TestValidateReplicationControllerUpdate(t *testing.T) {
|
|||||||
func TestValidateReplicationController(t *testing.T) {
|
func TestValidateReplicationController(t *testing.T) {
|
||||||
validSelector := map[string]string{"a": "b"}
|
validSelector := map[string]string{"a": "b"}
|
||||||
validPodTemplate := api.PodTemplate{
|
validPodTemplate := api.PodTemplate{
|
||||||
Spec: api.PodTemplateSpec{
|
Template: api.PodTemplateSpec{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Labels: validSelector,
|
Labels: validSelector,
|
||||||
},
|
},
|
||||||
@ -1852,7 +1852,7 @@ func TestValidateReplicationController(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
readWriteVolumePodTemplate := api.PodTemplate{
|
readWriteVolumePodTemplate := api.PodTemplate{
|
||||||
Spec: api.PodTemplateSpec{
|
Template: api.PodTemplateSpec{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Labels: validSelector,
|
Labels: validSelector,
|
||||||
},
|
},
|
||||||
@ -1866,7 +1866,7 @@ func TestValidateReplicationController(t *testing.T) {
|
|||||||
}
|
}
|
||||||
invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"}
|
invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"}
|
||||||
invalidPodTemplate := api.PodTemplate{
|
invalidPodTemplate := api.PodTemplate{
|
||||||
Spec: api.PodTemplateSpec{
|
Template: api.PodTemplateSpec{
|
||||||
Spec: api.PodSpec{
|
Spec: api.PodSpec{
|
||||||
RestartPolicy: api.RestartPolicyAlways,
|
RestartPolicy: api.RestartPolicyAlways,
|
||||||
DNSPolicy: api.DNSClusterFirst,
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
@ -1881,14 +1881,14 @@ func TestValidateReplicationController(t *testing.T) {
|
|||||||
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
|
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
|
||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Selector: validSelector,
|
Selector: validSelector,
|
||||||
Template: &validPodTemplate.Spec,
|
Template: &validPodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ObjectMeta: api.ObjectMeta{Name: "abc-123", Namespace: api.NamespaceDefault},
|
ObjectMeta: api.ObjectMeta{Name: "abc-123", Namespace: api.NamespaceDefault},
|
||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Selector: validSelector,
|
Selector: validSelector,
|
||||||
Template: &validPodTemplate.Spec,
|
Template: &validPodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1896,7 +1896,7 @@ func TestValidateReplicationController(t *testing.T) {
|
|||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Replicas: 1,
|
Replicas: 1,
|
||||||
Selector: validSelector,
|
Selector: validSelector,
|
||||||
Template: &readWriteVolumePodTemplate.Spec,
|
Template: &readWriteVolumePodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -1911,27 +1911,27 @@ func TestValidateReplicationController(t *testing.T) {
|
|||||||
ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault},
|
ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault},
|
||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Selector: validSelector,
|
Selector: validSelector,
|
||||||
Template: &validPodTemplate.Spec,
|
Template: &validPodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"missing-namespace": {
|
"missing-namespace": {
|
||||||
ObjectMeta: api.ObjectMeta{Name: "abc-123"},
|
ObjectMeta: api.ObjectMeta{Name: "abc-123"},
|
||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Selector: validSelector,
|
Selector: validSelector,
|
||||||
Template: &validPodTemplate.Spec,
|
Template: &validPodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"empty selector": {
|
"empty selector": {
|
||||||
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
|
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
|
||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Template: &validPodTemplate.Spec,
|
Template: &validPodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"selector_doesnt_match": {
|
"selector_doesnt_match": {
|
||||||
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
|
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
|
||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Selector: map[string]string{"foo": "bar"},
|
Selector: map[string]string{"foo": "bar"},
|
||||||
Template: &validPodTemplate.Spec,
|
Template: &validPodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"invalid manifest": {
|
"invalid manifest": {
|
||||||
@ -1945,7 +1945,7 @@ func TestValidateReplicationController(t *testing.T) {
|
|||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Replicas: 2,
|
Replicas: 2,
|
||||||
Selector: validSelector,
|
Selector: validSelector,
|
||||||
Template: &readWriteVolumePodTemplate.Spec,
|
Template: &readWriteVolumePodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"negative_replicas": {
|
"negative_replicas": {
|
||||||
@ -1965,7 +1965,7 @@ func TestValidateReplicationController(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Selector: validSelector,
|
Selector: validSelector,
|
||||||
Template: &validPodTemplate.Spec,
|
Template: &validPodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"invalid_label 2": {
|
"invalid_label 2": {
|
||||||
@ -1977,7 +1977,20 @@ func TestValidateReplicationController(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Template: &invalidPodTemplate.Spec,
|
Template: &invalidPodTemplate.Template,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"invalid_annotation": {
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "abc-123",
|
||||||
|
Namespace: api.NamespaceDefault,
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"NoUppercaseOrSpecialCharsLike=Equals": "bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: api.ReplicationControllerSpec{
|
||||||
|
Selector: validSelector,
|
||||||
|
Template: &validPodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"invalid restart policy 1": {
|
"invalid restart policy 1": {
|
||||||
|
@ -245,6 +245,7 @@ func (h *HumanReadablePrinter) HandledResources() []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var podColumns = []string{"POD", "IP", "CONTAINER(S)", "IMAGE(S)", "HOST", "LABELS", "STATUS", "CREATED", "MESSAGE"}
|
var podColumns = []string{"POD", "IP", "CONTAINER(S)", "IMAGE(S)", "HOST", "LABELS", "STATUS", "CREATED", "MESSAGE"}
|
||||||
|
var podTemplateColumns = []string{"TEMPLATE", "CONTAINER(S)", "IMAGE(S)", "PODLABELS"}
|
||||||
var replicationControllerColumns = []string{"CONTROLLER", "CONTAINER(S)", "IMAGE(S)", "SELECTOR", "REPLICAS"}
|
var replicationControllerColumns = []string{"CONTROLLER", "CONTAINER(S)", "IMAGE(S)", "SELECTOR", "REPLICAS"}
|
||||||
var serviceColumns = []string{"NAME", "LABELS", "SELECTOR", "IP", "PORT(S)"}
|
var serviceColumns = []string{"NAME", "LABELS", "SELECTOR", "IP", "PORT(S)"}
|
||||||
var endpointColumns = []string{"NAME", "ENDPOINTS"}
|
var endpointColumns = []string{"NAME", "ENDPOINTS"}
|
||||||
@ -263,6 +264,8 @@ var componentStatusColumns = []string{"NAME", "STATUS", "MESSAGE", "ERROR"}
|
|||||||
func (h *HumanReadablePrinter) addDefaultHandlers() {
|
func (h *HumanReadablePrinter) addDefaultHandlers() {
|
||||||
h.Handler(podColumns, printPod)
|
h.Handler(podColumns, printPod)
|
||||||
h.Handler(podColumns, printPodList)
|
h.Handler(podColumns, printPodList)
|
||||||
|
h.Handler(podTemplateColumns, printPodTemplate)
|
||||||
|
h.Handler(podTemplateColumns, printPodTemplateList)
|
||||||
h.Handler(replicationControllerColumns, printReplicationController)
|
h.Handler(replicationControllerColumns, printReplicationController)
|
||||||
h.Handler(replicationControllerColumns, printReplicationControllerList)
|
h.Handler(replicationControllerColumns, printReplicationControllerList)
|
||||||
h.Handler(serviceColumns, printService)
|
h.Handler(serviceColumns, printService)
|
||||||
@ -383,11 +386,6 @@ func interpretContainerStatus(status *api.ContainerStatus) (string, string, stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
func printPod(pod *api.Pod, w io.Writer) error {
|
func printPod(pod *api.Pod, w io.Writer) error {
|
||||||
// TODO: remove me when pods are converted
|
|
||||||
spec := &api.PodSpec{}
|
|
||||||
if err := api.Scheme.Convert(&pod.Spec, spec); err != nil {
|
|
||||||
glog.Errorf("Unable to convert pod manifest: %v", err)
|
|
||||||
}
|
|
||||||
_, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
|
_, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
|
||||||
pod.Name,
|
pod.Name,
|
||||||
pod.Status.PodIP,
|
pod.Status.PodIP,
|
||||||
@ -447,6 +445,40 @@ func printPodList(podList *api.PodList, w io.Writer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func printPodTemplate(pod *api.PodTemplate, w io.Writer) error {
|
||||||
|
containers := pod.Template.Spec.Containers
|
||||||
|
var firstContainer api.Container
|
||||||
|
if len(containers) > 0 {
|
||||||
|
firstContainer, containers = containers[0], containers[1:]
|
||||||
|
}
|
||||||
|
_, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\n",
|
||||||
|
pod.Name,
|
||||||
|
firstContainer.Name,
|
||||||
|
firstContainer.Image,
|
||||||
|
formatLabels(pod.Template.Labels),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Lay out all the other containers on separate lines.
|
||||||
|
for _, container := range containers {
|
||||||
|
_, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", "", container.Name, container.Image, "")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func printPodTemplateList(podList *api.PodTemplateList, w io.Writer) error {
|
||||||
|
for _, pod := range podList.Items {
|
||||||
|
if err := printPodTemplate(&pod, w); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func printReplicationController(controller *api.ReplicationController, w io.Writer) error {
|
func printReplicationController(controller *api.ReplicationController, w io.Writer) error {
|
||||||
containers := controller.Spec.Template.Spec.Containers
|
containers := controller.Spec.Template.Spec.Containers
|
||||||
var firstContainer api.Container
|
var firstContainer api.Container
|
||||||
|
@ -58,6 +58,7 @@ import (
|
|||||||
pvcetcd "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/persistentvolumeclaim/etcd"
|
pvcetcd "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/persistentvolumeclaim/etcd"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/pod"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/pod"
|
||||||
podetcd "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/pod/etcd"
|
podetcd "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/pod/etcd"
|
||||||
|
podtemplateetcd "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/podtemplate/etcd"
|
||||||
resourcequotaetcd "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/resourcequota/etcd"
|
resourcequotaetcd "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/resourcequota/etcd"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/secret"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/secret"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/service"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/service"
|
||||||
@ -360,9 +361,18 @@ func logStackOnRecover(panicReason interface{}, httpWriter http.ResponseWriter)
|
|||||||
|
|
||||||
// init initializes master.
|
// init initializes master.
|
||||||
func (m *Master) init(c *Config) {
|
func (m *Master) init(c *Config) {
|
||||||
|
// TODO: make initialization of the helper part of the Master, and allow some storage
|
||||||
|
// objects to have a newer storage version than the user's default.
|
||||||
|
newerHelper, err := NewEtcdHelper(c.EtcdHelper.Client, "v1beta3")
|
||||||
|
if err != nil {
|
||||||
|
glog.Fatalf("Unable to setup storage for v1beta3: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
podStorage := podetcd.NewStorage(c.EtcdHelper, c.KubeletClient)
|
podStorage := podetcd.NewStorage(c.EtcdHelper, c.KubeletClient)
|
||||||
podRegistry := pod.NewRegistry(podStorage.Pod)
|
podRegistry := pod.NewRegistry(podStorage.Pod)
|
||||||
|
|
||||||
|
podTemplateStorage := podtemplateetcd.NewREST(newerHelper)
|
||||||
|
|
||||||
eventRegistry := event.NewEtcdRegistry(c.EtcdHelper, uint64(c.EventTTL.Seconds()))
|
eventRegistry := event.NewEtcdRegistry(c.EtcdHelper, uint64(c.EventTTL.Seconds()))
|
||||||
limitRangeRegistry := limitrange.NewEtcdRegistry(c.EtcdHelper)
|
limitRangeRegistry := limitrange.NewEtcdRegistry(c.EtcdHelper)
|
||||||
|
|
||||||
@ -397,6 +407,8 @@ func (m *Master) init(c *Config) {
|
|||||||
"pods/binding": podStorage.Binding,
|
"pods/binding": podStorage.Binding,
|
||||||
"bindings": podStorage.Binding,
|
"bindings": podStorage.Binding,
|
||||||
|
|
||||||
|
"podTemplates": podTemplateStorage,
|
||||||
|
|
||||||
"replicationControllers": controllerStorage,
|
"replicationControllers": controllerStorage,
|
||||||
"services": service.NewStorage(m.serviceRegistry, m.nodeRegistry, m.endpointRegistry, m.portalNet, c.ClusterName),
|
"services": service.NewStorage(m.serviceRegistry, m.nodeRegistry, m.endpointRegistry, m.portalNet, c.ClusterName),
|
||||||
"endpoints": endpointsStorage,
|
"endpoints": endpointsStorage,
|
||||||
@ -606,6 +618,9 @@ func (m *Master) defaultAPIGroupVersion() *apiserver.APIGroupVersion {
|
|||||||
func (m *Master) api_v1beta1() *apiserver.APIGroupVersion {
|
func (m *Master) api_v1beta1() *apiserver.APIGroupVersion {
|
||||||
storage := make(map[string]rest.Storage)
|
storage := make(map[string]rest.Storage)
|
||||||
for k, v := range m.storage {
|
for k, v := range m.storage {
|
||||||
|
if k == "podTemplates" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
storage[k] = v
|
storage[k] = v
|
||||||
}
|
}
|
||||||
version := m.defaultAPIGroupVersion()
|
version := m.defaultAPIGroupVersion()
|
||||||
@ -619,6 +634,9 @@ func (m *Master) api_v1beta1() *apiserver.APIGroupVersion {
|
|||||||
func (m *Master) api_v1beta2() *apiserver.APIGroupVersion {
|
func (m *Master) api_v1beta2() *apiserver.APIGroupVersion {
|
||||||
storage := make(map[string]rest.Storage)
|
storage := make(map[string]rest.Storage)
|
||||||
for k, v := range m.storage {
|
for k, v := range m.storage {
|
||||||
|
if k == "podTemplates" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
storage[k] = v
|
storage[k] = v
|
||||||
}
|
}
|
||||||
version := m.defaultAPIGroupVersion()
|
version := m.defaultAPIGroupVersion()
|
||||||
|
@ -60,7 +60,7 @@ func createController(storage *REST, rc api.ReplicationController, t *testing.T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
var validPodTemplate = api.PodTemplate{
|
var validPodTemplate = api.PodTemplate{
|
||||||
Spec: api.PodTemplateSpec{
|
Template: api.PodTemplateSpec{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Labels: map[string]string{"a": "b"},
|
Labels: map[string]string{"a": "b"},
|
||||||
},
|
},
|
||||||
@ -79,8 +79,8 @@ var validPodTemplate = api.PodTemplate{
|
|||||||
}
|
}
|
||||||
|
|
||||||
var validControllerSpec = api.ReplicationControllerSpec{
|
var validControllerSpec = api.ReplicationControllerSpec{
|
||||||
Selector: validPodTemplate.Spec.Labels,
|
Selector: validPodTemplate.Template.Labels,
|
||||||
Template: &validPodTemplate.Spec,
|
Template: &validPodTemplate.Template,
|
||||||
}
|
}
|
||||||
|
|
||||||
var validController = api.ReplicationController{
|
var validController = api.ReplicationController{
|
||||||
@ -161,7 +161,7 @@ func TestCreateControllerWithGeneratedName(t *testing.T) {
|
|||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Replicas: 2,
|
Replicas: 2,
|
||||||
Selector: map[string]string{"a": "b"},
|
Selector: map[string]string{"a": "b"},
|
||||||
Template: &validPodTemplate.Spec,
|
Template: &validPodTemplate.Template,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -663,7 +663,7 @@ func TestCreate(t *testing.T) {
|
|||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Replicas: 2,
|
Replicas: 2,
|
||||||
Selector: map[string]string{"a": "b"},
|
Selector: map[string]string{"a": "b"},
|
||||||
Template: &validPodTemplate.Spec,
|
Template: &validPodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// invalid
|
// invalid
|
||||||
@ -671,7 +671,7 @@ func TestCreate(t *testing.T) {
|
|||||||
Spec: api.ReplicationControllerSpec{
|
Spec: api.ReplicationControllerSpec{
|
||||||
Replicas: 2,
|
Replicas: 2,
|
||||||
Selector: map[string]string{},
|
Selector: map[string]string{},
|
||||||
Template: &validPodTemplate.Spec,
|
Template: &validPodTemplate.Template,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -35,7 +35,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// podStrategy implements behavior for Pods
|
// podStrategy implements behavior for Pods
|
||||||
// TODO: move to a pod specific package.
|
|
||||||
type podStrategy struct {
|
type podStrategy struct {
|
||||||
runtime.ObjectTyper
|
runtime.ObjectTyper
|
||||||
api.NameGenerator
|
api.NameGenerator
|
||||||
|
18
pkg/registry/podtemplate/doc.go
Normal file
18
pkg/registry/podtemplate/doc.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
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 podtemplate provides RESTStorage implementations for storing PodTemplate API objects.
|
||||||
|
package podtemplate
|
63
pkg/registry/podtemplate/etcd/etcd.go
Normal file
63
pkg/registry/podtemplate/etcd/etcd.go
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
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 etcd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic"
|
||||||
|
etcdgeneric "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic/etcd"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/podtemplate"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
|
||||||
|
)
|
||||||
|
|
||||||
|
// rest implements a RESTStorage for pod templates against etcd
|
||||||
|
type REST struct {
|
||||||
|
etcdgeneric.Etcd
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewREST returns a RESTStorage object that will work against pod templates.
|
||||||
|
func NewREST(h tools.EtcdHelper) *REST {
|
||||||
|
prefix := "/registry/podtemplates"
|
||||||
|
store := etcdgeneric.Etcd{
|
||||||
|
NewFunc: func() runtime.Object { return &api.PodTemplate{} },
|
||||||
|
NewListFunc: func() runtime.Object { return &api.PodTemplateList{} },
|
||||||
|
KeyRootFunc: func(ctx api.Context) string {
|
||||||
|
return etcdgeneric.NamespaceKeyRootFunc(ctx, prefix)
|
||||||
|
},
|
||||||
|
KeyFunc: func(ctx api.Context, name string) (string, error) {
|
||||||
|
return etcdgeneric.NamespaceKeyFunc(ctx, prefix, name)
|
||||||
|
},
|
||||||
|
ObjectNameFunc: func(obj runtime.Object) (string, error) {
|
||||||
|
return obj.(*api.PodTemplate).Name, nil
|
||||||
|
},
|
||||||
|
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
|
return podtemplate.MatchPodTemplate(label, field)
|
||||||
|
},
|
||||||
|
EndpointName: "podtemplates",
|
||||||
|
|
||||||
|
CreateStrategy: podtemplate.Strategy,
|
||||||
|
UpdateStrategy: podtemplate.Strategy,
|
||||||
|
ReturnDeletedObject: true,
|
||||||
|
|
||||||
|
Helper: h,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &REST{store}
|
||||||
|
}
|
99
pkg/registry/podtemplate/etcd/etcd_test.go
Normal file
99
pkg/registry/podtemplate/etcd/etcd_test.go
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
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 etcd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest/resttest"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta3"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newHelper(t *testing.T) (*tools.FakeEtcdClient, tools.EtcdHelper) {
|
||||||
|
fakeEtcdClient := tools.NewFakeEtcdClient(t)
|
||||||
|
fakeEtcdClient.TestIndex = true
|
||||||
|
helper := tools.NewEtcdHelper(fakeEtcdClient, v1beta3.Codec)
|
||||||
|
return fakeEtcdClient, helper
|
||||||
|
}
|
||||||
|
|
||||||
|
func validNewPodTemplate(name string) *api.PodTemplate {
|
||||||
|
return &api.PodTemplate{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: name,
|
||||||
|
Namespace: api.NamespaceDefault,
|
||||||
|
},
|
||||||
|
Template: api.PodTemplateSpec{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Labels: map[string]string{"test": "foo"},
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
RestartPolicy: api.RestartPolicyAlways,
|
||||||
|
DNSPolicy: api.DNSClusterFirst,
|
||||||
|
Containers: []api.Container{
|
||||||
|
{
|
||||||
|
Name: "foo",
|
||||||
|
Image: "test",
|
||||||
|
ImagePullPolicy: api.PullAlways,
|
||||||
|
|
||||||
|
TerminationMessagePath: api.TerminationMessagePathDefault,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreate(t *testing.T) {
|
||||||
|
fakeEtcdClient, helper := newHelper(t)
|
||||||
|
storage := NewREST(helper)
|
||||||
|
test := resttest.New(t, storage, fakeEtcdClient.SetError)
|
||||||
|
pod := validNewPodTemplate("foo")
|
||||||
|
pod.ObjectMeta = api.ObjectMeta{}
|
||||||
|
test.TestCreate(
|
||||||
|
// valid
|
||||||
|
pod,
|
||||||
|
// invalid
|
||||||
|
&api.PodTemplate{
|
||||||
|
Template: api.PodTemplateSpec{},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdate(t *testing.T) {
|
||||||
|
fakeEtcdClient, helper := newHelper(t)
|
||||||
|
storage := NewREST(helper)
|
||||||
|
test := resttest.New(t, storage, fakeEtcdClient.SetError)
|
||||||
|
|
||||||
|
fakeEtcdClient.ExpectNotFoundGet("/registry/podtemplates/default/foo")
|
||||||
|
fakeEtcdClient.ChangeIndex = 2
|
||||||
|
pod := validNewPodTemplate("foo")
|
||||||
|
existing := validNewPodTemplate("exists")
|
||||||
|
obj, err := storage.Create(api.NewDefaultContext(), existing)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to create object: %v", err)
|
||||||
|
}
|
||||||
|
older := obj.(*api.PodTemplate)
|
||||||
|
older.ResourceVersion = "1"
|
||||||
|
|
||||||
|
test.TestUpdate(
|
||||||
|
pod,
|
||||||
|
existing,
|
||||||
|
older,
|
||||||
|
)
|
||||||
|
}
|
81
pkg/registry/podtemplate/rest.go
Normal file
81
pkg/registry/podtemplate/rest.go
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
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 podtemplate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||||
|
errs "github.com/GoogleCloudPlatform/kubernetes/pkg/util/fielderrors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// podTemplateStrategy implements behavior for PodTemplates
|
||||||
|
type podTemplateStrategy struct {
|
||||||
|
runtime.ObjectTyper
|
||||||
|
api.NameGenerator
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strategy is the default logic that applies when creating and updating PodTemplate
|
||||||
|
// objects via the REST API.
|
||||||
|
var Strategy = podTemplateStrategy{api.Scheme, api.SimpleNameGenerator}
|
||||||
|
|
||||||
|
// NamespaceScoped is true for pod templates.
|
||||||
|
func (podTemplateStrategy) NamespaceScoped() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrepareForCreate clears fields that are not allowed to be set by end users on creation.
|
||||||
|
func (podTemplateStrategy) PrepareForCreate(obj runtime.Object) {
|
||||||
|
_ = obj.(*api.PodTemplate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate validates a new pod template.
|
||||||
|
func (podTemplateStrategy) Validate(ctx api.Context, obj runtime.Object) errs.ValidationErrorList {
|
||||||
|
pod := obj.(*api.PodTemplate)
|
||||||
|
return validation.ValidatePodTemplate(pod)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllowCreateOnUpdate is false for pod templates.
|
||||||
|
func (podTemplateStrategy) AllowCreateOnUpdate() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
|
||||||
|
func (podTemplateStrategy) PrepareForUpdate(obj, old runtime.Object) {
|
||||||
|
_ = obj.(*api.PodTemplate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateUpdate is the default update validation for an end user.
|
||||||
|
func (podTemplateStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) errs.ValidationErrorList {
|
||||||
|
return validation.ValidatePodTemplateUpdate(obj.(*api.PodTemplate), old.(*api.PodTemplate))
|
||||||
|
}
|
||||||
|
|
||||||
|
// MatchPodTemplate returns a generic matcher for a given label and field selector.
|
||||||
|
func MatchPodTemplate(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
|
return generic.MatcherFunc(func(obj runtime.Object) (bool, error) {
|
||||||
|
podObj, ok := obj.(*api.PodTemplate)
|
||||||
|
if !ok {
|
||||||
|
return false, fmt.Errorf("not a pod template")
|
||||||
|
}
|
||||||
|
return label.Matches(labels.Set(podObj.Labels)), nil
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user