mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	PV & PVC Client implementation
This commit is contained in:
		@@ -65,6 +65,11 @@ func validateObject(obj runtime.Object) (errors []error) {
 | 
				
			|||||||
		for i := range t.Items {
 | 
							for i := range t.Items {
 | 
				
			||||||
			errors = append(errors, validateObject(&t.Items[i])...)
 | 
								errors = append(errors, validateObject(&t.Items[i])...)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						case *api.PersistentVolume:
 | 
				
			||||||
 | 
							errors = validation.ValidatePersistentVolume(t)
 | 
				
			||||||
 | 
						case *api.PersistentVolumeClaim:
 | 
				
			||||||
 | 
							api.ValidNamespace(ctx, &t.ObjectMeta)
 | 
				
			||||||
 | 
							errors = validation.ValidatePersistentVolumeClaim(t)
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return []error{fmt.Errorf("no validation defined for %#v", obj)}
 | 
							return []error{fmt.Errorf("no validation defined for %#v", obj)}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -160,6 +165,16 @@ func TestExampleObjectSchemas(t *testing.T) {
 | 
				
			|||||||
			"kitten-rc":   &api.ReplicationController{},
 | 
								"kitten-rc":   &api.ReplicationController{},
 | 
				
			||||||
			"nautilus-rc": &api.ReplicationController{},
 | 
								"nautilus-rc": &api.ReplicationController{},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							"../examples/persistent-volumes/volumes": {
 | 
				
			||||||
 | 
								"local-01": &api.PersistentVolume{},
 | 
				
			||||||
 | 
								"local-02": &api.PersistentVolume{},
 | 
				
			||||||
 | 
								"gce":      &api.PersistentVolume{},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"../examples/persistent-volumes/claims": {
 | 
				
			||||||
 | 
								"claim-01": &api.PersistentVolumeClaim{},
 | 
				
			||||||
 | 
								"claim-02": &api.PersistentVolumeClaim{},
 | 
				
			||||||
 | 
								"claim-03": &api.PersistentVolumeClaim{},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for path, expected := range cases {
 | 
						for path, expected := range cases {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								examples/persistent-volumes/claims/claim-01.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								examples/persistent-volumes/claims/claim-01.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					kind: PersistentVolumeClaim
 | 
				
			||||||
 | 
					apiVersion: v1beta3
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: myclaim-1
 | 
				
			||||||
 | 
					spec:
 | 
				
			||||||
 | 
					  accessModes:
 | 
				
			||||||
 | 
					    - ReadWriteOnce
 | 
				
			||||||
 | 
					  resources:
 | 
				
			||||||
 | 
					    requests:
 | 
				
			||||||
 | 
					      storage: 3
 | 
				
			||||||
							
								
								
									
										10
									
								
								examples/persistent-volumes/claims/claim-02.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								examples/persistent-volumes/claims/claim-02.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					kind: PersistentVolumeClaim
 | 
				
			||||||
 | 
					apiVersion: v1beta3
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: myclaim-2
 | 
				
			||||||
 | 
					spec:
 | 
				
			||||||
 | 
					  accessModes:
 | 
				
			||||||
 | 
					    - ReadWriteOnce
 | 
				
			||||||
 | 
					  resources:
 | 
				
			||||||
 | 
					    requests:
 | 
				
			||||||
 | 
					      storage: 8
 | 
				
			||||||
							
								
								
									
										17
									
								
								examples/persistent-volumes/claims/claim-03.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								examples/persistent-volumes/claims/claim-03.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "kind": "PersistentVolumeClaim",
 | 
				
			||||||
 | 
					    "apiVersion": "v1beta3",
 | 
				
			||||||
 | 
					    "metadata": {
 | 
				
			||||||
 | 
					        "name": "myclaim-3"
 | 
				
			||||||
 | 
					    }, "spec": {
 | 
				
			||||||
 | 
					        "accessModes": [
 | 
				
			||||||
 | 
					            "ReadWriteOnce",
 | 
				
			||||||
 | 
					            "ReadOnlyMany"
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "resources": {
 | 
				
			||||||
 | 
					            "requests": {
 | 
				
			||||||
 | 
					                "storage": "10G"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										69
									
								
								examples/persistent-volumes/simpletest/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								examples/persistent-volumes/simpletest/README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
				
			|||||||
 | 
					# How To Use Persistent Volumes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This guide assumes knowledge of Kubernetes fundamentals and that a user has a cluster up and running.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Create volumes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Persistent Volumes are intended for "network volumes", such as GCE Persistent Disks, NFS shares, and AWS EBS volumes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `HostPath` VolumeSource was included in the Persistent Volumes implementation for ease of testing.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					Create persistent volumes by posting them to the API server:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cluster/kubectl.sh create -f examples/persistent-volumes/volumes/local-01.yaml
 | 
				
			||||||
 | 
					cluster/kubectl.sh create -f examples/persistent-volumes/volumes/local-02.yaml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cluster/kubectl.sh get pv
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NAME                LABELS              CAPACITY            ACCESSMODES         STATUS              CLAIM
 | 
				
			||||||
 | 
					pv0001              map[]               10737418240         RWO                                     
 | 
				
			||||||
 | 
					pv0002              map[]               5368709120          RWO        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In the log:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I0302 10:20:45.663225    1920 persistent_volume_manager.go:115] Managing PersistentVolume[UID=b16e91d6-c0ef-11e4-8be4-80e6500a981e]
 | 
				
			||||||
 | 
					I0302 10:20:55.667945    1920 persistent_volume_manager.go:115] Managing PersistentVolume[UID=b41f4f0e-c0ef-11e4-8be4-80e6500a981e]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Create claims
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You must be in a namespace to create claims.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cluster/kubectl.sh create -f examples/persistent-volumes/claims/claim-01.yaml
 | 
				
			||||||
 | 
					cluster/kubectl.sh create -f examples/persistent-volumes/claims/claim-02.yaml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NAME                LABELS              STATUS              VOLUME
 | 
				
			||||||
 | 
					myclaim-1           map[]                                   
 | 
				
			||||||
 | 
					myclaim-2           map[]                                   
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Matching and binding
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PersistentVolumeClaim[UID=f4b3d283-c0ef-11e4-8be4-80e6500a981e] bound to PersistentVolume[UID=b16e91d6-c0ef-11e4-8be4-80e6500a981e]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cluster/kubectl.sh get pv
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NAME                LABELS              CAPACITY            ACCESSMODES         STATUS              CLAIM
 | 
				
			||||||
 | 
					pv0001              map[]               10737418240         RWO                                     myclaim-1 / f4b3d283-c0ef-11e4-8be4-80e6500a981e
 | 
				
			||||||
 | 
					pv0002              map[]               5368709120          RWO                                     myclaim-2 / f70da891-c0ef-11e4-8be4-80e6500a981e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cluster/kubectl.sh get pvc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NAME                LABELS              STATUS              VOLUME
 | 
				
			||||||
 | 
					myclaim-1           map[]                                   b16e91d6-c0ef-11e4-8be4-80e6500a981e
 | 
				
			||||||
 | 
					myclaim-2           map[]                                   b41f4f0e-c0ef-11e4-8be4-80e6500a981e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
							
								
								
									
										10
									
								
								examples/persistent-volumes/simpletest/namespace.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								examples/persistent-volumes/simpletest/namespace.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "kind": "Namespace",
 | 
				
			||||||
 | 
					    "apiVersion":"v1beta3",
 | 
				
			||||||
 | 
					    "metadata": {
 | 
				
			||||||
 | 
					        "name": "myns",
 | 
				
			||||||
 | 
					        "labels": {
 | 
				
			||||||
 | 
					            "name": "development"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								examples/persistent-volumes/simpletest/pod.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								examples/persistent-volumes/simpletest/pod.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					kind: Pod
 | 
				
			||||||
 | 
					apiVersion: v1beta3
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: mypod
 | 
				
			||||||
 | 
					spec:
 | 
				
			||||||
 | 
					  containers:
 | 
				
			||||||
 | 
					    - image: dockerfile/nginx
 | 
				
			||||||
 | 
					      name: myfrontend
 | 
				
			||||||
 | 
					      volumeMounts:
 | 
				
			||||||
 | 
					      - mountPath: "/var/www/html"
 | 
				
			||||||
 | 
					        name: mypd
 | 
				
			||||||
 | 
					  volumes:
 | 
				
			||||||
 | 
					    - name: mypd
 | 
				
			||||||
 | 
					      source:
 | 
				
			||||||
 | 
					        persistentVolumeClaim:
 | 
				
			||||||
 | 
					         accessMode: ReadWriteOnce
 | 
				
			||||||
 | 
					         claimRef:
 | 
				
			||||||
 | 
					           name: myclaim-1
 | 
				
			||||||
							
								
								
									
										10
									
								
								examples/persistent-volumes/volumes/gce.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								examples/persistent-volumes/volumes/gce.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					kind: PersistentVolume
 | 
				
			||||||
 | 
					apiVersion: v1beta3
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: pv0003
 | 
				
			||||||
 | 
					spec:
 | 
				
			||||||
 | 
					  capacity:
 | 
				
			||||||
 | 
					    storage: 10
 | 
				
			||||||
 | 
					  gcePersistentDisk:
 | 
				
			||||||
 | 
					    pdName: "abc123"
 | 
				
			||||||
 | 
					    fsType: "ext4"
 | 
				
			||||||
							
								
								
									
										11
									
								
								examples/persistent-volumes/volumes/local-01.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								examples/persistent-volumes/volumes/local-01.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					kind: PersistentVolume
 | 
				
			||||||
 | 
					apiVersion: v1beta3
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: pv0001
 | 
				
			||||||
 | 
					  labels:
 | 
				
			||||||
 | 
					    type: local
 | 
				
			||||||
 | 
					spec:
 | 
				
			||||||
 | 
					  capacity:
 | 
				
			||||||
 | 
					    storage: 10Gi
 | 
				
			||||||
 | 
					  hostPath:
 | 
				
			||||||
 | 
					    path: "/tmp/data01"
 | 
				
			||||||
							
								
								
									
										11
									
								
								examples/persistent-volumes/volumes/local-02.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								examples/persistent-volumes/volumes/local-02.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					kind: PersistentVolume
 | 
				
			||||||
 | 
					apiVersion: v1beta3
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: pv0002
 | 
				
			||||||
 | 
					  labels:
 | 
				
			||||||
 | 
					    type: local
 | 
				
			||||||
 | 
					spec:
 | 
				
			||||||
 | 
					  capacity:
 | 
				
			||||||
 | 
					    storage: 5Gi
 | 
				
			||||||
 | 
					  hostPath:
 | 
				
			||||||
 | 
					    path: "/tmp/data02"
 | 
				
			||||||
@@ -529,6 +529,49 @@ __EOF__
 | 
				
			|||||||
  # Post-condition: no replication controller is running
 | 
					  # Post-condition: no replication controller is running
 | 
				
			||||||
  kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
 | 
					  kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ######################
 | 
				
			||||||
 | 
					  # Persistent Volumes #
 | 
				
			||||||
 | 
					  ######################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ### Create and delete persistent volume examples
 | 
				
			||||||
 | 
					  # Pre-condition: no persistent volumes currently exist
 | 
				
			||||||
 | 
					  kube::test::get_object_assert pv "{{range.items}}{{.$id_field}}:{{end}}" ''
 | 
				
			||||||
 | 
					  # Command
 | 
				
			||||||
 | 
					  kubectl create -f examples/persistent-volumes/volumes/local-01.yaml "${kube_flags[@]}"
 | 
				
			||||||
 | 
					  kube::test::get_object_assert pv "{{range.items}}{{.$id_field}}:{{end}}" 'pv0001:'
 | 
				
			||||||
 | 
					  kubectl delete pv pv0001 "${kube_flags[@]}"
 | 
				
			||||||
 | 
					  kubectl create -f examples/persistent-volumes/volumes/local-02.yaml "${kube_flags[@]}"
 | 
				
			||||||
 | 
					  kube::test::get_object_assert pv "{{range.items}}{{.$id_field}}:{{end}}" 'pv0002:'
 | 
				
			||||||
 | 
					  kubectl delete pv pv0002 "${kube_flags[@]}"
 | 
				
			||||||
 | 
					  kubectl create -f examples/persistent-volumes/volumes/gce.yaml "${kube_flags[@]}"
 | 
				
			||||||
 | 
					  kube::test::get_object_assert pv "{{range.items}}{{.$id_field}}:{{end}}" 'pv0003:'
 | 
				
			||||||
 | 
					  kubectl delete pv pv0003 "${kube_flags[@]}"
 | 
				
			||||||
 | 
					  # Post-condition: no PVs
 | 
				
			||||||
 | 
					  kube::test::get_object_assert pv "{{range.items}}{{.$id_field}}:{{end}}" ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ############################
 | 
				
			||||||
 | 
					  # Persistent Volume Claims #
 | 
				
			||||||
 | 
					  ############################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ### Create and delete persistent volume claim examples
 | 
				
			||||||
 | 
					  # Pre-condition: no persistent volume claims currently exist
 | 
				
			||||||
 | 
					  kube::test::get_object_assert pvc "{{range.items}}{{.$id_field}}:{{end}}" ''
 | 
				
			||||||
 | 
					  # Command
 | 
				
			||||||
 | 
					  kubectl create -f examples/persistent-volumes/claims/claim-01.yaml "${kube_flags[@]}"
 | 
				
			||||||
 | 
					  kube::test::get_object_assert pvc "{{range.items}}{{.$id_field}}:{{end}}" 'myclaim-1:'
 | 
				
			||||||
 | 
					  kubectl delete pvc myclaim-1 "${kube_flags[@]}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  kubectl create -f examples/persistent-volumes/claims/claim-02.yaml "${kube_flags[@]}"
 | 
				
			||||||
 | 
					  kube::test::get_object_assert pvc "{{range.items}}{{.$id_field}}:{{end}}" 'myclaim-2:'
 | 
				
			||||||
 | 
					  kubectl delete pvc myclaim-2 "${kube_flags[@]}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  kubectl create -f examples/persistent-volumes/claims/claim-03.json "${kube_flags[@]}"
 | 
				
			||||||
 | 
					  kube::test::get_object_assert pvc "{{range.items}}{{.$id_field}}:{{end}}" 'myclaim-3:'
 | 
				
			||||||
 | 
					  kubectl delete pvc myclaim-3 "${kube_flags[@]}"
 | 
				
			||||||
 | 
					  # Post-condition: no PVCs
 | 
				
			||||||
 | 
					  kube::test::get_object_assert pvc "{{range.items}}{{.$id_field}}:{{end}}" ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #########
 | 
					  #########
 | 
				
			||||||
  # Nodes #
 | 
					  # Nodes #
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -224,8 +224,9 @@ type PersistentVolumeSpec struct {
 | 
				
			|||||||
	// Resources represents the actual resources of the volume
 | 
						// Resources represents the actual resources of the volume
 | 
				
			||||||
	Capacity ResourceList `json:"capacity`
 | 
						Capacity ResourceList `json:"capacity`
 | 
				
			||||||
	// Source represents the location and type of a volume to mount.
 | 
						// Source represents the location and type of a volume to mount.
 | 
				
			||||||
	// AccessModeTypes are inferred from the Source.
 | 
					 | 
				
			||||||
	PersistentVolumeSource `json:",inline"`
 | 
						PersistentVolumeSource `json:",inline"`
 | 
				
			||||||
 | 
						// AccessModes contains all ways the volume can be mounted
 | 
				
			||||||
 | 
						AccessModes []AccessModeType `json:"accessModes,omitempty"`
 | 
				
			||||||
	// holds the binding reference to a PersistentVolumeClaim
 | 
						// holds the binding reference to a PersistentVolumeClaim
 | 
				
			||||||
	ClaimRef *ObjectReference `json:"claimRef,omitempty"`
 | 
						ClaimRef *ObjectReference `json:"claimRef,omitempty"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -139,8 +139,9 @@ type PersistentVolumeSpec struct {
 | 
				
			|||||||
	// Resources represents the actual resources of the volume
 | 
						// Resources represents the actual resources of the volume
 | 
				
			||||||
	Capacity ResourceList `json:"capacity,omitempty" description:"a description of the persistent volume's resources and capacity"`
 | 
						Capacity ResourceList `json:"capacity,omitempty" description:"a description of the persistent volume's resources and capacity"`
 | 
				
			||||||
	// Source represents the location and type of a volume to mount.
 | 
						// Source represents the location and type of a volume to mount.
 | 
				
			||||||
	// AccessModeTypes are inferred from the Source.
 | 
					 | 
				
			||||||
	PersistentVolumeSource `json:",inline" description:"the actual volume backing the persistent volume"`
 | 
						PersistentVolumeSource `json:",inline" description:"the actual volume backing the persistent volume"`
 | 
				
			||||||
 | 
						// AccessModes contains all ways the volume can be mounted
 | 
				
			||||||
 | 
						AccessModes []AccessModeType `json:"accessModes,omitempty" description:"all ways the volume can be mounted"`
 | 
				
			||||||
	// holds the binding reference to a PersistentVolumeClaim
 | 
						// holds the binding reference to a PersistentVolumeClaim
 | 
				
			||||||
	ClaimRef *ObjectReference `json:"claimRef,omitempty" description:"the binding reference to a persistent volume claim"`
 | 
						ClaimRef *ObjectReference `json:"claimRef,omitempty" description:"the binding reference to a persistent volume claim"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -108,8 +108,9 @@ type PersistentVolumeSpec struct {
 | 
				
			|||||||
	// Resources represents the actual resources of the volume
 | 
						// Resources represents the actual resources of the volume
 | 
				
			||||||
	Capacity ResourceList `json:"capacity,omitempty" description:"a description of the persistent volume's resources and capacity"`
 | 
						Capacity ResourceList `json:"capacity,omitempty" description:"a description of the persistent volume's resources and capacity"`
 | 
				
			||||||
	// Source represents the location and type of a volume to mount.
 | 
						// Source represents the location and type of a volume to mount.
 | 
				
			||||||
	// AccessModeTypes are inferred from the Source.
 | 
					 | 
				
			||||||
	PersistentVolumeSource `json:",inline" description:"the actual volume backing the persistent volume"`
 | 
						PersistentVolumeSource `json:",inline" description:"the actual volume backing the persistent volume"`
 | 
				
			||||||
 | 
						// AccessModes contains all ways the volume can be mounted
 | 
				
			||||||
 | 
						AccessModes []AccessModeType `json:"accessModes,omitempty" description:"all ways the volume can be mounted"`
 | 
				
			||||||
	// holds the binding reference to a PersistentVolumeClaim
 | 
						// holds the binding reference to a PersistentVolumeClaim
 | 
				
			||||||
	ClaimRef *ObjectReference `json:"claimRef,omitempty" description:"the binding reference to a persistent volume claim"`
 | 
						ClaimRef *ObjectReference `json:"claimRef,omitempty" description:"the binding reference to a persistent volume claim"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -241,8 +241,9 @@ type PersistentVolumeSpec struct {
 | 
				
			|||||||
	// Resources represents the actual resources of the volume
 | 
						// Resources represents the actual resources of the volume
 | 
				
			||||||
	Capacity ResourceList `json:"capacity,omitempty" description:"a description of the persistent volume's resources and capacity"`
 | 
						Capacity ResourceList `json:"capacity,omitempty" description:"a description of the persistent volume's resources and capacity"`
 | 
				
			||||||
	// Source represents the location and type of a volume to mount.
 | 
						// Source represents the location and type of a volume to mount.
 | 
				
			||||||
	// AccessModeTypes are inferred from the Source.
 | 
					 | 
				
			||||||
	PersistentVolumeSource `json:",inline" description:"the actual volume backing the persistent volume"`
 | 
						PersistentVolumeSource `json:",inline" description:"the actual volume backing the persistent volume"`
 | 
				
			||||||
 | 
						// AccessModes contains all ways the volume can be mounted
 | 
				
			||||||
 | 
						AccessModes []AccessModeType `json:"accessModes,omitempty" description:"all ways the volume can be mounted"`
 | 
				
			||||||
	// holds the binding reference to a PersistentVolumeClaim
 | 
						// holds the binding reference to a PersistentVolumeClaim
 | 
				
			||||||
	ClaimRef *ObjectReference `json:"claimRef,omitempty" description:"the binding reference to a persistent volume claim"`
 | 
						ClaimRef *ObjectReference `json:"claimRef,omitempty" description:"the binding reference to a persistent volume claim"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -364,11 +364,12 @@ func validateNFS(nfs *api.NFSVolumeSource) errs.ValidationErrorList {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ValidatePersistentVolumeName(name string, prefix bool) (bool, string) {
 | 
					func ValidatePersistentVolumeName(name string, prefix bool) (bool, string) {
 | 
				
			||||||
	return util.IsDNS1123Label(name), name
 | 
						return nameIsDNSSubdomain(name, prefix)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ValidatePersistentVolume(pv *api.PersistentVolume) errs.ValidationErrorList {
 | 
					func ValidatePersistentVolume(pv *api.PersistentVolume) errs.ValidationErrorList {
 | 
				
			||||||
	allErrs := ValidateObjectMeta(&pv.ObjectMeta, false, ValidatePersistentVolumeName)
 | 
						allErrs := errs.ValidationErrorList{}
 | 
				
			||||||
 | 
						allErrs = append(allErrs, ValidateObjectMeta(&pv.ObjectMeta, false, ValidatePersistentVolumeName).Prefix("metadata")...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(pv.Spec.Capacity) == 0 {
 | 
						if len(pv.Spec.Capacity) == 0 {
 | 
				
			||||||
		allErrs = append(allErrs, errs.NewFieldRequired("persistentVolume.Capacity"))
 | 
							allErrs = append(allErrs, errs.NewFieldRequired("persistentVolume.Capacity"))
 | 
				
			||||||
@@ -393,6 +394,27 @@ func ValidatePersistentVolume(pv *api.PersistentVolume) errs.ValidationErrorList
 | 
				
			|||||||
	return allErrs
 | 
						return allErrs
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ValidatePersistentVolumeUpdate tests to see if the update is legal for an end user to make.
 | 
				
			||||||
 | 
					// newPv is updated with fields that cannot be changed.
 | 
				
			||||||
 | 
					func ValidatePersistentVolumeUpdate(newPv, oldPv *api.PersistentVolume) errs.ValidationErrorList {
 | 
				
			||||||
 | 
						allErrs := errs.ValidationErrorList{}
 | 
				
			||||||
 | 
						allErrs = ValidatePersistentVolume(newPv)
 | 
				
			||||||
 | 
						newPv.Status = oldPv.Status
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ValidatePersistentVolumeStatusUpdate tests to see if the status update is legal for an end user to make.
 | 
				
			||||||
 | 
					// newPv is updated with fields that cannot be changed.
 | 
				
			||||||
 | 
					func ValidatePersistentVolumeStatusUpdate(newPv, oldPv *api.PersistentVolume) errs.ValidationErrorList {
 | 
				
			||||||
 | 
						allErrs := errs.ValidationErrorList{}
 | 
				
			||||||
 | 
						allErrs = append(allErrs, ValidateObjectMetaUpdate(&oldPv.ObjectMeta, &newPv.ObjectMeta).Prefix("metadata")...)
 | 
				
			||||||
 | 
						if newPv.ResourceVersion == "" {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, fmt.Errorf("ResourceVersion must be specified"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						newPv.Spec = oldPv.Spec
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ValidatePersistentVolumeClaim(pvc *api.PersistentVolumeClaim) errs.ValidationErrorList {
 | 
					func ValidatePersistentVolumeClaim(pvc *api.PersistentVolumeClaim) errs.ValidationErrorList {
 | 
				
			||||||
	allErrs := ValidateObjectMeta(&pvc.ObjectMeta, true, ValidatePersistentVolumeName)
 | 
						allErrs := ValidateObjectMeta(&pvc.ObjectMeta, true, ValidatePersistentVolumeName)
 | 
				
			||||||
	if len(pvc.Spec.AccessModes) == 0 {
 | 
						if len(pvc.Spec.AccessModes) == 0 {
 | 
				
			||||||
@@ -404,6 +426,23 @@ func ValidatePersistentVolumeClaim(pvc *api.PersistentVolumeClaim) errs.Validati
 | 
				
			|||||||
	return allErrs
 | 
						return allErrs
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ValidatePersistentVolumeClaimUpdate(newPvc, oldPvc *api.PersistentVolumeClaim) errs.ValidationErrorList {
 | 
				
			||||||
 | 
						allErrs := errs.ValidationErrorList{}
 | 
				
			||||||
 | 
						allErrs = ValidatePersistentVolumeClaim(newPvc)
 | 
				
			||||||
 | 
						newPvc.Status = oldPvc.Status
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ValidatePersistentVolumeClaimStatusUpdate(newPvc, oldPvc *api.PersistentVolumeClaim) errs.ValidationErrorList {
 | 
				
			||||||
 | 
						allErrs := errs.ValidationErrorList{}
 | 
				
			||||||
 | 
						allErrs = append(allErrs, ValidateObjectMetaUpdate(&oldPvc.ObjectMeta, &newPvc.ObjectMeta).Prefix("metadata")...)
 | 
				
			||||||
 | 
						if newPvc.ResourceVersion == "" {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, fmt.Errorf("ResourceVersion must be specified"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						newPvc.Spec = oldPvc.Spec
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var supportedPortProtocols = util.NewStringSet(string(api.ProtocolTCP), string(api.ProtocolUDP))
 | 
					var supportedPortProtocols = util.NewStringSet(string(api.ProtocolTCP), string(api.ProtocolUDP))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func validatePorts(ports []api.ContainerPort) errs.ValidationErrorList {
 | 
					func validatePorts(ports []api.ContainerPort) errs.ValidationErrorList {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,6 +41,8 @@ type Interface interface {
 | 
				
			|||||||
	ResourceQuotasNamespacer
 | 
						ResourceQuotasNamespacer
 | 
				
			||||||
	SecretsNamespacer
 | 
						SecretsNamespacer
 | 
				
			||||||
	NamespacesInterface
 | 
						NamespacesInterface
 | 
				
			||||||
 | 
						PersistentVolumesInterface
 | 
				
			||||||
 | 
						PersistentVolumeClaimsNamespacer
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *Client) ReplicationControllers(namespace string) ReplicationControllerInterface {
 | 
					func (c *Client) ReplicationControllers(namespace string) ReplicationControllerInterface {
 | 
				
			||||||
@@ -66,7 +68,6 @@ func (c *Client) Pods(namespace string) PodInterface {
 | 
				
			|||||||
func (c *Client) Services(namespace string) ServiceInterface {
 | 
					func (c *Client) Services(namespace string) ServiceInterface {
 | 
				
			||||||
	return newServices(c, namespace)
 | 
						return newServices(c, namespace)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Client) LimitRanges(namespace string) LimitRangeInterface {
 | 
					func (c *Client) LimitRanges(namespace string) LimitRangeInterface {
 | 
				
			||||||
	return newLimitRanges(c, namespace)
 | 
						return newLimitRanges(c, namespace)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -83,6 +84,14 @@ func (c *Client) Namespaces() NamespaceInterface {
 | 
				
			|||||||
	return newNamespaces(c)
 | 
						return newNamespaces(c)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) PersistentVolumes() PersistentVolumeInterface {
 | 
				
			||||||
 | 
						return newPersistentVolumes(c)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) PersistentVolumeClaims(namespace string) PersistentVolumeClaimInterface {
 | 
				
			||||||
 | 
						return newPersistentVolumeClaims(c, namespace)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// VersionInterface has a method to retrieve the server version.
 | 
					// VersionInterface has a method to retrieve the server version.
 | 
				
			||||||
type VersionInterface interface {
 | 
					type VersionInterface interface {
 | 
				
			||||||
	ServerVersion() (*version.Info, error)
 | 
						ServerVersion() (*version.Info, error)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,6 +51,10 @@ type Fake struct {
 | 
				
			|||||||
	Secret                    api.Secret
 | 
						Secret                    api.Secret
 | 
				
			||||||
	Err                       error
 | 
						Err                       error
 | 
				
			||||||
	Watch                     watch.Interface
 | 
						Watch                     watch.Interface
 | 
				
			||||||
 | 
						PersistentVolume          api.PersistentVolume
 | 
				
			||||||
 | 
						PersistentVolumesList     api.PersistentVolumeList
 | 
				
			||||||
 | 
						PersistentVolumeClaim     api.PersistentVolumeClaim
 | 
				
			||||||
 | 
						PersistentVolumeClaimList api.PersistentVolumeClaimList
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *Fake) LimitRanges(namespace string) LimitRangeInterface {
 | 
					func (c *Fake) LimitRanges(namespace string) LimitRangeInterface {
 | 
				
			||||||
@@ -81,6 +85,14 @@ func (c *Fake) Pods(namespace string) PodInterface {
 | 
				
			|||||||
	return &FakePods{Fake: c, Namespace: namespace}
 | 
						return &FakePods{Fake: c, Namespace: namespace}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Fake) PersistentVolumes() PersistentVolumeInterface {
 | 
				
			||||||
 | 
						return &FakePersistentVolumes{Fake: c}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Fake) PersistentVolumeClaims(namespace string) PersistentVolumeClaimInterface {
 | 
				
			||||||
 | 
						return &FakePersistentVolumeClaims{Fake: c, Namespace: namespace}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *Fake) Services(namespace string) ServiceInterface {
 | 
					func (c *Fake) Services(namespace string) ServiceInterface {
 | 
				
			||||||
	return &FakeServices{Fake: c, Namespace: namespace}
 | 
						return &FakeServices{Fake: c, Namespace: namespace}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										58
									
								
								pkg/client/fake_persistent_volume_claims.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								pkg/client/fake_persistent_volume_claims.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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 client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type FakePersistentVolumeClaims struct {
 | 
				
			||||||
 | 
						Fake      *Fake
 | 
				
			||||||
 | 
						Namespace string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *FakePersistentVolumeClaims) List(labels labels.Selector, field fields.Selector) (*api.PersistentVolumeClaimList, error) {
 | 
				
			||||||
 | 
						c.Fake.Actions = append(c.Fake.Actions, FakeAction{Action: "list-persistentVolumeClaims"})
 | 
				
			||||||
 | 
						return api.Scheme.CopyOrDie(&c.Fake.PersistentVolumeClaimList).(*api.PersistentVolumeClaimList), c.Fake.Err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *FakePersistentVolumeClaims) Get(name string) (*api.PersistentVolumeClaim, error) {
 | 
				
			||||||
 | 
						c.Fake.Actions = append(c.Fake.Actions, FakeAction{Action: "get-persistentVolumeClaim", Value: name})
 | 
				
			||||||
 | 
						return api.Scheme.CopyOrDie(&c.Fake.PersistentVolumeClaim).(*api.PersistentVolumeClaim), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *FakePersistentVolumeClaims) Delete(name string) error {
 | 
				
			||||||
 | 
						c.Fake.Actions = append(c.Fake.Actions, FakeAction{Action: "delete-persistentVolumeClaim", Value: name})
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *FakePersistentVolumeClaims) Create(persistentvolumeclaim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error) {
 | 
				
			||||||
 | 
						c.Fake.Actions = append(c.Fake.Actions, FakeAction{Action: "create-persistentVolumeClaim"})
 | 
				
			||||||
 | 
						return &api.PersistentVolumeClaim{}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *FakePersistentVolumeClaims) Update(persistentvolumeclaim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error) {
 | 
				
			||||||
 | 
						c.Fake.Actions = append(c.Fake.Actions, FakeAction{Action: "update-persistentVolumeClaim", Value: persistentvolumeclaim.Name})
 | 
				
			||||||
 | 
						return &api.PersistentVolumeClaim{}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *FakePersistentVolumeClaims) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) {
 | 
				
			||||||
 | 
						return c.Fake.Watch, c.Fake.Err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										58
									
								
								pkg/client/fake_persistent_volumes.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								pkg/client/fake_persistent_volumes.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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 client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type FakePersistentVolumes struct {
 | 
				
			||||||
 | 
						Fake *Fake
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *FakePersistentVolumes) List(labels labels.Selector, field fields.Selector) (*api.PersistentVolumeList, error) {
 | 
				
			||||||
 | 
						c.Fake.Actions = append(c.Fake.Actions, FakeAction{Action: "list-persistentVolumes"})
 | 
				
			||||||
 | 
						return api.Scheme.CopyOrDie(&c.Fake.PersistentVolumesList).(*api.PersistentVolumeList), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *FakePersistentVolumes) Get(name string) (*api.PersistentVolume, error) {
 | 
				
			||||||
 | 
						c.Fake.Actions = append(c.Fake.Actions, FakeAction{Action: "get-persistentVolume", Value: name})
 | 
				
			||||||
 | 
						return api.Scheme.CopyOrDie(&c.Fake.PersistentVolume).(*api.PersistentVolume), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *FakePersistentVolumes) Delete(name string) error {
 | 
				
			||||||
 | 
						c.Fake.Actions = append(c.Fake.Actions, FakeAction{Action: "delete-persistentVolume", Value: name})
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *FakePersistentVolumes) Create(persistentvolume *api.PersistentVolume) (*api.PersistentVolume, error) {
 | 
				
			||||||
 | 
						c.Fake.Actions = append(c.Fake.Actions, FakeAction{Action: "create-persistentVolume"})
 | 
				
			||||||
 | 
						return &api.PersistentVolume{}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *FakePersistentVolumes) Update(persistentvolume *api.PersistentVolume) (*api.PersistentVolume, error) {
 | 
				
			||||||
 | 
						c.Fake.Actions = append(c.Fake.Actions, FakeAction{Action: "update-persistentVolume", Value: persistentvolume.Name})
 | 
				
			||||||
 | 
						return &api.PersistentVolume{}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *FakePersistentVolumes) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) {
 | 
				
			||||||
 | 
						c.Fake.Actions = append(c.Fake.Actions, FakeAction{Action: "watch-persistentVolumes", Value: resourceVersion})
 | 
				
			||||||
 | 
						return c.Fake.Watch, c.Fake.Err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										103
									
								
								pkg/client/persistentvolumeclaim.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								pkg/client/persistentvolumeclaim.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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 client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PersistentVolumeClaimsNamespacer has methods to work with PersistentVolumeClaim resources in a namespace
 | 
				
			||||||
 | 
					type PersistentVolumeClaimsNamespacer interface {
 | 
				
			||||||
 | 
						PersistentVolumeClaims(namespace string) PersistentVolumeClaimInterface
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PersistentVolumeClaimInterface has methods to work with PersistentVolumeClaim resources.
 | 
				
			||||||
 | 
					type PersistentVolumeClaimInterface interface {
 | 
				
			||||||
 | 
						List(label labels.Selector, field fields.Selector) (*api.PersistentVolumeClaimList, error)
 | 
				
			||||||
 | 
						Get(name string) (*api.PersistentVolumeClaim, error)
 | 
				
			||||||
 | 
						Create(claim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error)
 | 
				
			||||||
 | 
						Update(claim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error)
 | 
				
			||||||
 | 
						Delete(name string) error
 | 
				
			||||||
 | 
						Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// persistentVolumeClaims implements PersistentVolumeClaimsNamespacer interface
 | 
				
			||||||
 | 
					type persistentVolumeClaims struct {
 | 
				
			||||||
 | 
						client    *Client
 | 
				
			||||||
 | 
						namespace string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// newPersistentVolumeClaims returns a PodsClient
 | 
				
			||||||
 | 
					func newPersistentVolumeClaims(c *Client, namespace string) *persistentVolumeClaims {
 | 
				
			||||||
 | 
						return &persistentVolumeClaims{c, namespace}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *persistentVolumeClaims) List(label labels.Selector, field fields.Selector) (result *api.PersistentVolumeClaimList, err error) {
 | 
				
			||||||
 | 
						result = &api.PersistentVolumeClaimList{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = c.client.Get().
 | 
				
			||||||
 | 
							Namespace(c.namespace).
 | 
				
			||||||
 | 
							Resource("persistentVolumeClaims").
 | 
				
			||||||
 | 
							LabelsSelectorParam(api.LabelSelectorQueryParam(c.client.APIVersion()), label).
 | 
				
			||||||
 | 
							FieldsSelectorParam(api.FieldSelectorQueryParam(c.client.APIVersion()), field).
 | 
				
			||||||
 | 
							Do().
 | 
				
			||||||
 | 
							Into(result)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return result, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *persistentVolumeClaims) Get(name string) (result *api.PersistentVolumeClaim, err error) {
 | 
				
			||||||
 | 
						result = &api.PersistentVolumeClaim{}
 | 
				
			||||||
 | 
						err = c.client.Get().Namespace(c.namespace).Resource("persistentVolumeClaims").Name(name).Do().Into(result)
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *persistentVolumeClaims) Create(claim *api.PersistentVolumeClaim) (result *api.PersistentVolumeClaim, err error) {
 | 
				
			||||||
 | 
						result = &api.PersistentVolumeClaim{}
 | 
				
			||||||
 | 
						err = c.client.Post().Namespace(c.namespace).Resource("persistentVolumeClaims").Body(claim).Do().Into(result)
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *persistentVolumeClaims) Update(claim *api.PersistentVolumeClaim) (result *api.PersistentVolumeClaim, err error) {
 | 
				
			||||||
 | 
						result = &api.PersistentVolumeClaim{}
 | 
				
			||||||
 | 
						if len(claim.ResourceVersion) == 0 {
 | 
				
			||||||
 | 
							err = fmt.Errorf("invalid update object, missing resource version: %v", claim)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = c.client.Put().Namespace(c.namespace).Resource("persistentVolumeClaims").Name(claim.Name).Body(claim).Do().Into(result)
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *persistentVolumeClaims) Delete(name string) error {
 | 
				
			||||||
 | 
						return c.client.Delete().Namespace(c.namespace).Resource("persistentVolumeClaims").Name(name).Do().Error()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *persistentVolumeClaims) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) {
 | 
				
			||||||
 | 
						return c.client.Get().
 | 
				
			||||||
 | 
							Prefix("watch").
 | 
				
			||||||
 | 
							Namespace(c.namespace).
 | 
				
			||||||
 | 
							Resource("persistentVolumeClaims").
 | 
				
			||||||
 | 
							Param("resourceVersion", resourceVersion).
 | 
				
			||||||
 | 
							LabelsSelectorParam(api.LabelSelectorQueryParam(c.client.APIVersion()), label).
 | 
				
			||||||
 | 
							FieldsSelectorParam(api.FieldSelectorQueryParam(c.client.APIVersion()), field).
 | 
				
			||||||
 | 
							Watch()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										97
									
								
								pkg/client/persistentvolumes.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								pkg/client/persistentvolumes.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,97 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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 client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type PersistentVolumesInterface interface {
 | 
				
			||||||
 | 
						PersistentVolumes() PersistentVolumeInterface
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PersistentVolumeInterface has methods to work with PersistentVolume resources.
 | 
				
			||||||
 | 
					type PersistentVolumeInterface interface {
 | 
				
			||||||
 | 
						List(label labels.Selector, field fields.Selector) (*api.PersistentVolumeList, error)
 | 
				
			||||||
 | 
						Get(name string) (*api.PersistentVolume, error)
 | 
				
			||||||
 | 
						Create(volume *api.PersistentVolume) (*api.PersistentVolume, error)
 | 
				
			||||||
 | 
						Update(volume *api.PersistentVolume) (*api.PersistentVolume, error)
 | 
				
			||||||
 | 
						Delete(name string) error
 | 
				
			||||||
 | 
						Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// persistentVolumes implements PersistentVolumesInterface
 | 
				
			||||||
 | 
					type persistentVolumes struct {
 | 
				
			||||||
 | 
						client *Client
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newPersistentVolumes(c *Client) *persistentVolumes {
 | 
				
			||||||
 | 
						return &persistentVolumes{c}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *persistentVolumes) List(label labels.Selector, field fields.Selector) (result *api.PersistentVolumeList, err error) {
 | 
				
			||||||
 | 
						result = &api.PersistentVolumeList{}
 | 
				
			||||||
 | 
						err = c.client.Get().
 | 
				
			||||||
 | 
							Resource("persistentVolumes").
 | 
				
			||||||
 | 
							LabelsSelectorParam(api.LabelSelectorQueryParam(c.client.APIVersion()), label).
 | 
				
			||||||
 | 
							FieldsSelectorParam(api.FieldSelectorQueryParam(c.client.APIVersion()), field).
 | 
				
			||||||
 | 
							Do().
 | 
				
			||||||
 | 
							Into(result)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return result, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *persistentVolumes) Get(name string) (result *api.PersistentVolume, err error) {
 | 
				
			||||||
 | 
						result = &api.PersistentVolume{}
 | 
				
			||||||
 | 
						err = c.client.Get().Resource("persistentVolumes").Name(name).Do().Into(result)
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *persistentVolumes) Create(volume *api.PersistentVolume) (result *api.PersistentVolume, err error) {
 | 
				
			||||||
 | 
						result = &api.PersistentVolume{}
 | 
				
			||||||
 | 
						err = c.client.Post().Resource("persistentVolumes").Body(volume).Do().Into(result)
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *persistentVolumes) Update(volume *api.PersistentVolume) (result *api.PersistentVolume, err error) {
 | 
				
			||||||
 | 
						result = &api.PersistentVolume{}
 | 
				
			||||||
 | 
						if len(volume.ResourceVersion) == 0 {
 | 
				
			||||||
 | 
							err = fmt.Errorf("invalid update object, missing resource version: %v", volume)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = c.client.Put().Resource("persistentVolumes").Name(volume.Name).Body(volume).Do().Into(result)
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *persistentVolumes) Delete(name string) error {
 | 
				
			||||||
 | 
						return c.client.Delete().Resource("persistentVolumes").Name(name).Do().Error()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *persistentVolumes) Watch(label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) {
 | 
				
			||||||
 | 
						return c.client.Get().
 | 
				
			||||||
 | 
							Prefix("watch").
 | 
				
			||||||
 | 
							Resource("persistentVolumes").
 | 
				
			||||||
 | 
							Param("resourceVersion", resourceVersion).
 | 
				
			||||||
 | 
							LabelsSelectorParam(api.LabelSelectorQueryParam(c.client.APIVersion()), label).
 | 
				
			||||||
 | 
							FieldsSelectorParam(api.FieldSelectorQueryParam(c.client.APIVersion()), field).
 | 
				
			||||||
 | 
							Watch()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -68,6 +68,10 @@ func DescriberFor(kind string, c *client.Client) (Describer, bool) {
 | 
				
			|||||||
		return &ReplicationControllerDescriber{c}, true
 | 
							return &ReplicationControllerDescriber{c}, true
 | 
				
			||||||
	case "Service":
 | 
						case "Service":
 | 
				
			||||||
		return &ServiceDescriber{c}, true
 | 
							return &ServiceDescriber{c}, true
 | 
				
			||||||
 | 
						case "PersistentVolume":
 | 
				
			||||||
 | 
							return &PersistentVolumeDescriber{c}, true
 | 
				
			||||||
 | 
						case "PersistentVolumeClaim":
 | 
				
			||||||
 | 
							return &PersistentVolumeClaimDescriber{c}, true
 | 
				
			||||||
	case "Minion", "Node":
 | 
						case "Minion", "Node":
 | 
				
			||||||
		return &NodeDescriber{c}, true
 | 
							return &NodeDescriber{c}, true
 | 
				
			||||||
	case "LimitRange":
 | 
						case "LimitRange":
 | 
				
			||||||
@@ -269,6 +273,49 @@ func describePod(pod *api.Pod, rcs []api.ReplicationController, events *api.Even
 | 
				
			|||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type PersistentVolumeDescriber struct {
 | 
				
			||||||
 | 
						client.Interface
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (d *PersistentVolumeDescriber) Describe(namespace, name string) (string, error) {
 | 
				
			||||||
 | 
						c := d.PersistentVolumes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pv, err := c.Get(name)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return tabbedString(func(out io.Writer) error {
 | 
				
			||||||
 | 
							fmt.Fprintf(out, "Name:\t%s\n", pv.Name)
 | 
				
			||||||
 | 
							fmt.Fprintf(out, "Labels:\t%s\n", formatLabels(pv.Labels))
 | 
				
			||||||
 | 
							fmt.Fprintf(out, "Status:\t%d\n", pv.Status.Phase)
 | 
				
			||||||
 | 
							fmt.Fprintf(out, "Claim:\t%d\n", pv.Spec.ClaimRef.UID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type PersistentVolumeClaimDescriber struct {
 | 
				
			||||||
 | 
						client.Interface
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (d *PersistentVolumeClaimDescriber) Describe(namespace, name string) (string, error) {
 | 
				
			||||||
 | 
						c := d.PersistentVolumeClaims(namespace)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						psd, err := c.Get(name)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return tabbedString(func(out io.Writer) error {
 | 
				
			||||||
 | 
							fmt.Fprintf(out, "Name:\t%s\n", psd.Name)
 | 
				
			||||||
 | 
							fmt.Fprintf(out, "Status:\t%d\n", psd.Status.Phase)
 | 
				
			||||||
 | 
							fmt.Fprintf(out, "Volume:\t%d\n", psd.Status.VolumeRef.UID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func describeContainers(containers []api.ContainerStatus, out io.Writer) {
 | 
					func describeContainers(containers []api.ContainerStatus, out io.Writer) {
 | 
				
			||||||
	for _, container := range containers {
 | 
						for _, container := range containers {
 | 
				
			||||||
		fmt.Fprintf(out, "  %v:\n", container.Name)
 | 
							fmt.Fprintf(out, "  %v:\n", container.Name)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -107,6 +107,8 @@ func expandResourceShortcut(resource string) string {
 | 
				
			|||||||
		"ev":     "events",
 | 
							"ev":     "events",
 | 
				
			||||||
		"limits": "limitRanges",
 | 
							"limits": "limitRanges",
 | 
				
			||||||
		"quota":  "resourceQuotas",
 | 
							"quota":  "resourceQuotas",
 | 
				
			||||||
 | 
							"pv":     "persistentVolumes",
 | 
				
			||||||
 | 
							"pvc":    "persistentVolumeClaims",
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if expanded, ok := shortForms[resource]; ok {
 | 
						if expanded, ok := shortForms[resource]; ok {
 | 
				
			||||||
		return expanded
 | 
							return expanded
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,6 +32,7 @@ import (
 | 
				
			|||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
				
			||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
 | 
				
			||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/volume"
 | 
				
			||||||
	"github.com/docker/docker/pkg/units"
 | 
						"github.com/docker/docker/pkg/units"
 | 
				
			||||||
	"github.com/ghodss/yaml"
 | 
						"github.com/ghodss/yaml"
 | 
				
			||||||
	"github.com/golang/glog"
 | 
						"github.com/golang/glog"
 | 
				
			||||||
@@ -237,6 +238,8 @@ var limitRangeColumns = []string{"NAME"}
 | 
				
			|||||||
var resourceQuotaColumns = []string{"NAME"}
 | 
					var resourceQuotaColumns = []string{"NAME"}
 | 
				
			||||||
var namespaceColumns = []string{"NAME", "LABELS", "STATUS"}
 | 
					var namespaceColumns = []string{"NAME", "LABELS", "STATUS"}
 | 
				
			||||||
var secretColumns = []string{"NAME", "DATA"}
 | 
					var secretColumns = []string{"NAME", "DATA"}
 | 
				
			||||||
 | 
					var persistentVolumeColumns = []string{"NAME", "LABELS", "CAPACITY", "ACCESSMODES", "STATUS", "CLAIM"}
 | 
				
			||||||
 | 
					var persistentVolumeClaimColumns = []string{"NAME", "LABELS", "STATUS", "VOLUME"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// addDefaultHandlers adds print handlers for default Kubernetes types.
 | 
					// addDefaultHandlers adds print handlers for default Kubernetes types.
 | 
				
			||||||
func (h *HumanReadablePrinter) addDefaultHandlers() {
 | 
					func (h *HumanReadablePrinter) addDefaultHandlers() {
 | 
				
			||||||
@@ -261,6 +264,10 @@ func (h *HumanReadablePrinter) addDefaultHandlers() {
 | 
				
			|||||||
	h.Handler(namespaceColumns, printNamespaceList)
 | 
						h.Handler(namespaceColumns, printNamespaceList)
 | 
				
			||||||
	h.Handler(secretColumns, printSecret)
 | 
						h.Handler(secretColumns, printSecret)
 | 
				
			||||||
	h.Handler(secretColumns, printSecretList)
 | 
						h.Handler(secretColumns, printSecretList)
 | 
				
			||||||
 | 
						h.Handler(persistentVolumeClaimColumns, printPersistentVolumeClaim)
 | 
				
			||||||
 | 
						h.Handler(persistentVolumeClaimColumns, printPersistentVolumeClaimList)
 | 
				
			||||||
 | 
						h.Handler(persistentVolumeColumns, printPersistentVolume)
 | 
				
			||||||
 | 
						h.Handler(persistentVolumeColumns, printPersistentVolumeList)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (h *HumanReadablePrinter) unknown(data []byte, w io.Writer) error {
 | 
					func (h *HumanReadablePrinter) unknown(data []byte, w io.Writer) error {
 | 
				
			||||||
@@ -506,6 +513,50 @@ func printNodeList(list *api.NodeList, w io.Writer) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func printPersistentVolume(pv *api.PersistentVolume, w io.Writer) error {
 | 
				
			||||||
 | 
						claimRefUID := ""
 | 
				
			||||||
 | 
						if pv.Spec.ClaimRef != nil {
 | 
				
			||||||
 | 
							claimRefUID += pv.Spec.ClaimRef.Name
 | 
				
			||||||
 | 
							claimRefUID += " / "
 | 
				
			||||||
 | 
							claimRefUID += string(pv.Spec.ClaimRef.UID)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						modesStr := volume.GetAccessModesAsString(pv.Spec.AccessModes)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						aQty := pv.Spec.Capacity[api.ResourceStorage]
 | 
				
			||||||
 | 
						aSize := aQty.Value()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err := fmt.Fprintf(w, "%s\t%s\t%d\t%s\t%s\t%s\n", pv.Name, pv.Labels, aSize, modesStr, pv.Status.Phase, claimRefUID)
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func printPersistentVolumeList(list *api.PersistentVolumeList, w io.Writer) error {
 | 
				
			||||||
 | 
						for _, pv := range list.Items {
 | 
				
			||||||
 | 
							if err := printPersistentVolume(&pv, w); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func printPersistentVolumeClaim(pvc *api.PersistentVolumeClaim, w io.Writer) error {
 | 
				
			||||||
 | 
						volumeRefUID := ""
 | 
				
			||||||
 | 
						if pvc.Status.VolumeRef != nil {
 | 
				
			||||||
 | 
							volumeRefUID = string(pvc.Status.VolumeRef.UID)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", pvc.Name, pvc.Labels, pvc.Status.Phase, volumeRefUID)
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func printPersistentVolumeClaimList(list *api.PersistentVolumeClaimList, w io.Writer) error {
 | 
				
			||||||
 | 
						for _, psd := range list.Items {
 | 
				
			||||||
 | 
							if err := printPersistentVolumeClaim(&psd, w); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func printStatus(status *api.Status, w io.Writer) error {
 | 
					func printStatus(status *api.Status, w io.Writer) error {
 | 
				
			||||||
	_, err := fmt.Fprintf(w, "%v\n", status.Status)
 | 
						_, err := fmt.Fprintf(w, "%v\n", status.Status)
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -52,6 +52,8 @@ import (
 | 
				
			|||||||
	nodeetcd "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/minion/etcd"
 | 
						nodeetcd "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/minion/etcd"
 | 
				
			||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/namespace"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/namespace"
 | 
				
			||||||
	namespaceetcd "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/namespace/etcd"
 | 
						namespaceetcd "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/namespace/etcd"
 | 
				
			||||||
 | 
						pvetcd "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/persistentvolume/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"
 | 
				
			||||||
	resourcequotaetcd "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/resourcequota/etcd"
 | 
						resourcequotaetcd "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/resourcequota/etcd"
 | 
				
			||||||
@@ -363,6 +365,8 @@ func (m *Master) init(c *Config) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	resourceQuotaStorage, resourceQuotaStatusStorage := resourcequotaetcd.NewStorage(c.EtcdHelper)
 | 
						resourceQuotaStorage, resourceQuotaStatusStorage := resourcequotaetcd.NewStorage(c.EtcdHelper)
 | 
				
			||||||
	secretRegistry := secret.NewEtcdRegistry(c.EtcdHelper)
 | 
						secretRegistry := secret.NewEtcdRegistry(c.EtcdHelper)
 | 
				
			||||||
 | 
						persistentVolumeStorage, persistentVolumeStatusStorage := pvetcd.NewStorage(c.EtcdHelper)
 | 
				
			||||||
 | 
						persistentVolumeClaimStorage := pvcetcd.NewStorage(c.EtcdHelper)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	namespaceStorage, namespaceStatusStorage, namespaceFinalizeStorage := namespaceetcd.NewStorage(c.EtcdHelper)
 | 
						namespaceStorage, namespaceStatusStorage, namespaceFinalizeStorage := namespaceetcd.NewStorage(c.EtcdHelper)
 | 
				
			||||||
	m.namespaceRegistry = namespace.NewRegistry(namespaceStorage)
 | 
						m.namespaceRegistry = namespace.NewRegistry(namespaceStorage)
 | 
				
			||||||
@@ -400,6 +404,9 @@ func (m *Master) init(c *Config) {
 | 
				
			|||||||
		"namespaces/status":        namespaceStatusStorage,
 | 
							"namespaces/status":        namespaceStatusStorage,
 | 
				
			||||||
		"namespaces/finalize":      namespaceFinalizeStorage,
 | 
							"namespaces/finalize":      namespaceFinalizeStorage,
 | 
				
			||||||
		"secrets":                  secret.NewStorage(secretRegistry),
 | 
							"secrets":                  secret.NewStorage(secretRegistry),
 | 
				
			||||||
 | 
							"persistentVolumes":        persistentVolumeStorage,
 | 
				
			||||||
 | 
							"persistentVolumes/status": persistentVolumeStatusStorage,
 | 
				
			||||||
 | 
							"persistentVolumeClaims":   persistentVolumeClaimStorage,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	apiVersions := []string{"v1beta1", "v1beta2"}
 | 
						apiVersions := []string{"v1beta1", "v1beta2"}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -133,6 +133,10 @@ func deleteAllContent(kubeClient client.Interface, namespace string) (err error)
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						err = deletePersistentVolumeClaims(kubeClient, namespace)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	err = deleteLimitRanges(kubeClient, namespace)
 | 
						err = deleteLimitRanges(kubeClient, namespace)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
@@ -292,3 +296,17 @@ func deleteSecrets(kubeClient client.Interface, ns string) error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func deletePersistentVolumeClaims(kubeClient client.Interface, ns string) error {
 | 
				
			||||||
 | 
						items, err := kubeClient.PersistentVolumeClaims(ns).List(labels.Everything(), fields.Everything())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for i := range items.Items {
 | 
				
			||||||
 | 
							err := kubeClient.PersistentVolumeClaims(ns).Delete(items.Items[i].Name)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										17
									
								
								pkg/registry/persistentvolume/doc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								pkg/registry/persistentvolume/doc.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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 persistentvolume
 | 
				
			||||||
							
								
								
									
										80
									
								
								pkg/registry/persistentvolume/etcd/etcd.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								pkg/registry/persistentvolume/etcd/etcd.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,80 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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 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/persistentvolume"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// rest implements a RESTStorage for persistentvolumes against etcd
 | 
				
			||||||
 | 
					type REST struct {
 | 
				
			||||||
 | 
						*etcdgeneric.Etcd
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewREST returns a RESTStorage object that will work against PersistentVolume objects.
 | 
				
			||||||
 | 
					func NewStorage(h tools.EtcdHelper) (*REST, *StatusREST) {
 | 
				
			||||||
 | 
						prefix := "/registry/persistentvolumes"
 | 
				
			||||||
 | 
						store := &etcdgeneric.Etcd{
 | 
				
			||||||
 | 
							NewFunc:     func() runtime.Object { return &api.PersistentVolume{} },
 | 
				
			||||||
 | 
							NewListFunc: func() runtime.Object { return &api.PersistentVolumeList{} },
 | 
				
			||||||
 | 
							KeyRootFunc: func(ctx api.Context) string {
 | 
				
			||||||
 | 
								return prefix
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							KeyFunc: func(ctx api.Context, name string) (string, error) {
 | 
				
			||||||
 | 
								return prefix + "/" + name, nil
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							ObjectNameFunc: func(obj runtime.Object) (string, error) {
 | 
				
			||||||
 | 
								return obj.(*api.PersistentVolume).Name, nil
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
 | 
				
			||||||
 | 
								return persistentvolume.MatchPersistentVolumes(label, field)
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							EndpointName: "persistentvolume",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Helper: h,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						store.CreateStrategy = persistentvolume.Strategy
 | 
				
			||||||
 | 
						store.UpdateStrategy = persistentvolume.Strategy
 | 
				
			||||||
 | 
						store.ReturnDeletedObject = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						statusStore := *store
 | 
				
			||||||
 | 
						statusStore.UpdateStrategy = persistentvolume.StatusStrategy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &REST{store}, &StatusREST{store: &statusStore}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// StatusREST implements the REST endpoint for changing the status of a persistentvolume.
 | 
				
			||||||
 | 
					type StatusREST struct {
 | 
				
			||||||
 | 
						store *etcdgeneric.Etcd
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *StatusREST) New() runtime.Object {
 | 
				
			||||||
 | 
						return &api.PersistentVolume{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Update alters the status subset of an object.
 | 
				
			||||||
 | 
					func (r *StatusREST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) {
 | 
				
			||||||
 | 
						return r.store.Update(ctx, obj)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										342
									
								
								pkg/registry/persistentvolume/etcd/etcd_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										342
									
								
								pkg/registry/persistentvolume/etcd/etcd_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,342 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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 etcd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest/resttest"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/coreos/go-etcd/etcd"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type testRegistry struct {
 | 
				
			||||||
 | 
						*registrytest.GenericRegistry
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newStorage(t *testing.T) (*REST, *StatusREST, *tools.FakeEtcdClient, tools.EtcdHelper) {
 | 
				
			||||||
 | 
						fakeEtcdClient := tools.NewFakeEtcdClient(t)
 | 
				
			||||||
 | 
						fakeEtcdClient.TestIndex = true
 | 
				
			||||||
 | 
						helper := tools.NewEtcdHelper(fakeEtcdClient, latest.Codec)
 | 
				
			||||||
 | 
						storage, statusStorage := NewStorage(helper)
 | 
				
			||||||
 | 
						return storage, statusStorage, fakeEtcdClient, helper
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func validNewPersistentVolume(name string) *api.PersistentVolume {
 | 
				
			||||||
 | 
						pv := &api.PersistentVolume{
 | 
				
			||||||
 | 
							ObjectMeta: api.ObjectMeta{
 | 
				
			||||||
 | 
								Name: name,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							Spec: api.PersistentVolumeSpec{
 | 
				
			||||||
 | 
								Capacity: api.ResourceList{
 | 
				
			||||||
 | 
									api.ResourceName(api.ResourceStorage): resource.MustParse("10G"),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								PersistentVolumeSource: api.PersistentVolumeSource{
 | 
				
			||||||
 | 
									HostPath: &api.HostPathVolumeSource{Path: "/foo"},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return pv
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func validChangedPersistentVolume() *api.PersistentVolume {
 | 
				
			||||||
 | 
						pv := validNewPersistentVolume("foo")
 | 
				
			||||||
 | 
						pv.ResourceVersion = "1"
 | 
				
			||||||
 | 
						return pv
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestCreate(t *testing.T) {
 | 
				
			||||||
 | 
						storage, _, fakeEtcdClient, _ := newStorage(t)
 | 
				
			||||||
 | 
						test := resttest.New(t, storage, fakeEtcdClient.SetError)
 | 
				
			||||||
 | 
						pv := validNewPersistentVolume("foo")
 | 
				
			||||||
 | 
						pv.ObjectMeta = api.ObjectMeta{}
 | 
				
			||||||
 | 
						test.TestCreate(
 | 
				
			||||||
 | 
							// valid
 | 
				
			||||||
 | 
							pv,
 | 
				
			||||||
 | 
							// invalid
 | 
				
			||||||
 | 
							&api.PersistentVolume{
 | 
				
			||||||
 | 
								ObjectMeta: api.ObjectMeta{Name: "*BadName!"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestDelete(t *testing.T) {
 | 
				
			||||||
 | 
						ctx := api.NewDefaultContext()
 | 
				
			||||||
 | 
						storage, _, fakeEtcdClient, _ := newStorage(t)
 | 
				
			||||||
 | 
						test := resttest.New(t, storage, fakeEtcdClient.SetError)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pv := validChangedPersistentVolume()
 | 
				
			||||||
 | 
						key, _ := storage.KeyFunc(ctx, pv.Name)
 | 
				
			||||||
 | 
						createFn := func() runtime.Object {
 | 
				
			||||||
 | 
							fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
 | 
				
			||||||
 | 
								R: &etcd.Response{
 | 
				
			||||||
 | 
									Node: &etcd.Node{
 | 
				
			||||||
 | 
										Value:         runtime.EncodeOrDie(latest.Codec, pv),
 | 
				
			||||||
 | 
										ModifiedIndex: 1,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return pv
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						gracefulSetFn := func() bool {
 | 
				
			||||||
 | 
							if fakeEtcdClient.Data[key].R.Node == nil {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return fakeEtcdClient.Data[key].R.Node.TTL == 30
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						test.TestDeleteNoGraceful(createFn, gracefulSetFn)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestEtcdListPersistentVolumes(t *testing.T) {
 | 
				
			||||||
 | 
						ctx := api.NewDefaultContext()
 | 
				
			||||||
 | 
						storage, _, fakeClient, _ := newStorage(t)
 | 
				
			||||||
 | 
						key := storage.KeyRootFunc(ctx)
 | 
				
			||||||
 | 
						fakeClient.Data[key] = tools.EtcdResponseWithError{
 | 
				
			||||||
 | 
							R: &etcd.Response{
 | 
				
			||||||
 | 
								Node: &etcd.Node{
 | 
				
			||||||
 | 
									Nodes: []*etcd.Node{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Value: runtime.EncodeOrDie(latest.Codec, validNewPersistentVolume("foo")),
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Value: runtime.EncodeOrDie(latest.Codec, validNewPersistentVolume("bar")),
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							E: nil,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pvObj, err := storage.List(ctx, labels.Everything(), fields.Everything())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						pvs := pvObj.(*api.PersistentVolumeList)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(pvs.Items) != 2 || pvs.Items[0].Name != "foo" || pvs.Items[1].Name != "bar" {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected persistentVolume list: %#v", pvs)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestEtcdGetPersistentVolumes(t *testing.T) {
 | 
				
			||||||
 | 
						ctx := api.NewDefaultContext()
 | 
				
			||||||
 | 
						storage, _, fakeClient, _ := newStorage(t)
 | 
				
			||||||
 | 
						persistentVolume := validNewPersistentVolume("foo")
 | 
				
			||||||
 | 
						name := persistentVolume.Name
 | 
				
			||||||
 | 
						key, _ := storage.KeyFunc(ctx, name)
 | 
				
			||||||
 | 
						fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, persistentVolume), 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						response, err := fakeClient.Get(key, false, false)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("Unexpected error %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var persistentVolumeOut api.PersistentVolume
 | 
				
			||||||
 | 
						err = latest.Codec.DecodeInto([]byte(response.Node.Value), &persistentVolumeOut)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						obj, err := storage.Get(ctx, name)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						got := obj.(*api.PersistentVolume)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						persistentVolume.ObjectMeta.ResourceVersion = got.ObjectMeta.ResourceVersion
 | 
				
			||||||
 | 
						if e, a := persistentVolume, got; !api.Semantic.DeepEqual(*e, *a) {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected persistentVolume: %#v, expected %#v", e, a)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestListEmptyPersistentVolumesList(t *testing.T) {
 | 
				
			||||||
 | 
						ctx := api.NewDefaultContext()
 | 
				
			||||||
 | 
						storage, _, fakeClient, _ := newStorage(t)
 | 
				
			||||||
 | 
						fakeClient.ChangeIndex = 1
 | 
				
			||||||
 | 
						key := storage.KeyRootFunc(ctx)
 | 
				
			||||||
 | 
						fakeClient.Data[key] = tools.EtcdResponseWithError{
 | 
				
			||||||
 | 
							R: &etcd.Response{},
 | 
				
			||||||
 | 
							E: fakeClient.NewError(tools.EtcdErrorCodeNotFound),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						persistentVolume, err := storage.List(ctx, labels.Everything(), fields.Everything())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(persistentVolume.(*api.PersistentVolumeList).Items) != 0 {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected non-zero pod list: %#v", persistentVolume)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if persistentVolume.(*api.PersistentVolumeList).ResourceVersion != "1" {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected resource version: %#v", persistentVolume)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestListPersistentVolumesList(t *testing.T) {
 | 
				
			||||||
 | 
						ctx := api.NewDefaultContext()
 | 
				
			||||||
 | 
						storage, _, fakeClient, _ := newStorage(t)
 | 
				
			||||||
 | 
						fakeClient.ChangeIndex = 1
 | 
				
			||||||
 | 
						key := storage.KeyRootFunc(ctx)
 | 
				
			||||||
 | 
						fakeClient.Data[key] = tools.EtcdResponseWithError{
 | 
				
			||||||
 | 
							R: &etcd.Response{
 | 
				
			||||||
 | 
								Node: &etcd.Node{
 | 
				
			||||||
 | 
									Nodes: []*etcd.Node{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Value: runtime.EncodeOrDie(latest.Codec, &api.PersistentVolume{
 | 
				
			||||||
 | 
												ObjectMeta: api.ObjectMeta{Name: "foo"},
 | 
				
			||||||
 | 
											}),
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Value: runtime.EncodeOrDie(latest.Codec, &api.PersistentVolume{
 | 
				
			||||||
 | 
												ObjectMeta: api.ObjectMeta{Name: "bar"},
 | 
				
			||||||
 | 
											}),
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						persistentVolumeObj, err := storage.List(ctx, labels.Everything(), fields.Everything())
 | 
				
			||||||
 | 
						persistentVolumeList := persistentVolumeObj.(*api.PersistentVolumeList)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(persistentVolumeList.Items) != 2 {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected persistentVolume list: %#v", persistentVolumeList)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if persistentVolumeList.Items[0].Name != "foo" {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected persistentVolume: %#v", persistentVolumeList.Items[0])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if persistentVolumeList.Items[1].Name != "bar" {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected persistentVolume: %#v", persistentVolumeList.Items[1])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestPersistentVolumesDecode(t *testing.T) {
 | 
				
			||||||
 | 
						storage, _, _, _ := newStorage(t)
 | 
				
			||||||
 | 
						expected := validNewPersistentVolume("foo")
 | 
				
			||||||
 | 
						body, err := latest.Codec.Encode(expected)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						actual := storage.New()
 | 
				
			||||||
 | 
						if err := latest.Codec.DecodeInto(body, actual); err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !api.Semantic.DeepEqual(expected, actual) {
 | 
				
			||||||
 | 
							t.Errorf("mismatch: %s", util.ObjectDiff(expected, actual))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestEtcdUpdatePersistentVolumes(t *testing.T) {
 | 
				
			||||||
 | 
						ctx := api.NewDefaultContext()
 | 
				
			||||||
 | 
						storage, _, fakeClient, _ := newStorage(t)
 | 
				
			||||||
 | 
						persistentVolume := validChangedPersistentVolume()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						key, _ := storage.KeyFunc(ctx, "foo")
 | 
				
			||||||
 | 
						fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, validNewPersistentVolume("foo")), 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, _, err := storage.Update(ctx, persistentVolume)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						response, err := fakeClient.Get(key, false, false)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("Unexpected error %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var persistentVolumeOut api.PersistentVolume
 | 
				
			||||||
 | 
						err = latest.Codec.DecodeInto([]byte(response.Node.Value), &persistentVolumeOut)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						persistentVolume.ObjectMeta.ResourceVersion = persistentVolumeOut.ObjectMeta.ResourceVersion
 | 
				
			||||||
 | 
						if !api.Semantic.DeepEqual(persistentVolume, &persistentVolumeOut) {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected persistentVolume: %#v, expected %#v", &persistentVolumeOut, persistentVolume)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestDeletePersistentVolumes(t *testing.T) {
 | 
				
			||||||
 | 
						ctx := api.NewDefaultContext()
 | 
				
			||||||
 | 
						storage, _, fakeClient, _ := newStorage(t)
 | 
				
			||||||
 | 
						persistentVolume := validNewPersistentVolume("foo")
 | 
				
			||||||
 | 
						name := persistentVolume.Name
 | 
				
			||||||
 | 
						key, _ := storage.KeyFunc(ctx, name)
 | 
				
			||||||
 | 
						fakeClient.ChangeIndex = 1
 | 
				
			||||||
 | 
						fakeClient.Data[key] = tools.EtcdResponseWithError{
 | 
				
			||||||
 | 
							R: &etcd.Response{
 | 
				
			||||||
 | 
								Node: &etcd.Node{
 | 
				
			||||||
 | 
									Value:         runtime.EncodeOrDie(latest.Codec, persistentVolume),
 | 
				
			||||||
 | 
									ModifiedIndex: 1,
 | 
				
			||||||
 | 
									CreatedIndex:  1,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_, err := storage.Delete(ctx, name, nil)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestEtcdUpdateStatus(t *testing.T) {
 | 
				
			||||||
 | 
						storage, statusStorage, fakeClient, helper := newStorage(t)
 | 
				
			||||||
 | 
						ctx := api.NewDefaultContext()
 | 
				
			||||||
 | 
						fakeClient.TestIndex = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						key, _ := storage.KeyFunc(ctx, "foo")
 | 
				
			||||||
 | 
						pvStart := validNewPersistentVolume("foo")
 | 
				
			||||||
 | 
						fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, pvStart), 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pvIn := &api.PersistentVolume{
 | 
				
			||||||
 | 
							ObjectMeta: api.ObjectMeta{
 | 
				
			||||||
 | 
								Name:            "foo",
 | 
				
			||||||
 | 
								ResourceVersion: "1",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							Status: api.PersistentVolumeStatus{
 | 
				
			||||||
 | 
								Phase: api.VolumeBound,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						expected := *pvStart
 | 
				
			||||||
 | 
						expected.ResourceVersion = "2"
 | 
				
			||||||
 | 
						expected.Labels = pvIn.Labels
 | 
				
			||||||
 | 
						expected.Status = pvIn.Status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, _, err := statusStorage.Update(ctx, pvIn)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("Unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var pvOut api.PersistentVolume
 | 
				
			||||||
 | 
						if err := helper.ExtractObj(key, &pvOut, false); err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("Unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !api.Semantic.DeepEqual(expected, pvOut) {
 | 
				
			||||||
 | 
							t.Errorf("unexpected object: %s", util.ObjectDiff(expected, pvOut))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										87
									
								
								pkg/registry/persistentvolume/registry.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								pkg/registry/persistentvolume/registry.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,87 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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 persistentvolume
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Registry is an interface implemented by things that know how to store PersistentVolume objects.
 | 
				
			||||||
 | 
					type Registry interface {
 | 
				
			||||||
 | 
						// ListPersistentVolumes obtains a list of persistentVolumes having labels which match selector.
 | 
				
			||||||
 | 
						ListPersistentVolumes(ctx api.Context, selector labels.Selector) (*api.PersistentVolumeList, error)
 | 
				
			||||||
 | 
						// Watch for new/changed/deleted persistentVolumes
 | 
				
			||||||
 | 
						WatchPersistentVolumes(ctx api.Context, label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error)
 | 
				
			||||||
 | 
						// Get a specific persistentVolume
 | 
				
			||||||
 | 
						GetPersistentVolume(ctx api.Context, persistentVolumeID string) (*api.PersistentVolume, error)
 | 
				
			||||||
 | 
						// Create a persistentVolume based on a specification.
 | 
				
			||||||
 | 
						CreatePersistentVolume(ctx api.Context, persistentVolume *api.PersistentVolume) error
 | 
				
			||||||
 | 
						// Update an existing persistentVolume
 | 
				
			||||||
 | 
						UpdatePersistentVolume(ctx api.Context, persistentVolume *api.PersistentVolume) error
 | 
				
			||||||
 | 
						// Delete an existing persistentVolume
 | 
				
			||||||
 | 
						DeletePersistentVolume(ctx api.Context, persistentVolumeID string) error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// storage puts strong typing around storage calls
 | 
				
			||||||
 | 
					type storage struct {
 | 
				
			||||||
 | 
						rest.StandardStorage
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewRegistry returns a new Registry interface for the given Storage. Any mismatched
 | 
				
			||||||
 | 
					// types will panic.
 | 
				
			||||||
 | 
					func NewRegistry(s rest.StandardStorage) Registry {
 | 
				
			||||||
 | 
						return &storage{s}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *storage) ListPersistentVolumes(ctx api.Context, label labels.Selector) (*api.PersistentVolumeList, error) {
 | 
				
			||||||
 | 
						obj, err := s.List(ctx, label, fields.Everything())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return obj.(*api.PersistentVolumeList), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *storage) WatchPersistentVolumes(ctx api.Context, label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) {
 | 
				
			||||||
 | 
						return s.Watch(ctx, label, field, resourceVersion)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *storage) GetPersistentVolume(ctx api.Context, persistentVolumeID string) (*api.PersistentVolume, error) {
 | 
				
			||||||
 | 
						obj, err := s.Get(ctx, persistentVolumeID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return obj.(*api.PersistentVolume), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *storage) CreatePersistentVolume(ctx api.Context, persistentVolume *api.PersistentVolume) error {
 | 
				
			||||||
 | 
						_, err := s.Create(ctx, persistentVolume)
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *storage) UpdatePersistentVolume(ctx api.Context, persistentVolume *api.PersistentVolume) error {
 | 
				
			||||||
 | 
						_, _, err := s.Update(ctx, persistentVolume)
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *storage) DeletePersistentVolume(ctx api.Context, persistentVolumeID string) error {
 | 
				
			||||||
 | 
						_, err := s.Delete(ctx, persistentVolumeID, nil)
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										109
									
								
								pkg/registry/persistentvolume/rest.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								pkg/registry/persistentvolume/rest.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,109 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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 persistentvolume
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/util/fielderrors"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// persistentvolumeStrategy implements behavior for PersistentVolume objects
 | 
				
			||||||
 | 
					type persistentvolumeStrategy struct {
 | 
				
			||||||
 | 
						runtime.ObjectTyper
 | 
				
			||||||
 | 
						api.NameGenerator
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Strategy is the default logic that applies when creating and updating PersistentVolume
 | 
				
			||||||
 | 
					// objects via the REST API.
 | 
				
			||||||
 | 
					var Strategy = persistentvolumeStrategy{api.Scheme, api.SimpleNameGenerator}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NamespaceScoped is false for persistentvolumes.
 | 
				
			||||||
 | 
					func (persistentvolumeStrategy) NamespaceScoped() bool {
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ResetBeforeCreate clears fields that are not allowed to be set by end users on creation.
 | 
				
			||||||
 | 
					func (persistentvolumeStrategy) PrepareForCreate(obj runtime.Object) {
 | 
				
			||||||
 | 
						pv := obj.(*api.PersistentVolume)
 | 
				
			||||||
 | 
						pv.Status = api.PersistentVolumeStatus{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
 | 
				
			||||||
 | 
					func (persistentvolumeStrategy) PrepareForUpdate(obj, old runtime.Object) {
 | 
				
			||||||
 | 
						newPv := obj.(*api.PersistentVolume)
 | 
				
			||||||
 | 
						oldPv := obj.(*api.PersistentVolume)
 | 
				
			||||||
 | 
						newPv.Status = oldPv.Status
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Validate validates a new persistentvolume.
 | 
				
			||||||
 | 
					func (persistentvolumeStrategy) Validate(obj runtime.Object) fielderrors.ValidationErrorList {
 | 
				
			||||||
 | 
						persistentvolume := obj.(*api.PersistentVolume)
 | 
				
			||||||
 | 
						return validation.ValidatePersistentVolume(persistentvolume)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AllowCreateOnUpdate is false for persistentvolumes.
 | 
				
			||||||
 | 
					func (persistentvolumeStrategy) AllowCreateOnUpdate() bool {
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ValidateUpdate is the default update validation for an end user.
 | 
				
			||||||
 | 
					func (persistentvolumeStrategy) ValidateUpdate(obj, old runtime.Object) fielderrors.ValidationErrorList {
 | 
				
			||||||
 | 
						return validation.ValidatePersistentVolumeUpdate(obj.(*api.PersistentVolume), old.(*api.PersistentVolume))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type persistentvolumeStatusStrategy struct {
 | 
				
			||||||
 | 
						persistentvolumeStrategy
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var StatusStrategy = persistentvolumeStatusStrategy{Strategy}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (persistentvolumeStatusStrategy) PrepareForUpdate(obj, old runtime.Object) {
 | 
				
			||||||
 | 
						newPv := obj.(*api.PersistentVolume)
 | 
				
			||||||
 | 
						oldPv := obj.(*api.PersistentVolume)
 | 
				
			||||||
 | 
						newPv.Spec = oldPv.Spec
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (persistentvolumeStatusStrategy) ValidateUpdate(obj, old runtime.Object) fielderrors.ValidationErrorList {
 | 
				
			||||||
 | 
						return validation.ValidatePersistentVolumeStatusUpdate(obj.(*api.PersistentVolume), old.(*api.PersistentVolume))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MatchPersistentVolume returns a generic matcher for a given label and field selector.
 | 
				
			||||||
 | 
					func MatchPersistentVolumes(label labels.Selector, field fields.Selector) generic.Matcher {
 | 
				
			||||||
 | 
						return generic.MatcherFunc(func(obj runtime.Object) (bool, error) {
 | 
				
			||||||
 | 
							persistentvolumeObj, ok := obj.(*api.PersistentVolume)
 | 
				
			||||||
 | 
							if !ok {
 | 
				
			||||||
 | 
								return false, fmt.Errorf("not a persistentvolume")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							fields := PersistentVolumeToSelectableFields(persistentvolumeObj)
 | 
				
			||||||
 | 
							return label.Matches(labels.Set(persistentvolumeObj.Labels)) && field.Matches(fields), nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PersistentVolumeToSelectableFields returns a label set that represents the object
 | 
				
			||||||
 | 
					// TODO: fields are not labels, and the validation rules for them do not apply.
 | 
				
			||||||
 | 
					func PersistentVolumeToSelectableFields(persistentvolume *api.PersistentVolume) labels.Set {
 | 
				
			||||||
 | 
						return labels.Set{
 | 
				
			||||||
 | 
							"name": persistentvolume.Name,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										17
									
								
								pkg/registry/persistentvolumeclaim/doc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								pkg/registry/persistentvolumeclaim/doc.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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 persistentvolumeclaim
 | 
				
			||||||
							
								
								
									
										63
									
								
								pkg/registry/persistentvolumeclaim/etcd/etcd.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								pkg/registry/persistentvolumeclaim/etcd/etcd.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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 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/persistentvolumeclaim"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// rest implements a RESTStorage for persistentvolumeclaims against etcd
 | 
				
			||||||
 | 
					type REST struct {
 | 
				
			||||||
 | 
						*etcdgeneric.Etcd
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewREST returns a RESTStorage object that will work against PersistentVolumeClaim objects.
 | 
				
			||||||
 | 
					func NewStorage(h tools.EtcdHelper) *REST {
 | 
				
			||||||
 | 
						prefix := "/registry/persistentvolumeclaims"
 | 
				
			||||||
 | 
						store := &etcdgeneric.Etcd{
 | 
				
			||||||
 | 
							NewFunc:     func() runtime.Object { return &api.PersistentVolumeClaim{} },
 | 
				
			||||||
 | 
							NewListFunc: func() runtime.Object { return &api.PersistentVolumeClaimList{} },
 | 
				
			||||||
 | 
							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.PersistentVolumeClaim).Name, nil
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
 | 
				
			||||||
 | 
								return persistentvolumeclaim.MatchPersistentVolumeClaim(label, field)
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							EndpointName: "persistentvolumeclaims",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Helper: h,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						store.CreateStrategy = persistentvolumeclaim.Strategy
 | 
				
			||||||
 | 
						store.UpdateStrategy = persistentvolumeclaim.Strategy
 | 
				
			||||||
 | 
						store.ReturnDeletedObject = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &REST{store}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										334
									
								
								pkg/registry/persistentvolumeclaim/etcd/etcd_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										334
									
								
								pkg/registry/persistentvolumeclaim/etcd/etcd_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,334 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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 etcd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest/resttest"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/registrytest"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/coreos/go-etcd/etcd"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type testRegistry struct {
 | 
				
			||||||
 | 
						*registrytest.GenericRegistry
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newStorage(t *testing.T) (*REST, *tools.FakeEtcdClient, tools.EtcdHelper) {
 | 
				
			||||||
 | 
						fakeEtcdClient := tools.NewFakeEtcdClient(t)
 | 
				
			||||||
 | 
						fakeEtcdClient.TestIndex = true
 | 
				
			||||||
 | 
						helper := tools.NewEtcdHelper(fakeEtcdClient, latest.Codec)
 | 
				
			||||||
 | 
						storage := NewStorage(helper)
 | 
				
			||||||
 | 
						return storage, fakeEtcdClient, helper
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func validNewPersistentVolumeClaim(name, ns string) *api.PersistentVolumeClaim {
 | 
				
			||||||
 | 
						pv := &api.PersistentVolumeClaim{
 | 
				
			||||||
 | 
							ObjectMeta: api.ObjectMeta{
 | 
				
			||||||
 | 
								Name:      name,
 | 
				
			||||||
 | 
								Namespace: ns,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							Spec: api.PersistentVolumeClaimSpec{
 | 
				
			||||||
 | 
								AccessModes: []api.AccessModeType{api.ReadWriteOnce},
 | 
				
			||||||
 | 
								Resources: api.ResourceRequirements{
 | 
				
			||||||
 | 
									Requests: api.ResourceList{
 | 
				
			||||||
 | 
										api.ResourceName(api.ResourceStorage): resource.MustParse("10G"),
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return pv
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func validChangedPersistentVolumeClaim() *api.PersistentVolumeClaim {
 | 
				
			||||||
 | 
						pv := validNewPersistentVolumeClaim("foo", api.NamespaceDefault)
 | 
				
			||||||
 | 
						pv.ResourceVersion = "1"
 | 
				
			||||||
 | 
						return pv
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestCreate(t *testing.T) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						registry, fakeEtcdClient, _ := newStorage(t)
 | 
				
			||||||
 | 
						test := resttest.New(t, registry, fakeEtcdClient.SetError)
 | 
				
			||||||
 | 
						pv := validNewPersistentVolumeClaim("foo", api.NamespaceDefault)
 | 
				
			||||||
 | 
						pv.ObjectMeta = api.ObjectMeta{}
 | 
				
			||||||
 | 
						test.TestCreate(
 | 
				
			||||||
 | 
							// valid
 | 
				
			||||||
 | 
							pv,
 | 
				
			||||||
 | 
							// invalid
 | 
				
			||||||
 | 
							&api.PersistentVolumeClaim{
 | 
				
			||||||
 | 
								ObjectMeta: api.ObjectMeta{Name: "*BadName!"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestDelete2(t *testing.T) {
 | 
				
			||||||
 | 
						ctx := api.NewDefaultContext()
 | 
				
			||||||
 | 
						storage, fakeEtcdClient, _ := newStorage(t)
 | 
				
			||||||
 | 
						test := resttest.New(t, storage, fakeEtcdClient.SetError)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pv := validChangedPersistentVolumeClaim()
 | 
				
			||||||
 | 
						key, _ := storage.KeyFunc(ctx, pv.Name)
 | 
				
			||||||
 | 
						createFn := func() runtime.Object {
 | 
				
			||||||
 | 
							fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
 | 
				
			||||||
 | 
								R: &etcd.Response{
 | 
				
			||||||
 | 
									Node: &etcd.Node{
 | 
				
			||||||
 | 
										Value:         runtime.EncodeOrDie(latest.Codec, pv),
 | 
				
			||||||
 | 
										ModifiedIndex: 1,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return pv
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						gracefulSetFn := func() bool {
 | 
				
			||||||
 | 
							if fakeEtcdClient.Data[key].R.Node == nil {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return fakeEtcdClient.Data[key].R.Node.TTL == 30
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						test.TestDeleteNoGraceful(createFn, gracefulSetFn)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestDelete(t *testing.T) {
 | 
				
			||||||
 | 
						ctx := api.NewDefaultContext()
 | 
				
			||||||
 | 
						registry, fakeEtcdClient, _ := newStorage(t)
 | 
				
			||||||
 | 
						test := resttest.New(t, registry, fakeEtcdClient.SetError)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pvc := validChangedPersistentVolumeClaim()
 | 
				
			||||||
 | 
						key, _ := registry.KeyFunc(ctx, pvc.Name)
 | 
				
			||||||
 | 
						createFn := func() runtime.Object {
 | 
				
			||||||
 | 
							fakeEtcdClient.Data[key] = tools.EtcdResponseWithError{
 | 
				
			||||||
 | 
								R: &etcd.Response{
 | 
				
			||||||
 | 
									Node: &etcd.Node{
 | 
				
			||||||
 | 
										Value:         runtime.EncodeOrDie(latest.Codec, pvc),
 | 
				
			||||||
 | 
										ModifiedIndex: 1,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return pvc
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						gracefulSetFn := func() bool {
 | 
				
			||||||
 | 
							if fakeEtcdClient.Data[key].R.Node == nil {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return fakeEtcdClient.Data[key].R.Node.TTL == 30
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						test.TestDeleteNoGraceful(createFn, gracefulSetFn)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestEtcdListPersistentVolumeClaims(t *testing.T) {
 | 
				
			||||||
 | 
						ctx := api.NewDefaultContext()
 | 
				
			||||||
 | 
						registry, fakeClient, _ := newStorage(t)
 | 
				
			||||||
 | 
						key := registry.KeyRootFunc(ctx)
 | 
				
			||||||
 | 
						fakeClient.Data[key] = tools.EtcdResponseWithError{
 | 
				
			||||||
 | 
							R: &etcd.Response{
 | 
				
			||||||
 | 
								Node: &etcd.Node{
 | 
				
			||||||
 | 
									Nodes: []*etcd.Node{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Value: runtime.EncodeOrDie(latest.Codec, validNewPersistentVolumeClaim("foo", api.NamespaceDefault)),
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Value: runtime.EncodeOrDie(latest.Codec, validNewPersistentVolumeClaim("bar", api.NamespaceDefault)),
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							E: nil,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pvObj, err := registry.List(ctx, labels.Everything(), fields.Everything())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						pvs := pvObj.(*api.PersistentVolumeClaimList)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(pvs.Items) != 2 || pvs.Items[0].Name != "foo" || pvs.Items[1].Name != "bar" {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected persistentVolume list: %#v", pvs)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestEtcdGetPersistentVolumeClaims(t *testing.T) {
 | 
				
			||||||
 | 
						ctx := api.NewDefaultContext()
 | 
				
			||||||
 | 
						registry, fakeClient, _ := newStorage(t)
 | 
				
			||||||
 | 
						persistentVolume := validNewPersistentVolumeClaim("foo", api.NamespaceDefault)
 | 
				
			||||||
 | 
						name := persistentVolume.Name
 | 
				
			||||||
 | 
						key, _ := registry.KeyFunc(ctx, name)
 | 
				
			||||||
 | 
						fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, persistentVolume), 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						response, err := fakeClient.Get(key, false, false)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("Unexpected error %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var persistentVolumeOut api.PersistentVolumeClaim
 | 
				
			||||||
 | 
						err = latest.Codec.DecodeInto([]byte(response.Node.Value), &persistentVolumeOut)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						obj, err := registry.Get(ctx, name)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						got := obj.(*api.PersistentVolumeClaim)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						persistentVolume.ObjectMeta.ResourceVersion = got.ObjectMeta.ResourceVersion
 | 
				
			||||||
 | 
						if e, a := persistentVolume, got; !api.Semantic.DeepEqual(*e, *a) {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected persistentVolume: %#v, expected %#v", e, a)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestListEmptyPersistentVolumeClaimsList(t *testing.T) {
 | 
				
			||||||
 | 
						ctx := api.NewDefaultContext()
 | 
				
			||||||
 | 
						registry, fakeClient, _ := newStorage(t)
 | 
				
			||||||
 | 
						fakeClient.ChangeIndex = 1
 | 
				
			||||||
 | 
						key := registry.KeyRootFunc(ctx)
 | 
				
			||||||
 | 
						fakeClient.Data[key] = tools.EtcdResponseWithError{
 | 
				
			||||||
 | 
							R: &etcd.Response{},
 | 
				
			||||||
 | 
							E: fakeClient.NewError(tools.EtcdErrorCodeNotFound),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						persistentVolume, err := registry.List(ctx, labels.Everything(), fields.Everything())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(persistentVolume.(*api.PersistentVolumeClaimList).Items) != 0 {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected non-zero pod list: %#v", persistentVolume)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if persistentVolume.(*api.PersistentVolumeClaimList).ResourceVersion != "1" {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected resource version: %#v", persistentVolume)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestListPersistentVolumeClaimsList(t *testing.T) {
 | 
				
			||||||
 | 
						ctx := api.NewDefaultContext()
 | 
				
			||||||
 | 
						registry, fakeClient, _ := newStorage(t)
 | 
				
			||||||
 | 
						fakeClient.ChangeIndex = 1
 | 
				
			||||||
 | 
						key := registry.KeyRootFunc(ctx)
 | 
				
			||||||
 | 
						fakeClient.Data[key] = tools.EtcdResponseWithError{
 | 
				
			||||||
 | 
							R: &etcd.Response{
 | 
				
			||||||
 | 
								Node: &etcd.Node{
 | 
				
			||||||
 | 
									Nodes: []*etcd.Node{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Value: runtime.EncodeOrDie(latest.Codec, &api.PersistentVolumeClaim{
 | 
				
			||||||
 | 
												ObjectMeta: api.ObjectMeta{Name: "foo"},
 | 
				
			||||||
 | 
											}),
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Value: runtime.EncodeOrDie(latest.Codec, &api.PersistentVolumeClaim{
 | 
				
			||||||
 | 
												ObjectMeta: api.ObjectMeta{Name: "bar"},
 | 
				
			||||||
 | 
											}),
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						persistentVolumeObj, err := registry.List(ctx, labels.Everything(), fields.Everything())
 | 
				
			||||||
 | 
						persistentVolumeList := persistentVolumeObj.(*api.PersistentVolumeClaimList)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(persistentVolumeList.Items) != 2 {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected persistentVolume list: %#v", persistentVolumeList)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if persistentVolumeList.Items[0].Name != "foo" {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected persistentVolume: %#v", persistentVolumeList.Items[0])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if persistentVolumeList.Items[1].Name != "bar" {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected persistentVolume: %#v", persistentVolumeList.Items[1])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestPersistentVolumeClaimsDecode(t *testing.T) {
 | 
				
			||||||
 | 
						registry, _, _ := newStorage(t)
 | 
				
			||||||
 | 
						expected := validNewPersistentVolumeClaim("foo", api.NamespaceDefault)
 | 
				
			||||||
 | 
						body, err := latest.Codec.Encode(expected)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						actual := registry.New()
 | 
				
			||||||
 | 
						if err := latest.Codec.DecodeInto(body, actual); err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !api.Semantic.DeepEqual(expected, actual) {
 | 
				
			||||||
 | 
							t.Errorf("mismatch: %s", util.ObjectDiff(expected, actual))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestEtcdUpdatePersistentVolumeClaims(t *testing.T) {
 | 
				
			||||||
 | 
						ctx := api.NewDefaultContext()
 | 
				
			||||||
 | 
						registry, fakeClient, _ := newStorage(t)
 | 
				
			||||||
 | 
						persistentVolume := validChangedPersistentVolumeClaim()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						key, _ := registry.KeyFunc(ctx, "foo")
 | 
				
			||||||
 | 
						fakeClient.Set(key, runtime.EncodeOrDie(latest.Codec, validNewPersistentVolumeClaim("foo", api.NamespaceDefault)), 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, _, err := registry.Update(ctx, persistentVolume)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						response, err := fakeClient.Get(key, false, false)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("Unexpected error %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var persistentVolumeOut api.PersistentVolumeClaim
 | 
				
			||||||
 | 
						err = latest.Codec.DecodeInto([]byte(response.Node.Value), &persistentVolumeOut)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf("unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						persistentVolume.ObjectMeta.ResourceVersion = persistentVolumeOut.ObjectMeta.ResourceVersion
 | 
				
			||||||
 | 
						if !api.Semantic.DeepEqual(persistentVolume, &persistentVolumeOut) {
 | 
				
			||||||
 | 
							t.Errorf("Unexpected persistentVolume: %#v, expected %#v", &persistentVolumeOut, persistentVolume)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestDeletePersistentVolumeClaims(t *testing.T) {
 | 
				
			||||||
 | 
						ctx := api.NewDefaultContext()
 | 
				
			||||||
 | 
						registry, fakeClient, _ := newStorage(t)
 | 
				
			||||||
 | 
						persistentVolume := validNewPersistentVolumeClaim("foo", api.NamespaceDefault)
 | 
				
			||||||
 | 
						name := persistentVolume.Name
 | 
				
			||||||
 | 
						key, _ := registry.KeyFunc(ctx, name)
 | 
				
			||||||
 | 
						fakeClient.ChangeIndex = 1
 | 
				
			||||||
 | 
						fakeClient.Data[key] = tools.EtcdResponseWithError{
 | 
				
			||||||
 | 
							R: &etcd.Response{
 | 
				
			||||||
 | 
								Node: &etcd.Node{
 | 
				
			||||||
 | 
									Value:         runtime.EncodeOrDie(latest.Codec, persistentVolume),
 | 
				
			||||||
 | 
									ModifiedIndex: 1,
 | 
				
			||||||
 | 
									CreatedIndex:  1,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_, err := registry.Delete(ctx, name, nil)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("unexpected error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										87
									
								
								pkg/registry/persistentvolumeclaim/registry.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								pkg/registry/persistentvolumeclaim/registry.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,87 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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 persistentvolumeclaim
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Registry is an interface implemented by things that know how to store PersistentVolumeClaim objects.
 | 
				
			||||||
 | 
					type Registry interface {
 | 
				
			||||||
 | 
						// ListPersistentVolumeClaims obtains a list of PVCs having labels which match selector.
 | 
				
			||||||
 | 
						ListPersistentVolumeClaims(ctx api.Context, selector labels.Selector) (*api.PersistentVolumeClaimList, error)
 | 
				
			||||||
 | 
						// Watch for new/changed/deleted PVCs
 | 
				
			||||||
 | 
						WatchPersistentVolumeClaims(ctx api.Context, label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error)
 | 
				
			||||||
 | 
						// Get a specific PVC
 | 
				
			||||||
 | 
						GetPersistentVolumeClaim(ctx api.Context, pvcID string) (*api.PersistentVolumeClaim, error)
 | 
				
			||||||
 | 
						// Create a PVC based on a specification.
 | 
				
			||||||
 | 
						CreatePersistentVolumeClaim(ctx api.Context, pvc *api.PersistentVolumeClaim) error
 | 
				
			||||||
 | 
						// Update an existing PVC
 | 
				
			||||||
 | 
						UpdatePersistentVolumeClaim(ctx api.Context, pvc *api.PersistentVolumeClaim) error
 | 
				
			||||||
 | 
						// Delete an existing PVC
 | 
				
			||||||
 | 
						DeletePersistentVolumeClaim(ctx api.Context, pvcID string) error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// storage puts strong typing around storage calls
 | 
				
			||||||
 | 
					type storage struct {
 | 
				
			||||||
 | 
						rest.StandardStorage
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewRegistry returns a new Registry interface for the given Storage. Any mismatched
 | 
				
			||||||
 | 
					// types will panic.
 | 
				
			||||||
 | 
					func NewRegistry(s rest.StandardStorage) Registry {
 | 
				
			||||||
 | 
						return &storage{s}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *storage) ListPersistentVolumeClaims(ctx api.Context, label labels.Selector) (*api.PersistentVolumeClaimList, error) {
 | 
				
			||||||
 | 
						obj, err := s.List(ctx, label, fields.Everything())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return obj.(*api.PersistentVolumeClaimList), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *storage) WatchPersistentVolumeClaims(ctx api.Context, label labels.Selector, field fields.Selector, resourceVersion string) (watch.Interface, error) {
 | 
				
			||||||
 | 
						return s.Watch(ctx, label, field, resourceVersion)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *storage) GetPersistentVolumeClaim(ctx api.Context, podID string) (*api.PersistentVolumeClaim, error) {
 | 
				
			||||||
 | 
						obj, err := s.Get(ctx, podID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return obj.(*api.PersistentVolumeClaim), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *storage) CreatePersistentVolumeClaim(ctx api.Context, pod *api.PersistentVolumeClaim) error {
 | 
				
			||||||
 | 
						_, err := s.Create(ctx, pod)
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *storage) UpdatePersistentVolumeClaim(ctx api.Context, pod *api.PersistentVolumeClaim) error {
 | 
				
			||||||
 | 
						_, _, err := s.Update(ctx, pod)
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *storage) DeletePersistentVolumeClaim(ctx api.Context, podID string) error {
 | 
				
			||||||
 | 
						_, err := s.Delete(ctx, podID, nil)
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										109
									
								
								pkg/registry/persistentvolumeclaim/rest.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								pkg/registry/persistentvolumeclaim/rest.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,109 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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 persistentvolumeclaim
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/util/fielderrors"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// persistentvolumeclaimStrategy implements behavior for PersistentVolumeClaim objects
 | 
				
			||||||
 | 
					type persistentvolumeclaimStrategy struct {
 | 
				
			||||||
 | 
						runtime.ObjectTyper
 | 
				
			||||||
 | 
						api.NameGenerator
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Strategy is the default logic that applies when creating and updating PersistentVolumeClaim
 | 
				
			||||||
 | 
					// objects via the REST API.
 | 
				
			||||||
 | 
					var Strategy = persistentvolumeclaimStrategy{api.Scheme, api.SimpleNameGenerator}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NamespaceScoped is true for persistentvolumeclaims.
 | 
				
			||||||
 | 
					func (persistentvolumeclaimStrategy) NamespaceScoped() bool {
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ResetBeforeCreate clears fields that are not allowed to be set by end users on creation.
 | 
				
			||||||
 | 
					func (persistentvolumeclaimStrategy) PrepareForCreate(obj runtime.Object) {
 | 
				
			||||||
 | 
						pv := obj.(*api.PersistentVolumeClaim)
 | 
				
			||||||
 | 
						pv.Status = api.PersistentVolumeClaimStatus{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
 | 
				
			||||||
 | 
					func (persistentvolumeclaimStrategy) PrepareForUpdate(obj, old runtime.Object) {
 | 
				
			||||||
 | 
						newPvc := obj.(*api.PersistentVolumeClaim)
 | 
				
			||||||
 | 
						oldPvc := obj.(*api.PersistentVolumeClaim)
 | 
				
			||||||
 | 
						newPvc.Status = oldPvc.Status
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Validate validates a new persistentvolumeclaim.
 | 
				
			||||||
 | 
					func (persistentvolumeclaimStrategy) Validate(obj runtime.Object) fielderrors.ValidationErrorList {
 | 
				
			||||||
 | 
						pvc := obj.(*api.PersistentVolumeClaim)
 | 
				
			||||||
 | 
						return validation.ValidatePersistentVolumeClaim(pvc)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AllowCreateOnUpdate is false for persistentvolumeclaims.
 | 
				
			||||||
 | 
					func (persistentvolumeclaimStrategy) AllowCreateOnUpdate() bool {
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ValidateUpdate is the default update validation for an end user.
 | 
				
			||||||
 | 
					func (persistentvolumeclaimStrategy) ValidateUpdate(obj, old runtime.Object) fielderrors.ValidationErrorList {
 | 
				
			||||||
 | 
						return validation.ValidatePersistentVolumeClaimUpdate(obj.(*api.PersistentVolumeClaim), old.(*api.PersistentVolumeClaim))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type persistentvolumeclaimStatusStrategy struct {
 | 
				
			||||||
 | 
						persistentvolumeclaimStrategy
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var StatusStrategy = persistentvolumeclaimStatusStrategy{Strategy}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (persistentvolumeclaimStatusStrategy) PrepareForUpdate(obj, old runtime.Object) {
 | 
				
			||||||
 | 
						newPvc := obj.(*api.PersistentVolumeClaim)
 | 
				
			||||||
 | 
						oldPvc := obj.(*api.PersistentVolumeClaim)
 | 
				
			||||||
 | 
						newPvc.Spec = oldPvc.Spec
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (persistentvolumeclaimStatusStrategy) ValidateUpdate(obj, old runtime.Object) fielderrors.ValidationErrorList {
 | 
				
			||||||
 | 
						return validation.ValidatePersistentVolumeClaimStatusUpdate(obj.(*api.PersistentVolumeClaim), old.(*api.PersistentVolumeClaim))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MatchPersistentVolumeClaim returns a generic matcher for a given label and field selector.
 | 
				
			||||||
 | 
					func MatchPersistentVolumeClaim(label labels.Selector, field fields.Selector) generic.Matcher {
 | 
				
			||||||
 | 
						return generic.MatcherFunc(func(obj runtime.Object) (bool, error) {
 | 
				
			||||||
 | 
							persistentvolumeclaimObj, ok := obj.(*api.PersistentVolumeClaim)
 | 
				
			||||||
 | 
							if !ok {
 | 
				
			||||||
 | 
								return false, fmt.Errorf("not a persistentvolumeclaim")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							fields := PersistentVolumeClaimToSelectableFields(persistentvolumeclaimObj)
 | 
				
			||||||
 | 
							return label.Matches(labels.Set(persistentvolumeclaimObj.Labels)) && field.Matches(fields), nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PersistentVolumeClaimToSelectableFields returns a label set that represents the object
 | 
				
			||||||
 | 
					// TODO: fields are not labels, and the validation rules for them do not apply.
 | 
				
			||||||
 | 
					func PersistentVolumeClaimToSelectableFields(persistentvolumeclaim *api.PersistentVolumeClaim) labels.Set {
 | 
				
			||||||
 | 
						return labels.Set{
 | 
				
			||||||
 | 
							"name": persistentvolumeclaim.Name,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										54
									
								
								pkg/volume/util.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								pkg/volume/util.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					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 volume
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetAccessModesAsString(modes []api.AccessModeType) string {
 | 
				
			||||||
 | 
						modesAsString := ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if contains(modes, api.ReadWriteOnce) {
 | 
				
			||||||
 | 
							appendAccessMode(modesAsString, "RWO")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if contains(modes, api.ReadOnlyMany) {
 | 
				
			||||||
 | 
							appendAccessMode(modesAsString, "ROX")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if contains(modes, api.ReadWriteMany) {
 | 
				
			||||||
 | 
							appendAccessMode(modesAsString, "RWX")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return modesAsString
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func appendAccessMode(modes, mode string) string {
 | 
				
			||||||
 | 
						if modes != "" {
 | 
				
			||||||
 | 
							modes += ","
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						modes += mode
 | 
				
			||||||
 | 
						return modes
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func contains(modes []api.AccessModeType, mode api.AccessModeType) bool {
 | 
				
			||||||
 | 
						for _, m := range modes {
 | 
				
			||||||
 | 
							if m == mode {
 | 
				
			||||||
 | 
								return true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user