Merge pull request #47987 from wongma7/reclaimpolicy
Automatic merge from submit-queue (batch tested with PRs 49869, 47987, 50211, 50804, 50583) Add ReclaimPolicy field to StorageClass fix https://github.com/kubernetes/kubernetes/issues/38192, enough people want this imo so going ahead and adding it according to initial suggested design some considerations: * No Recycle allowed, Retain (& Delete) only. * Do we need to gate the field. * E2E test where a Retain PV is dynamically provisioned is TODO if we agree we want this & this is the way to do it. * Need a feature repo issue to track docs and stuff for 1.8 **Release note**: ```release-note StorageClass has a new field to configure reclaim policy of dynamically provisioned PVs. ```
This commit is contained in:
@@ -14,6 +14,7 @@ go_library(
|
||||
"zz_generated.deepcopy.go",
|
||||
],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
|
@@ -8,7 +8,12 @@ load(
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["fuzzer.go"],
|
||||
deps = ["//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/apis/storage:go_default_library",
|
||||
"//vendor/github.com/google/gofuzz:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
|
@@ -17,10 +17,20 @@ limitations under the License.
|
||||
package fuzzer
|
||||
|
||||
import (
|
||||
fuzz "github.com/google/gofuzz"
|
||||
|
||||
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
)
|
||||
|
||||
// Funcs returns the fuzzer functions for the storage api group.
|
||||
var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
|
||||
return []interface{}{}
|
||||
return []interface{}{
|
||||
func(obj *storage.StorageClass, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(obj) // fuzz self without calling this function again
|
||||
reclamationPolicies := []api.PersistentVolumeReclaimPolicy{api.PersistentVolumeReclaimDelete, api.PersistentVolumeReclaimRetain}
|
||||
obj.ReclaimPolicy = &reclamationPolicies[c.Rand.Intn(len(reclamationPolicies))]
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@@ -16,7 +16,10 @@ limitations under the License.
|
||||
|
||||
package storage
|
||||
|
||||
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
// +genclient
|
||||
// +genclient:nonNamespaced
|
||||
@@ -46,6 +49,11 @@ type StorageClass struct {
|
||||
// 512, with a cumulative max size of 256K
|
||||
// +optional
|
||||
Parameters map[string]string
|
||||
|
||||
// reclaimPolicy is the reclaim policy that dynamically provisioned
|
||||
// PersistentVolumes of this storage class are created with
|
||||
// +optional
|
||||
ReclaimPolicy *api.PersistentVolumeReclaimPolicy
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
@@ -8,13 +8,16 @@ load(
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"defaults.go",
|
||||
"doc.go",
|
||||
"register.go",
|
||||
"zz_generated.conversion.go",
|
||||
"zz_generated.defaults.go",
|
||||
],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/apis/storage:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/storage/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
|
34
pkg/apis/storage/v1/defaults.go
Normal file
34
pkg/apis/storage/v1/defaults.go
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
storagev1 "k8s.io/api/storage/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
func addDefaultingFuncs(scheme *runtime.Scheme) error {
|
||||
return RegisterDefaults(scheme)
|
||||
}
|
||||
|
||||
func SetDefaults_StorageClass(obj *storagev1.StorageClass) {
|
||||
if obj.ReclaimPolicy == nil {
|
||||
obj.ReclaimPolicy = new(v1.PersistentVolumeReclaimPolicy)
|
||||
*obj.ReclaimPolicy = v1.PersistentVolumeReclaimDelete
|
||||
}
|
||||
}
|
@@ -41,5 +41,5 @@ func init() {
|
||||
// We only register manually written functions here. The registration of the
|
||||
// generated functions takes place in the generated files. The separation
|
||||
// makes the code compile even when the generated files are missing.
|
||||
localSchemeBuilder.Register(RegisterDefaults)
|
||||
localSchemeBuilder.Register(addDefaultingFuncs)
|
||||
}
|
||||
|
@@ -21,9 +21,11 @@ limitations under the License.
|
||||
package v1
|
||||
|
||||
import (
|
||||
core_v1 "k8s.io/api/core/v1"
|
||||
v1 "k8s.io/api/storage/v1"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
api "k8s.io/kubernetes/pkg/api"
|
||||
storage "k8s.io/kubernetes/pkg/apis/storage"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
@@ -47,6 +49,7 @@ func autoConvert_v1_StorageClass_To_storage_StorageClass(in *v1.StorageClass, ou
|
||||
out.ObjectMeta = in.ObjectMeta
|
||||
out.Provisioner = in.Provisioner
|
||||
out.Parameters = *(*map[string]string)(unsafe.Pointer(&in.Parameters))
|
||||
out.ReclaimPolicy = (*api.PersistentVolumeReclaimPolicy)(unsafe.Pointer(in.ReclaimPolicy))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -59,6 +62,7 @@ func autoConvert_storage_StorageClass_To_v1_StorageClass(in *storage.StorageClas
|
||||
out.ObjectMeta = in.ObjectMeta
|
||||
out.Provisioner = in.Provisioner
|
||||
out.Parameters = *(*map[string]string)(unsafe.Pointer(&in.Parameters))
|
||||
out.ReclaimPolicy = (*core_v1.PersistentVolumeReclaimPolicy)(unsafe.Pointer(in.ReclaimPolicy))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@@ -21,6 +21,7 @@ limitations under the License.
|
||||
package v1
|
||||
|
||||
import (
|
||||
v1 "k8s.io/api/storage/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
@@ -28,5 +29,18 @@ import (
|
||||
// Public to allow building arbitrary schemes.
|
||||
// All generated defaulters are covering - they call all nested defaulters.
|
||||
func RegisterDefaults(scheme *runtime.Scheme) error {
|
||||
scheme.AddTypeDefaultingFunc(&v1.StorageClass{}, func(obj interface{}) { SetObjectDefaults_StorageClass(obj.(*v1.StorageClass)) })
|
||||
scheme.AddTypeDefaultingFunc(&v1.StorageClassList{}, func(obj interface{}) { SetObjectDefaults_StorageClassList(obj.(*v1.StorageClassList)) })
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetObjectDefaults_StorageClass(in *v1.StorageClass) {
|
||||
SetDefaults_StorageClass(in)
|
||||
}
|
||||
|
||||
func SetObjectDefaults_StorageClassList(in *v1.StorageClassList) {
|
||||
for i := range in.Items {
|
||||
a := &in.Items[i]
|
||||
SetObjectDefaults_StorageClass(a)
|
||||
}
|
||||
}
|
||||
|
@@ -8,13 +8,16 @@ load(
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"defaults.go",
|
||||
"doc.go",
|
||||
"register.go",
|
||||
"zz_generated.conversion.go",
|
||||
"zz_generated.defaults.go",
|
||||
],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/apis/storage:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/storage/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
|
34
pkg/apis/storage/v1beta1/defaults.go
Normal file
34
pkg/apis/storage/v1beta1/defaults.go
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
storagev1beta1 "k8s.io/api/storage/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
func addDefaultingFuncs(scheme *runtime.Scheme) error {
|
||||
return RegisterDefaults(scheme)
|
||||
}
|
||||
|
||||
func SetDefaults_StorageClass(obj *storagev1beta1.StorageClass) {
|
||||
if obj.ReclaimPolicy == nil {
|
||||
obj.ReclaimPolicy = new(v1.PersistentVolumeReclaimPolicy)
|
||||
*obj.ReclaimPolicy = v1.PersistentVolumeReclaimDelete
|
||||
}
|
||||
}
|
@@ -41,5 +41,5 @@ func init() {
|
||||
// We only register manually written functions here. The registration of the
|
||||
// generated functions takes place in the generated files. The separation
|
||||
// makes the code compile even when the generated files are missing.
|
||||
localSchemeBuilder.Register(RegisterDefaults)
|
||||
localSchemeBuilder.Register(addDefaultingFuncs)
|
||||
}
|
||||
|
@@ -21,9 +21,11 @@ limitations under the License.
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
v1 "k8s.io/api/core/v1"
|
||||
v1beta1 "k8s.io/api/storage/v1beta1"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
api "k8s.io/kubernetes/pkg/api"
|
||||
storage "k8s.io/kubernetes/pkg/apis/storage"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
@@ -47,6 +49,7 @@ func autoConvert_v1beta1_StorageClass_To_storage_StorageClass(in *v1beta1.Storag
|
||||
out.ObjectMeta = in.ObjectMeta
|
||||
out.Provisioner = in.Provisioner
|
||||
out.Parameters = *(*map[string]string)(unsafe.Pointer(&in.Parameters))
|
||||
out.ReclaimPolicy = (*api.PersistentVolumeReclaimPolicy)(unsafe.Pointer(in.ReclaimPolicy))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -59,6 +62,7 @@ func autoConvert_storage_StorageClass_To_v1beta1_StorageClass(in *storage.Storag
|
||||
out.ObjectMeta = in.ObjectMeta
|
||||
out.Provisioner = in.Provisioner
|
||||
out.Parameters = *(*map[string]string)(unsafe.Pointer(&in.Parameters))
|
||||
out.ReclaimPolicy = (*v1.PersistentVolumeReclaimPolicy)(unsafe.Pointer(in.ReclaimPolicy))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@@ -21,6 +21,7 @@ limitations under the License.
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
v1beta1 "k8s.io/api/storage/v1beta1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
@@ -28,5 +29,18 @@ import (
|
||||
// Public to allow building arbitrary schemes.
|
||||
// All generated defaulters are covering - they call all nested defaulters.
|
||||
func RegisterDefaults(scheme *runtime.Scheme) error {
|
||||
scheme.AddTypeDefaultingFunc(&v1beta1.StorageClass{}, func(obj interface{}) { SetObjectDefaults_StorageClass(obj.(*v1beta1.StorageClass)) })
|
||||
scheme.AddTypeDefaultingFunc(&v1beta1.StorageClassList{}, func(obj interface{}) { SetObjectDefaults_StorageClassList(obj.(*v1beta1.StorageClassList)) })
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetObjectDefaults_StorageClass(in *v1beta1.StorageClass) {
|
||||
SetDefaults_StorageClass(in)
|
||||
}
|
||||
|
||||
func SetObjectDefaults_StorageClassList(in *v1beta1.StorageClassList) {
|
||||
for i := range in.Items {
|
||||
a := &in.Items[i]
|
||||
SetObjectDefaults_StorageClass(a)
|
||||
}
|
||||
}
|
||||
|
@@ -10,8 +10,10 @@ go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["validation.go"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/validation:go_default_library",
|
||||
"//pkg/apis/storage:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||
],
|
||||
@@ -22,6 +24,7 @@ go_test(
|
||||
srcs = ["validation_test.go"],
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/apis/storage:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
],
|
||||
|
@@ -20,8 +20,10 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/validation"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
apivalidation "k8s.io/kubernetes/pkg/api/validation"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
)
|
||||
@@ -31,6 +33,7 @@ func ValidateStorageClass(storageClass *storage.StorageClass) field.ErrorList {
|
||||
allErrs := apivalidation.ValidateObjectMeta(&storageClass.ObjectMeta, false, apivalidation.ValidateClassName, field.NewPath("metadata"))
|
||||
allErrs = append(allErrs, validateProvisioner(storageClass.Provisioner, field.NewPath("provisioner"))...)
|
||||
allErrs = append(allErrs, validateParameters(storageClass.Parameters, field.NewPath("parameters"))...)
|
||||
allErrs = append(allErrs, validateReclaimPolicy(storageClass.ReclaimPolicy, field.NewPath("reclaimPolicy"))...)
|
||||
|
||||
return allErrs
|
||||
}
|
||||
@@ -45,6 +48,10 @@ func ValidateStorageClassUpdate(storageClass, oldStorageClass *storage.StorageCl
|
||||
if storageClass.Provisioner != oldStorageClass.Provisioner {
|
||||
allErrs = append(allErrs, field.Forbidden(field.NewPath("provisioner"), "updates to provisioner are forbidden."))
|
||||
}
|
||||
|
||||
if *storageClass.ReclaimPolicy != *oldStorageClass.ReclaimPolicy {
|
||||
allErrs = append(allErrs, field.Forbidden(field.NewPath("reclaimPolicy"), "updates to reclaimPolicy are forbidden."))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
@@ -87,3 +94,17 @@ func validateParameters(params map[string]string, fldPath *field.Path) field.Err
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
var supportedReclaimPolicy = sets.NewString(string(api.PersistentVolumeReclaimDelete), string(api.PersistentVolumeReclaimRetain))
|
||||
|
||||
// validateReclaimPolicy tests that the reclaim policy is one of the supported. It is up to the volume plugin to reject
|
||||
// provisioning for storage classes with impossible reclaim policies, e.g. EBS is not Recyclable
|
||||
func validateReclaimPolicy(reclaimPolicy *api.PersistentVolumeReclaimPolicy, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if len(string(*reclaimPolicy)) > 0 {
|
||||
if !supportedReclaimPolicy.Has(string(*reclaimPolicy)) {
|
||||
allErrs = append(allErrs, field.NotSupported(fldPath, reclaimPolicy, supportedReclaimPolicy.List()))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
@@ -21,21 +21,27 @@ import (
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
)
|
||||
|
||||
func TestValidateStorageClass(t *testing.T) {
|
||||
deleteReclaimPolicy := api.PersistentVolumeReclaimPolicy("Delete")
|
||||
retainReclaimPolicy := api.PersistentVolumeReclaimPolicy("Retain")
|
||||
recycleReclaimPolicy := api.PersistentVolumeReclaimPolicy("Recycle")
|
||||
successCases := []storage.StorageClass{
|
||||
{
|
||||
// empty parameters
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "kubernetes.io/foo-provisioner",
|
||||
Parameters: map[string]string{},
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "kubernetes.io/foo-provisioner",
|
||||
Parameters: map[string]string{},
|
||||
ReclaimPolicy: &deleteReclaimPolicy,
|
||||
},
|
||||
{
|
||||
// nil parameters
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "kubernetes.io/foo-provisioner",
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "kubernetes.io/foo-provisioner",
|
||||
ReclaimPolicy: &deleteReclaimPolicy,
|
||||
},
|
||||
{
|
||||
// some parameters
|
||||
@@ -46,6 +52,13 @@ func TestValidateStorageClass(t *testing.T) {
|
||||
"foo-parameter": "free-form-string",
|
||||
"foo-parameter2": "{\"embedded\": \"json\", \"with\": {\"structures\":\"inside\"}}",
|
||||
},
|
||||
ReclaimPolicy: &deleteReclaimPolicy,
|
||||
},
|
||||
{
|
||||
// retain reclaimPolicy
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "kubernetes.io/foo-provisioner",
|
||||
ReclaimPolicy: &retainReclaimPolicy,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -68,12 +81,14 @@ func TestValidateStorageClass(t *testing.T) {
|
||||
|
||||
errorCases := map[string]storage.StorageClass{
|
||||
"namespace is present": {
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"},
|
||||
Provisioner: "kubernetes.io/foo-provisioner",
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"},
|
||||
Provisioner: "kubernetes.io/foo-provisioner",
|
||||
ReclaimPolicy: &deleteReclaimPolicy,
|
||||
},
|
||||
"invalid provisioner": {
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "kubernetes.io/invalid/provisioner",
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "kubernetes.io/invalid/provisioner",
|
||||
ReclaimPolicy: &deleteReclaimPolicy,
|
||||
},
|
||||
"invalid empty parameter name": {
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
||||
@@ -81,15 +96,23 @@ func TestValidateStorageClass(t *testing.T) {
|
||||
Parameters: map[string]string{
|
||||
"": "value",
|
||||
},
|
||||
ReclaimPolicy: &deleteReclaimPolicy,
|
||||
},
|
||||
"provisioner: Required value": {
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "",
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "",
|
||||
ReclaimPolicy: &deleteReclaimPolicy,
|
||||
},
|
||||
"too long parameters": {
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "kubernetes.io/foo",
|
||||
Parameters: longParameters,
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "kubernetes.io/foo",
|
||||
Parameters: longParameters,
|
||||
ReclaimPolicy: &deleteReclaimPolicy,
|
||||
},
|
||||
"invalid reclaimpolicy": {
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
||||
Provisioner: "kubernetes.io/foo",
|
||||
ReclaimPolicy: &recycleReclaimPolicy,
|
||||
},
|
||||
}
|
||||
|
||||
|
@@ -23,6 +23,7 @@ package storage
|
||||
import (
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
api "k8s.io/kubernetes/pkg/api"
|
||||
reflect "reflect"
|
||||
)
|
||||
|
||||
@@ -59,6 +60,15 @@ func (in *StorageClass) DeepCopyInto(out *StorageClass) {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.ReclaimPolicy != nil {
|
||||
in, out := &in.ReclaimPolicy, &out.ReclaimPolicy
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(api.PersistentVolumeReclaimPolicy)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user