From 2829fadfad633ce28176de6ad5692bb90490a54c Mon Sep 17 00:00:00 2001 From: markturansky Date: Fri, 29 May 2015 16:12:10 -0400 Subject: [PATCH] PV Recycling API --- api/swagger-spec/v1.json | 14 +++++++++- api/swagger-spec/v1beta3.json | 17 +++++++++--- .../persistent-volumes/volumes/local-02.yaml | 3 ++- pkg/api/deep_copy_generated.go | 3 +++ pkg/api/testing/fuzzer.go | 5 +++- pkg/api/types.go | 26 +++++++++++++++++++ pkg/api/v1/conversion_generated.go | 6 +++++ pkg/api/v1/deep_copy_generated.go | 3 +++ pkg/api/v1/defaults.go | 3 +++ pkg/api/v1/defaults_test.go | 3 +++ pkg/api/v1/types.go | 26 +++++++++++++++++++ pkg/api/v1beta3/conversion_generated.go | 6 +++++ pkg/api/v1beta3/deep_copy_generated.go | 3 +++ pkg/api/v1beta3/defaults.go | 3 +++ pkg/api/v1beta3/defaults_test.go | 3 +++ pkg/api/v1beta3/types.go | 26 +++++++++++++++++++ pkg/client/persistentvolume_test.go | 3 ++- pkg/kubectl/describe.go | 2 ++ pkg/kubectl/resource_printer.go | 4 +-- .../persistentvolume/etcd/etcd_test.go | 5 +++- .../persistent_volume_claim_binder_test.go | 2 +- 21 files changed, 155 insertions(+), 11 deletions(-) diff --git a/api/swagger-spec/v1.json b/api/swagger-spec/v1.json index a4cbc6970f2..146b69c24a4 100644 --- a/api/swagger-spec/v1.json +++ b/api/swagger-spec/v1.json @@ -10603,6 +10603,10 @@ "claimRef": { "$ref": "v1.ObjectReference", "description": "when bound, a reference to the bound claim" + }, + "persistentVolumeReclaimPolicy": { + "type": "string", + "description": "persistentVolumeReclaimPolicy is what happens to a volume when released from its claim; Default is Retain." } } }, @@ -10807,6 +10811,14 @@ "phase": { "type": "string", "description": "the current phase of a persistent volume" + }, + "message": { + "type": "string", + "description": "human-readable message indicating details about why the volume is in this state" + }, + "reason": { + "type": "string", + "description": "(brief) reason the volume is not is not available, such as failed recycling" } } }, @@ -12041,4 +12053,4 @@ } } } - } \ No newline at end of file + } diff --git a/api/swagger-spec/v1beta3.json b/api/swagger-spec/v1beta3.json index ca8407ad61e..37d7aef43e7 100644 --- a/api/swagger-spec/v1beta3.json +++ b/api/swagger-spec/v1beta3.json @@ -10600,6 +10600,10 @@ "claimRef": { "$ref": "v1beta3.ObjectReference", "description": "when bound, a reference to the bound claim" + }, + "persistentVolumeReclaimPolicy": { + "type": "string", + "description": "persistentVolumeReclaimPolicy is what happens to a volume when released from its claim; Default is Retain." } } }, @@ -10804,6 +10808,14 @@ "phase": { "type": "string", "description": "the current phase of a persistent volume" + }, + "message": { + "type": "string", + "description": "human-readable message indicating details about why the volume is in this state" + }, + "reason": { + "type": "string", + "description": "(brief) reason the volume is not is not available, such as failed recycling" } } }, @@ -10862,8 +10874,7 @@ "v1beta3.PodSpec": { "id": "v1beta3.PodSpec", "required": [ - "containers", - "serviceAccount" + "containers" ], "properties": { "volumes": { @@ -12048,4 +12059,4 @@ } } } - } \ No newline at end of file + } diff --git a/examples/persistent-volumes/volumes/local-02.yaml b/examples/persistent-volumes/volumes/local-02.yaml index 24bca725390..4be4c3ce12e 100644 --- a/examples/persistent-volumes/volumes/local-02.yaml +++ b/examples/persistent-volumes/volumes/local-02.yaml @@ -6,8 +6,9 @@ metadata: type: local spec: capacity: - storage: 5Gi + storage: 8Gi accessModes: - ReadWriteOnce hostPath: path: "/tmp/data02" + persistentVolumeReclaimPolicy: Recycle diff --git a/pkg/api/deep_copy_generated.go b/pkg/api/deep_copy_generated.go index cc3202a19d3..9a72d2e1774 100644 --- a/pkg/api/deep_copy_generated.go +++ b/pkg/api/deep_copy_generated.go @@ -1243,11 +1243,14 @@ func deepCopy_api_PersistentVolumeSpec(in PersistentVolumeSpec, out *PersistentV } else { out.ClaimRef = nil } + out.PersistentVolumeReclaimPolicy = in.PersistentVolumeReclaimPolicy return nil } func deepCopy_api_PersistentVolumeStatus(in PersistentVolumeStatus, out *PersistentVolumeStatus, c *conversion.Cloner) error { out.Phase = in.Phase + out.Message = in.Message + out.Reason = in.Reason return nil } diff --git a/pkg/api/testing/fuzzer.go b/pkg/api/testing/fuzzer.go index f60d68c4cbf..f33d2e7f625 100644 --- a/pkg/api/testing/fuzzer.go +++ b/pkg/api/testing/fuzzer.go @@ -234,8 +234,11 @@ func FuzzerFor(t *testing.T, version string, src rand.Source) *fuzz.Fuzzer { }, func(pv *api.PersistentVolume, c fuzz.Continue) { c.FuzzNoCustom(pv) // fuzz self without calling this function again - types := []api.PersistentVolumePhase{api.VolumePending, api.VolumeBound, api.VolumeReleased, api.VolumeAvailable} + types := []api.PersistentVolumePhase{api.VolumeAvailable, api.VolumePending, api.VolumeBound, api.VolumeReleased, api.VolumeFailed} pv.Status.Phase = types[c.Rand.Intn(len(types))] + pv.Status.Message = c.RandString() + reclamationPolicies := []api.PersistentVolumeReclaimPolicy{api.PersistentVolumeReclaimRecycle, api.PersistentVolumeReclaimRetain} + pv.Spec.PersistentVolumeReclaimPolicy = reclamationPolicies[c.Rand.Intn(len(reclamationPolicies))] }, func(pvc *api.PersistentVolumeClaim, c fuzz.Continue) { c.FuzzNoCustom(pvc) // fuzz self without calling this function again diff --git a/pkg/api/types.go b/pkg/api/types.go index a016ff25a94..370124f0dc3 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -263,11 +263,33 @@ type PersistentVolumeSpec struct { // ClaimRef is expected to be non-nil when bound. // claim.VolumeName is the authoritative bind between PV and PVC. ClaimRef *ObjectReference `json:"claimRef,omitempty"` + // Optional: what happens to a persistent volume when released from its claim. + PersistentVolumeReclaimPolicy PersistentVolumeReclaimPolicy `json:"persistentVolumeReclaimPolicy,omitempty" description:"what happens to a volume when released from its claim; Valid options are Retain (default) and Recycle. Recyling must be supported by the volume plugin underlying this persistent volume."` } +// PersistentVolumeReclaimPolicy describes a policy for end-of-life maintenance of persistent volumes +type PersistentVolumeReclaimPolicy string + +const ( + // PersistentVolumeReclaimRecycle means the volume will be recycled back into the pool of unbound persistent volumes on release from its claim. + // The volume plugin must support Recycling. + PersistentVolumeReclaimRecycle PersistentVolumeReclaimPolicy = "Recycle" + // PersistentVolumeReclaimDelete means the volume will be deleted from Kubernetes on release from its claim. + // The volume plugin must support Deletion. + // TODO: implement w/ DeletableVolumePlugin + // PersistentVolumeReclaimDelete PersistentVolumeReclaimPolicy = "Delete" + // PersistentVolumeReclaimRetain means the volume will left in its current phase (Released) for manual reclamation by the administrator. + // The default policy is Retain. + PersistentVolumeReclaimRetain PersistentVolumeReclaimPolicy = "Retain" +) + type PersistentVolumeStatus struct { // Phase indicates if a volume is available, bound to a claim, or released by a claim Phase PersistentVolumePhase `json:"phase,omitempty"` + // A human-readable message indicating details about why the volume is in this state. + Message string `json:"message,omitempty"` + // Reason is a brief CamelCase string that describes any failure and is meant for machine parsing and tidy display in the CLI + Reason string `json:"reason,omitempty"` } type PersistentVolumeList struct { @@ -331,12 +353,16 @@ const ( // used for PersistentVolumes that are not available VolumePending PersistentVolumePhase = "Pending" // used for PersistentVolumes that are not yet bound + // Available volumes are held by the binder and matched to PersistentVolumeClaims VolumeAvailable PersistentVolumePhase = "Available" // used for PersistentVolumes that are bound VolumeBound PersistentVolumePhase = "Bound" // used for PersistentVolumes where the bound PersistentVolumeClaim was deleted // released volumes must be recycled before becoming available again + // this phase is used by the persistent volume claim binder to signal to another process to reclaim the resource VolumeReleased PersistentVolumePhase = "Released" + // used for PersistentVolumes that failed to be correctly recycled or deleted after being released from a claim + VolumeFailed PersistentVolumePhase = "Failed" ) type PersistentVolumeClaimPhase string diff --git a/pkg/api/v1/conversion_generated.go b/pkg/api/v1/conversion_generated.go index 2ada8393a58..1c29849e9ca 100644 --- a/pkg/api/v1/conversion_generated.go +++ b/pkg/api/v1/conversion_generated.go @@ -1358,6 +1358,7 @@ func convert_api_PersistentVolumeSpec_To_v1_PersistentVolumeSpec(in *api.Persist } else { out.ClaimRef = nil } + out.PersistentVolumeReclaimPolicy = PersistentVolumeReclaimPolicy(in.PersistentVolumeReclaimPolicy) return nil } @@ -1366,6 +1367,8 @@ func convert_api_PersistentVolumeStatus_To_v1_PersistentVolumeStatus(in *api.Per defaulting.(func(*api.PersistentVolumeStatus))(in) } out.Phase = PersistentVolumePhase(in.Phase) + out.Message = in.Message + out.Reason = in.Reason return nil } @@ -3633,6 +3636,7 @@ func convert_v1_PersistentVolumeSpec_To_api_PersistentVolumeSpec(in *PersistentV } else { out.ClaimRef = nil } + out.PersistentVolumeReclaimPolicy = api.PersistentVolumeReclaimPolicy(in.PersistentVolumeReclaimPolicy) return nil } @@ -3641,6 +3645,8 @@ func convert_v1_PersistentVolumeStatus_To_api_PersistentVolumeStatus(in *Persist defaulting.(func(*PersistentVolumeStatus))(in) } out.Phase = api.PersistentVolumePhase(in.Phase) + out.Message = in.Message + out.Reason = in.Reason return nil } diff --git a/pkg/api/v1/deep_copy_generated.go b/pkg/api/v1/deep_copy_generated.go index d724895bf8c..978d3652be3 100644 --- a/pkg/api/v1/deep_copy_generated.go +++ b/pkg/api/v1/deep_copy_generated.go @@ -1174,11 +1174,14 @@ func deepCopy_v1_PersistentVolumeSpec(in PersistentVolumeSpec, out *PersistentVo } else { out.ClaimRef = nil } + out.PersistentVolumeReclaimPolicy = in.PersistentVolumeReclaimPolicy return nil } func deepCopy_v1_PersistentVolumeStatus(in PersistentVolumeStatus, out *PersistentVolumeStatus, c *conversion.Cloner) error { out.Phase = in.Phase + out.Message = in.Message + out.Reason = in.Reason return nil } diff --git a/pkg/api/v1/defaults.go b/pkg/api/v1/defaults.go index cfc8a1fdec9..59b0e8dd450 100644 --- a/pkg/api/v1/defaults.go +++ b/pkg/api/v1/defaults.go @@ -113,6 +113,9 @@ func addDefaultingFuncs() { if obj.Status.Phase == "" { obj.Status.Phase = VolumePending } + if obj.Spec.PersistentVolumeReclaimPolicy == "" { + obj.Spec.PersistentVolumeReclaimPolicy = PersistentVolumeReclaimRetain + } }, func(obj *PersistentVolumeClaim) { if obj.Status.Phase == "" { diff --git a/pkg/api/v1/defaults_test.go b/pkg/api/v1/defaults_test.go index a359ee0de10..a7d8d51b4a0 100644 --- a/pkg/api/v1/defaults_test.go +++ b/pkg/api/v1/defaults_test.go @@ -258,6 +258,9 @@ func TestSetDefaultPersistentVolume(t *testing.T) { if pv2.Status.Phase != versioned.VolumePending { t.Errorf("Expected volume phase %v, got %v", versioned.VolumePending, pv2.Status.Phase) } + if pv2.Spec.PersistentVolumeReclaimPolicy != versioned.PersistentVolumeReclaimRetain { + t.Errorf("Expected pv reclaim policy %v, got %v", versioned.PersistentVolumeReclaimRetain, pv2.Spec.PersistentVolumeReclaimPolicy) + } } func TestSetDefaultPersistentVolumeClaim(t *testing.T) { diff --git a/pkg/api/v1/types.go b/pkg/api/v1/types.go index 63b17d0a8c4..4a857cbd239 100644 --- a/pkg/api/v1/types.go +++ b/pkg/api/v1/types.go @@ -280,11 +280,33 @@ type PersistentVolumeSpec struct { // ClaimRef is expected to be non-nil when bound. // claim.VolumeName is the authoritative bind between PV and PVC. ClaimRef *ObjectReference `json:"claimRef,omitempty" description:"when bound, a reference to the bound claim"` + // Optional: what happens to a persistent volume when released from its claim. + PersistentVolumeReclaimPolicy PersistentVolumeReclaimPolicy `json:"persistentVolumeReclaimPolicy,omitempty" description:"what happens to a volume when released from its claim; Valid options are Retain (default) and Recycle. Recyling must be supported by the volume plugin underlying this persistent volume."` } +// PersistentVolumeReclaimPolicy describes a policy for end-of-life maintenance of persistent volumes +type PersistentVolumeReclaimPolicy string + +const ( + // PersistentVolumeReclaimRecycle means the volume will be recycled back into the pool of unbound persistent volumes on release from its claim. + // The volume plugin must support Recycling. + PersistentVolumeReclaimRecycle PersistentVolumeReclaimPolicy = "Recycle" + // PersistentVolumeReclaimDelete means the volume will be deleted from Kubernetes on release from its claim. + // The volume plugin must support Deletion. + // TODO: implement w/ DeletableVolumePlugin + // PersistentVolumeReclaimDelete PersistentVolumeReclaimPolicy = "Delete" + // PersistentVolumeReclaimRetain means the volume will left in its current phase (Released) for manual reclamation by the administrator. + // The default policy is Retain. + PersistentVolumeReclaimRetain PersistentVolumeReclaimPolicy = "Retain" +) + type PersistentVolumeStatus struct { // Phase indicates if a volume is available, bound to a claim, or released by a claim Phase PersistentVolumePhase `json:"phase,omitempty" description:"the current phase of a persistent volume"` + // A human-readable message indicating details about why the volume is in this state. + Message string `json:"message,omitempty" description:"human-readable message indicating details about why the volume is in this state"` + // Reason is a brief CamelCase string that describes any failure and is meant for machine parsing and tidy display in the CLI + Reason string `json:"reason,omitempty" description:"(brief) reason the volume is not is not available"` } type PersistentVolumeList struct { @@ -348,12 +370,16 @@ const ( // used for PersistentVolumes that are not available VolumePending PersistentVolumePhase = "Pending" // used for PersistentVolumes that are not yet bound + // Available volumes are held by the binder and matched to PersistentVolumeClaims VolumeAvailable PersistentVolumePhase = "Available" // used for PersistentVolumes that are bound VolumeBound PersistentVolumePhase = "Bound" // used for PersistentVolumes where the bound PersistentVolumeClaim was deleted // released volumes must be recycled before becoming available again + // this phase is used by the persistent volume claim binder to signal to another process to reclaim the resource VolumeReleased PersistentVolumePhase = "Released" + // used for PersistentVolumes that failed to be correctly recycled or deleted after being released from a claim + VolumeFailed PersistentVolumePhase = "Failed" ) type PersistentVolumeClaimPhase string diff --git a/pkg/api/v1beta3/conversion_generated.go b/pkg/api/v1beta3/conversion_generated.go index 4799a52ac35..5baa0dc65a5 100644 --- a/pkg/api/v1beta3/conversion_generated.go +++ b/pkg/api/v1beta3/conversion_generated.go @@ -1216,6 +1216,7 @@ func convert_api_PersistentVolumeSpec_To_v1beta3_PersistentVolumeSpec(in *api.Pe } else { out.ClaimRef = nil } + out.PersistentVolumeReclaimPolicy = PersistentVolumeReclaimPolicy(in.PersistentVolumeReclaimPolicy) return nil } @@ -1224,6 +1225,8 @@ func convert_api_PersistentVolumeStatus_To_v1beta3_PersistentVolumeStatus(in *ap defaulting.(func(*api.PersistentVolumeStatus))(in) } out.Phase = PersistentVolumePhase(in.Phase) + out.Message = in.Message + out.Reason = in.Reason return nil } @@ -3305,6 +3308,7 @@ func convert_v1beta3_PersistentVolumeSpec_To_api_PersistentVolumeSpec(in *Persis } else { out.ClaimRef = nil } + out.PersistentVolumeReclaimPolicy = api.PersistentVolumeReclaimPolicy(in.PersistentVolumeReclaimPolicy) return nil } @@ -3313,6 +3317,8 @@ func convert_v1beta3_PersistentVolumeStatus_To_api_PersistentVolumeStatus(in *Pe defaulting.(func(*PersistentVolumeStatus))(in) } out.Phase = api.PersistentVolumePhase(in.Phase) + out.Message = in.Message + out.Reason = in.Reason return nil } diff --git a/pkg/api/v1beta3/deep_copy_generated.go b/pkg/api/v1beta3/deep_copy_generated.go index 19f5f118c38..441f4ef5ec3 100644 --- a/pkg/api/v1beta3/deep_copy_generated.go +++ b/pkg/api/v1beta3/deep_copy_generated.go @@ -1178,11 +1178,14 @@ func deepCopy_v1beta3_PersistentVolumeSpec(in PersistentVolumeSpec, out *Persist } else { out.ClaimRef = nil } + out.PersistentVolumeReclaimPolicy = in.PersistentVolumeReclaimPolicy return nil } func deepCopy_v1beta3_PersistentVolumeStatus(in PersistentVolumeStatus, out *PersistentVolumeStatus, c *conversion.Cloner) error { out.Phase = in.Phase + out.Message = in.Message + out.Reason = in.Reason return nil } diff --git a/pkg/api/v1beta3/defaults.go b/pkg/api/v1beta3/defaults.go index d542e5f3047..c8fb0d51e75 100644 --- a/pkg/api/v1beta3/defaults.go +++ b/pkg/api/v1beta3/defaults.go @@ -117,6 +117,9 @@ func addDefaultingFuncs() { if obj.Status.Phase == "" { obj.Status.Phase = VolumePending } + if obj.Spec.PersistentVolumeReclaimPolicy == "" { + obj.Spec.PersistentVolumeReclaimPolicy = PersistentVolumeReclaimRetain + } }, func(obj *PersistentVolumeClaim) { if obj.Status.Phase == "" { diff --git a/pkg/api/v1beta3/defaults_test.go b/pkg/api/v1beta3/defaults_test.go index 745be4c4f9f..058cfcd955c 100644 --- a/pkg/api/v1beta3/defaults_test.go +++ b/pkg/api/v1beta3/defaults_test.go @@ -195,6 +195,9 @@ func TestSetDefaultPersistentVolume(t *testing.T) { if pv2.Status.Phase != versioned.VolumePending { t.Errorf("Expected volume phase %v, got %v", versioned.VolumePending, pv2.Status.Phase) } + if pv2.Spec.PersistentVolumeReclaimPolicy != versioned.PersistentVolumeReclaimRetain { + t.Errorf("Expected pv reclaim policy %v, got %v", versioned.PersistentVolumeReclaimRetain, pv2.Spec.PersistentVolumeReclaimPolicy) + } } func TestSetDefaultPersistentVolumeClaim(t *testing.T) { diff --git a/pkg/api/v1beta3/types.go b/pkg/api/v1beta3/types.go index 3cab8697bfd..db5a64d4a63 100644 --- a/pkg/api/v1beta3/types.go +++ b/pkg/api/v1beta3/types.go @@ -280,11 +280,33 @@ type PersistentVolumeSpec struct { // ClaimRef is expected to be non-nil when bound. // claim.VolumeName is the authoritative bind between PV and PVC. ClaimRef *ObjectReference `json:"claimRef,omitempty" description:"when bound, a reference to the bound claim"` + // Optional: what happens to a persistent volume when released from its claim. + PersistentVolumeReclaimPolicy PersistentVolumeReclaimPolicy `json:"persistentVolumeReclaimPolicy,omitempty" description:"what happens to a volume when released from its claim; Valid options are Retain (default) and Recycle. Recyling must be supported by the volume plugin underlying this persistent volume."` } +// PersistentVolumeReclaimPolicy describes a policy for end-of-life maintenance of persistent volumes +type PersistentVolumeReclaimPolicy string + +const ( + // PersistentVolumeReclaimRecycle means the volume will be recycled back into the pool of unbound persistent volumes on release from its claim. + // The volume plugin must support Recycling. + PersistentVolumeReclaimRecycle PersistentVolumeReclaimPolicy = "Recycle" + // PersistentVolumeReclaimDelete means the volume will be deleted from Kubernetes on release from its claim. + // The volume plugin must support Deletion. + // TODO: implement w/ DeletableVolumePlugin + // PersistentVolumeReclaimDelete PersistentVolumeReclaimPolicy = "Delete" + // PersistentVolumeReclaimRetain means the volume will left in its current phase (Released) for manual reclamation by the administrator. + // The default policy is Retain. + PersistentVolumeReclaimRetain PersistentVolumeReclaimPolicy = "Retain" +) + type PersistentVolumeStatus struct { // Phase indicates if a volume is available, bound to a claim, or released by a claim Phase PersistentVolumePhase `json:"phase,omitempty" description:"the current phase of a persistent volume"` + // A human-readable message indicating details about why the volume is in this state. + Message string `json:"message,omitempty" description:"human-readable message indicating details about why the volume is in this state"` + // Reason is a brief CamelCase string that describes any failure and is meant for machine parsing and tidy display in the CLI + Reason string `json:"reason,omitempty" description:"(brief) reason the volume is not is not available"` } type PersistentVolumeList struct { @@ -348,12 +370,16 @@ const ( // used for PersistentVolumes that are not available VolumePending PersistentVolumePhase = "Pending" // used for PersistentVolumes that are not yet bound + // Available volumes are held by the binder and matched to PersistentVolumeClaims VolumeAvailable PersistentVolumePhase = "Available" // used for PersistentVolumes that are bound VolumeBound PersistentVolumePhase = "Bound" // used for PersistentVolumes where the bound PersistentVolumeClaim was deleted // released volumes must be recycled before becoming available again + // this phase is used by the persistent volume claim binder to signal to another process to reclaim the resource VolumeReleased PersistentVolumePhase = "Released" + // used for PersistentVolumes that failed to be correctly recycled or deleted after being released from a claim + VolumeFailed PersistentVolumePhase = "Failed" ) type PersistentVolumeClaimPhase string diff --git a/pkg/client/persistentvolume_test.go b/pkg/client/persistentvolume_test.go index f299ed9d893..3c319fb4c24 100644 --- a/pkg/client/persistentvolume_test.go +++ b/pkg/client/persistentvolume_test.go @@ -151,7 +151,8 @@ func TestPersistentVolumeStatusUpdate(t *testing.T) { }, }, Status: api.PersistentVolumeStatus{ - Phase: api.VolumeBound, + Phase: api.VolumeBound, + Message: "foo", }, } c := &testClient{ diff --git a/pkg/kubectl/describe.go b/pkg/kubectl/describe.go index a3947047e59..5901441b051 100644 --- a/pkg/kubectl/describe.go +++ b/pkg/kubectl/describe.go @@ -311,6 +311,8 @@ func (d *PersistentVolumeDescriber) Describe(namespace, name string) (string, er } else { fmt.Fprintf(out, "Claim:\t%s\n", "") } + fmt.Fprintf(out, "Reclaim Policy:\t%d\n", pv.Spec.PersistentVolumeReclaimPolicy) + fmt.Fprintf(out, "Message:\t%d\n", pv.Status.Message) return nil }) } diff --git a/pkg/kubectl/resource_printer.go b/pkg/kubectl/resource_printer.go index 90ad20f3ef8..e0f17a9ecc1 100644 --- a/pkg/kubectl/resource_printer.go +++ b/pkg/kubectl/resource_printer.go @@ -259,7 +259,7 @@ var resourceQuotaColumns = []string{"NAME"} var namespaceColumns = []string{"NAME", "LABELS", "STATUS"} var secretColumns = []string{"NAME", "TYPE", "DATA"} var serviceAccountColumns = []string{"NAME", "SECRETS"} -var persistentVolumeColumns = []string{"NAME", "LABELS", "CAPACITY", "ACCESSMODES", "STATUS", "CLAIM"} +var persistentVolumeColumns = []string{"NAME", "LABELS", "CAPACITY", "ACCESSMODES", "STATUS", "CLAIM", "REASON"} var persistentVolumeClaimColumns = []string{"NAME", "LABELS", "STATUS", "VOLUME"} var componentStatusColumns = []string{"NAME", "STATUS", "MESSAGE", "ERROR"} @@ -732,7 +732,7 @@ func printPersistentVolume(pv *api.PersistentVolume, w io.Writer, withNamespace 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", name, formatLabels(pv.Labels), aSize, modesStr, pv.Status.Phase, claimRefUID) + _, err := fmt.Fprintf(w, "%s\t%s\t%d\t%s\t%s\t%s\t%s\n", name, formatLabels(pv.Labels), aSize, modesStr, pv.Status.Phase, claimRefUID, pv.Status.Reason) return err } diff --git a/pkg/registry/persistentvolume/etcd/etcd_test.go b/pkg/registry/persistentvolume/etcd/etcd_test.go index 0ce3d2912ad..37afbfd57a6 100644 --- a/pkg/registry/persistentvolume/etcd/etcd_test.go +++ b/pkg/registry/persistentvolume/etcd/etcd_test.go @@ -59,9 +59,12 @@ func validNewPersistentVolume(name string) *api.PersistentVolume { PersistentVolumeSource: api.PersistentVolumeSource{ HostPath: &api.HostPathVolumeSource{Path: "/foo"}, }, + PersistentVolumeReclaimPolicy: api.PersistentVolumeReclaimRetain, }, Status: api.PersistentVolumeStatus{ - Phase: api.VolumePending, + Phase: api.VolumePending, + Message: "bar", + Reason: "foo", }, } return pv diff --git a/pkg/volumeclaimbinder/persistent_volume_claim_binder_test.go b/pkg/volumeclaimbinder/persistent_volume_claim_binder_test.go index 8032c118736..cd21f0c942c 100644 --- a/pkg/volumeclaimbinder/persistent_volume_claim_binder_test.go +++ b/pkg/volumeclaimbinder/persistent_volume_claim_binder_test.go @@ -98,7 +98,7 @@ func TestExampleObjects(t *testing.T) { Spec: api.PersistentVolumeSpec{ AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("5Gi"), + api.ResourceName(api.ResourceStorage): resource.MustParse("8Gi"), }, PersistentVolumeSource: api.PersistentVolumeSource{ HostPath: &api.HostPathVolumeSource{