diff --git a/pkg/apis/apps/v1/conversion.go b/pkg/apis/apps/v1/conversion.go index a2ce0f19eaa..ff789eb88da 100644 --- a/pkg/apis/apps/v1/conversion.go +++ b/pkg/apis/apps/v1/conversion.go @@ -21,8 +21,10 @@ import ( "strconv" appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/conversion" "k8s.io/kubernetes/pkg/apis/apps" + "k8s.io/kubernetes/pkg/apis/core" k8s_api_v1 "k8s.io/kubernetes/pkg/apis/core/v1" ) @@ -198,3 +200,45 @@ func deepCopyStringMap(m map[string]string) map[string]string { } return ret } + +// Convert_apps_StatefulSetSpec_To_v1_StatefulSetSpec augments auto-conversion to preserve < 1.17 behavior +// setting apiVersion/kind in nested persistent volume claim objects. +func Convert_v1_StatefulSetSpec_To_apps_StatefulSetSpec(in *appsv1.StatefulSetSpec, out *apps.StatefulSetSpec, s conversion.Scope) error { + if err := autoConvert_v1_StatefulSetSpec_To_apps_StatefulSetSpec(in, out, s); err != nil { + return err + } + // set APIVersion/Kind to behave the same as reflective conversion < 1.17. + // see http://issue.k8s.io/87583 + if out.VolumeClaimTemplates != nil { + // copy so we don't modify the input + templatesCopy := make([]core.PersistentVolumeClaim, len(out.VolumeClaimTemplates)) + copy(templatesCopy, out.VolumeClaimTemplates) + out.VolumeClaimTemplates = templatesCopy + for i := range out.VolumeClaimTemplates { + out.VolumeClaimTemplates[i].APIVersion = "" + out.VolumeClaimTemplates[i].Kind = "" + } + } + return nil +} + +// Convert_apps_StatefulSetSpec_To_v1_StatefulSetSpec augments auto-conversion to preserve < 1.17 behavior +// setting apiVersion/kind in nested persistent volume claim objects. +func Convert_apps_StatefulSetSpec_To_v1_StatefulSetSpec(in *apps.StatefulSetSpec, out *appsv1.StatefulSetSpec, s conversion.Scope) error { + if err := autoConvert_apps_StatefulSetSpec_To_v1_StatefulSetSpec(in, out, s); err != nil { + return err + } + // set APIVersion/Kind to behave the same as reflective conversion < 1.17. + // see http://issue.k8s.io/87583 + if out.VolumeClaimTemplates != nil { + // copy so we don't modify the input + templatesCopy := make([]corev1.PersistentVolumeClaim, len(out.VolumeClaimTemplates)) + copy(templatesCopy, out.VolumeClaimTemplates) + out.VolumeClaimTemplates = templatesCopy + for i := range out.VolumeClaimTemplates { + out.VolumeClaimTemplates[i].APIVersion = "v1" + out.VolumeClaimTemplates[i].Kind = "PersistentVolumeClaim" + } + } + return nil +} diff --git a/pkg/apis/apps/v1/zz_generated.conversion.go b/pkg/apis/apps/v1/zz_generated.conversion.go index 063d1159119..c0cda17e934 100644 --- a/pkg/apis/apps/v1/zz_generated.conversion.go +++ b/pkg/apis/apps/v1/zz_generated.conversion.go @@ -250,16 +250,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1.StatefulSetSpec)(nil), (*apps.StatefulSetSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1_StatefulSetSpec_To_apps_StatefulSetSpec(a.(*v1.StatefulSetSpec), b.(*apps.StatefulSetSpec), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*apps.StatefulSetSpec)(nil), (*v1.StatefulSetSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_apps_StatefulSetSpec_To_v1_StatefulSetSpec(a.(*apps.StatefulSetSpec), b.(*v1.StatefulSetSpec), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*v1.StatefulSetStatus)(nil), (*apps.StatefulSetStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1_StatefulSetStatus_To_apps_StatefulSetStatus(a.(*v1.StatefulSetStatus), b.(*apps.StatefulSetStatus), scope) }); err != nil { @@ -300,6 +290,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*apps.StatefulSetSpec)(nil), (*v1.StatefulSetSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_apps_StatefulSetSpec_To_v1_StatefulSetSpec(a.(*apps.StatefulSetSpec), b.(*v1.StatefulSetSpec), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*v1.DaemonSetSpec)(nil), (*apps.DaemonSetSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1_DaemonSetSpec_To_apps_DaemonSetSpec(a.(*v1.DaemonSetSpec), b.(*apps.DaemonSetSpec), scope) }); err != nil { @@ -320,6 +315,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1.StatefulSetSpec)(nil), (*apps.StatefulSetSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_StatefulSetSpec_To_apps_StatefulSetSpec(a.(*v1.StatefulSetSpec), b.(*apps.StatefulSetSpec), scope) + }); err != nil { + return err + } return nil } @@ -1155,11 +1155,6 @@ func autoConvert_v1_StatefulSetSpec_To_apps_StatefulSetSpec(in *v1.StatefulSetSp return nil } -// Convert_v1_StatefulSetSpec_To_apps_StatefulSetSpec is an autogenerated conversion function. -func Convert_v1_StatefulSetSpec_To_apps_StatefulSetSpec(in *v1.StatefulSetSpec, out *apps.StatefulSetSpec, s conversion.Scope) error { - return autoConvert_v1_StatefulSetSpec_To_apps_StatefulSetSpec(in, out, s) -} - func autoConvert_apps_StatefulSetSpec_To_v1_StatefulSetSpec(in *apps.StatefulSetSpec, out *v1.StatefulSetSpec, s conversion.Scope) error { if err := metav1.Convert_int32_To_Pointer_int32(&in.Replicas, &out.Replicas, s); err != nil { return err @@ -1178,11 +1173,6 @@ func autoConvert_apps_StatefulSetSpec_To_v1_StatefulSetSpec(in *apps.StatefulSet return nil } -// Convert_apps_StatefulSetSpec_To_v1_StatefulSetSpec is an autogenerated conversion function. -func Convert_apps_StatefulSetSpec_To_v1_StatefulSetSpec(in *apps.StatefulSetSpec, out *v1.StatefulSetSpec, s conversion.Scope) error { - return autoConvert_apps_StatefulSetSpec_To_v1_StatefulSetSpec(in, out, s) -} - func autoConvert_v1_StatefulSetStatus_To_apps_StatefulSetStatus(in *v1.StatefulSetStatus, out *apps.StatefulSetStatus, s conversion.Scope) error { if err := metav1.Convert_int64_To_Pointer_int64(&in.ObservedGeneration, &out.ObservedGeneration, s); err != nil { return err diff --git a/pkg/apis/apps/v1beta1/conversion.go b/pkg/apis/apps/v1beta1/conversion.go index ba3fbe40e17..80a63c702cd 100644 --- a/pkg/apis/apps/v1beta1/conversion.go +++ b/pkg/apis/apps/v1beta1/conversion.go @@ -20,11 +20,14 @@ import ( "fmt" appsv1beta1 "k8s.io/api/apps/v1beta1" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/conversion" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" + apps "k8s.io/kubernetes/pkg/apis/apps" "k8s.io/kubernetes/pkg/apis/autoscaling" + "k8s.io/kubernetes/pkg/apis/core" ) func addConversionFuncs(scheme *runtime.Scheme) error { @@ -76,3 +79,45 @@ func Convert_v1beta1_ScaleStatus_To_autoscaling_ScaleStatus(in *appsv1beta1.Scal } return nil } + +// Convert_v1beta1_StatefulSetSpec_To_apps_StatefulSetSpec augments auto-conversion to preserve < 1.17 behavior +// setting apiVersion/kind in nested persistent volume claim objects. +func Convert_v1beta1_StatefulSetSpec_To_apps_StatefulSetSpec(in *appsv1beta1.StatefulSetSpec, out *apps.StatefulSetSpec, s conversion.Scope) error { + if err := autoConvert_v1beta1_StatefulSetSpec_To_apps_StatefulSetSpec(in, out, s); err != nil { + return err + } + // set APIVersion/Kind to behave the same as reflective conversion < 1.17. + // see http://issue.k8s.io/87583 + if out.VolumeClaimTemplates != nil { + // copy so we don't modify the input + templatesCopy := make([]core.PersistentVolumeClaim, len(out.VolumeClaimTemplates)) + copy(templatesCopy, out.VolumeClaimTemplates) + out.VolumeClaimTemplates = templatesCopy + for i := range out.VolumeClaimTemplates { + out.VolumeClaimTemplates[i].APIVersion = "" + out.VolumeClaimTemplates[i].Kind = "" + } + } + return nil +} + +// Convert_apps_StatefulSetSpec_To_v1beta1_StatefulSetSpec augments auto-conversion to preserve < 1.17 behavior +// setting apiVersion/kind in nested persistent volume claim objects. +func Convert_apps_StatefulSetSpec_To_v1beta1_StatefulSetSpec(in *apps.StatefulSetSpec, out *appsv1beta1.StatefulSetSpec, s conversion.Scope) error { + if err := autoConvert_apps_StatefulSetSpec_To_v1beta1_StatefulSetSpec(in, out, s); err != nil { + return err + } + // set APIVersion/Kind to behave the same as reflective conversion < 1.17. + // see http://issue.k8s.io/87583 + if out.VolumeClaimTemplates != nil { + // copy so we don't modify the input + templatesCopy := make([]corev1.PersistentVolumeClaim, len(out.VolumeClaimTemplates)) + copy(templatesCopy, out.VolumeClaimTemplates) + out.VolumeClaimTemplates = templatesCopy + for i := range out.VolumeClaimTemplates { + out.VolumeClaimTemplates[i].APIVersion = "v1" + out.VolumeClaimTemplates[i].Kind = "PersistentVolumeClaim" + } + } + return nil +} diff --git a/pkg/apis/apps/v1beta1/zz_generated.conversion.go b/pkg/apis/apps/v1beta1/zz_generated.conversion.go index 5b4d63cbd40..afa6f60389e 100644 --- a/pkg/apis/apps/v1beta1/zz_generated.conversion.go +++ b/pkg/apis/apps/v1beta1/zz_generated.conversion.go @@ -211,16 +211,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1beta1.StatefulSetSpec)(nil), (*apps.StatefulSetSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1beta1_StatefulSetSpec_To_apps_StatefulSetSpec(a.(*v1beta1.StatefulSetSpec), b.(*apps.StatefulSetSpec), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*apps.StatefulSetSpec)(nil), (*v1beta1.StatefulSetSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_apps_StatefulSetSpec_To_v1beta1_StatefulSetSpec(a.(*apps.StatefulSetSpec), b.(*v1beta1.StatefulSetSpec), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*v1beta1.StatefulSetStatus)(nil), (*apps.StatefulSetStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta1_StatefulSetStatus_To_apps_StatefulSetStatus(a.(*v1beta1.StatefulSetStatus), b.(*apps.StatefulSetStatus), scope) }); err != nil { @@ -241,6 +231,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*apps.StatefulSetSpec)(nil), (*v1beta1.StatefulSetSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_apps_StatefulSetSpec_To_v1beta1_StatefulSetSpec(a.(*apps.StatefulSetSpec), b.(*v1beta1.StatefulSetSpec), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*autoscaling.ScaleStatus)(nil), (*v1beta1.ScaleStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_autoscaling_ScaleStatus_To_v1beta1_ScaleStatus(a.(*autoscaling.ScaleStatus), b.(*v1beta1.ScaleStatus), scope) }); err != nil { @@ -251,6 +246,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1beta1.StatefulSetSpec)(nil), (*apps.StatefulSetSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_StatefulSetSpec_To_apps_StatefulSetSpec(a.(*v1beta1.StatefulSetSpec), b.(*apps.StatefulSetSpec), scope) + }); err != nil { + return err + } return nil } @@ -835,11 +835,6 @@ func autoConvert_v1beta1_StatefulSetSpec_To_apps_StatefulSetSpec(in *v1beta1.Sta return nil } -// Convert_v1beta1_StatefulSetSpec_To_apps_StatefulSetSpec is an autogenerated conversion function. -func Convert_v1beta1_StatefulSetSpec_To_apps_StatefulSetSpec(in *v1beta1.StatefulSetSpec, out *apps.StatefulSetSpec, s conversion.Scope) error { - return autoConvert_v1beta1_StatefulSetSpec_To_apps_StatefulSetSpec(in, out, s) -} - func autoConvert_apps_StatefulSetSpec_To_v1beta1_StatefulSetSpec(in *apps.StatefulSetSpec, out *v1beta1.StatefulSetSpec, s conversion.Scope) error { if err := metav1.Convert_int32_To_Pointer_int32(&in.Replicas, &out.Replicas, s); err != nil { return err @@ -858,11 +853,6 @@ func autoConvert_apps_StatefulSetSpec_To_v1beta1_StatefulSetSpec(in *apps.Statef return nil } -// Convert_apps_StatefulSetSpec_To_v1beta1_StatefulSetSpec is an autogenerated conversion function. -func Convert_apps_StatefulSetSpec_To_v1beta1_StatefulSetSpec(in *apps.StatefulSetSpec, out *v1beta1.StatefulSetSpec, s conversion.Scope) error { - return autoConvert_apps_StatefulSetSpec_To_v1beta1_StatefulSetSpec(in, out, s) -} - func autoConvert_v1beta1_StatefulSetStatus_To_apps_StatefulSetStatus(in *v1beta1.StatefulSetStatus, out *apps.StatefulSetStatus, s conversion.Scope) error { out.ObservedGeneration = (*int64)(unsafe.Pointer(in.ObservedGeneration)) out.Replicas = in.Replicas diff --git a/pkg/apis/apps/v1beta2/conversion.go b/pkg/apis/apps/v1beta2/conversion.go index adf0e1dee05..988926f0b43 100644 --- a/pkg/apis/apps/v1beta2/conversion.go +++ b/pkg/apis/apps/v1beta2/conversion.go @@ -21,12 +21,14 @@ import ( "strconv" appsv1beta2 "k8s.io/api/apps/v1beta2" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/conversion" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/kubernetes/pkg/apis/apps" autoscaling "k8s.io/kubernetes/pkg/apis/autoscaling" + "k8s.io/kubernetes/pkg/apis/core" k8s_api_v1 "k8s.io/kubernetes/pkg/apis/core/v1" ) @@ -255,3 +257,45 @@ func deepCopyStringMap(m map[string]string) map[string]string { } return ret } + +// Convert_v1beta2_StatefulSetSpec_To_apps_StatefulSetSpec augments auto-conversion to preserve < 1.17 behavior +// setting apiVersion/kind in nested persistent volume claim objects. +func Convert_v1beta2_StatefulSetSpec_To_apps_StatefulSetSpec(in *appsv1beta2.StatefulSetSpec, out *apps.StatefulSetSpec, s conversion.Scope) error { + if err := autoConvert_v1beta2_StatefulSetSpec_To_apps_StatefulSetSpec(in, out, s); err != nil { + return err + } + // set APIVersion/Kind to behave the same as reflective conversion < 1.17. + // see http://issue.k8s.io/87583 + if out.VolumeClaimTemplates != nil { + // copy so we don't modify the input + templatesCopy := make([]core.PersistentVolumeClaim, len(out.VolumeClaimTemplates)) + copy(templatesCopy, out.VolumeClaimTemplates) + out.VolumeClaimTemplates = templatesCopy + for i := range out.VolumeClaimTemplates { + out.VolumeClaimTemplates[i].APIVersion = "" + out.VolumeClaimTemplates[i].Kind = "" + } + } + return nil +} + +// Convert_apps_StatefulSetSpec_To_v1beta2_StatefulSetSpec augments auto-conversion to preserve < 1.17 behavior +// setting apiVersion/kind in nested persistent volume claim objects. +func Convert_apps_StatefulSetSpec_To_v1beta2_StatefulSetSpec(in *apps.StatefulSetSpec, out *appsv1beta2.StatefulSetSpec, s conversion.Scope) error { + if err := autoConvert_apps_StatefulSetSpec_To_v1beta2_StatefulSetSpec(in, out, s); err != nil { + return err + } + // set APIVersion/Kind to behave the same as reflective conversion < 1.17. + // see http://issue.k8s.io/87583 + if out.VolumeClaimTemplates != nil { + // copy so we don't modify the input + templatesCopy := make([]corev1.PersistentVolumeClaim, len(out.VolumeClaimTemplates)) + copy(templatesCopy, out.VolumeClaimTemplates) + out.VolumeClaimTemplates = templatesCopy + for i := range out.VolumeClaimTemplates { + out.VolumeClaimTemplates[i].APIVersion = "v1" + out.VolumeClaimTemplates[i].Kind = "PersistentVolumeClaim" + } + } + return nil +} diff --git a/pkg/apis/apps/v1beta2/zz_generated.conversion.go b/pkg/apis/apps/v1beta2/zz_generated.conversion.go index fa4bc08c51e..480793529b4 100644 --- a/pkg/apis/apps/v1beta2/zz_generated.conversion.go +++ b/pkg/apis/apps/v1beta2/zz_generated.conversion.go @@ -271,16 +271,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*v1beta2.StatefulSetSpec)(nil), (*apps.StatefulSetSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1beta2_StatefulSetSpec_To_apps_StatefulSetSpec(a.(*v1beta2.StatefulSetSpec), b.(*apps.StatefulSetSpec), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*apps.StatefulSetSpec)(nil), (*v1beta2.StatefulSetSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_apps_StatefulSetSpec_To_v1beta2_StatefulSetSpec(a.(*apps.StatefulSetSpec), b.(*v1beta2.StatefulSetSpec), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*v1beta2.StatefulSetStatus)(nil), (*apps.StatefulSetStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta2_StatefulSetStatus_To_apps_StatefulSetStatus(a.(*v1beta2.StatefulSetStatus), b.(*apps.StatefulSetStatus), scope) }); err != nil { @@ -321,6 +311,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*apps.StatefulSetSpec)(nil), (*v1beta2.StatefulSetSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_apps_StatefulSetSpec_To_v1beta2_StatefulSetSpec(a.(*apps.StatefulSetSpec), b.(*v1beta2.StatefulSetSpec), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*autoscaling.ScaleStatus)(nil), (*v1beta2.ScaleStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_autoscaling_ScaleStatus_To_v1beta2_ScaleStatus(a.(*autoscaling.ScaleStatus), b.(*v1beta2.ScaleStatus), scope) }); err != nil { @@ -351,6 +346,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1beta2.StatefulSetSpec)(nil), (*apps.StatefulSetSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_StatefulSetSpec_To_apps_StatefulSetSpec(a.(*v1beta2.StatefulSetSpec), b.(*apps.StatefulSetSpec), scope) + }); err != nil { + return err + } return nil } @@ -1251,11 +1251,6 @@ func autoConvert_v1beta2_StatefulSetSpec_To_apps_StatefulSetSpec(in *v1beta2.Sta return nil } -// Convert_v1beta2_StatefulSetSpec_To_apps_StatefulSetSpec is an autogenerated conversion function. -func Convert_v1beta2_StatefulSetSpec_To_apps_StatefulSetSpec(in *v1beta2.StatefulSetSpec, out *apps.StatefulSetSpec, s conversion.Scope) error { - return autoConvert_v1beta2_StatefulSetSpec_To_apps_StatefulSetSpec(in, out, s) -} - func autoConvert_apps_StatefulSetSpec_To_v1beta2_StatefulSetSpec(in *apps.StatefulSetSpec, out *v1beta2.StatefulSetSpec, s conversion.Scope) error { if err := metav1.Convert_int32_To_Pointer_int32(&in.Replicas, &out.Replicas, s); err != nil { return err @@ -1274,11 +1269,6 @@ func autoConvert_apps_StatefulSetSpec_To_v1beta2_StatefulSetSpec(in *apps.Statef return nil } -// Convert_apps_StatefulSetSpec_To_v1beta2_StatefulSetSpec is an autogenerated conversion function. -func Convert_apps_StatefulSetSpec_To_v1beta2_StatefulSetSpec(in *apps.StatefulSetSpec, out *v1beta2.StatefulSetSpec, s conversion.Scope) error { - return autoConvert_apps_StatefulSetSpec_To_v1beta2_StatefulSetSpec(in, out, s) -} - func autoConvert_v1beta2_StatefulSetStatus_To_apps_StatefulSetStatus(in *v1beta2.StatefulSetStatus, out *apps.StatefulSetStatus, s conversion.Scope) error { if err := metav1.Convert_int64_To_Pointer_int64(&in.ObservedGeneration, &out.ObservedGeneration, s); err != nil { return err diff --git a/test/integration/statefulset/BUILD b/test/integration/statefulset/BUILD index 6b7b3e5c530..e0c6d0be44d 100644 --- a/test/integration/statefulset/BUILD +++ b/test/integration/statefulset/BUILD @@ -34,10 +34,14 @@ go_test( embed = [":go_default_library"], tags = ["integration"], deps = [ + "//cmd/kube-apiserver/app/testing:go_default_library", "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/json:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//staging/src/k8s.io/client-go/dynamic:go_default_library", "//test/integration/framework:go_default_library", ], ) diff --git a/test/integration/statefulset/statefulset_test.go b/test/integration/statefulset/statefulset_test.go index 427ac5a4009..d25832e9dd4 100644 --- a/test/integration/statefulset/statefulset_test.go +++ b/test/integration/statefulset/statefulset_test.go @@ -21,12 +21,92 @@ import ( "testing" appsv1 "k8s.io/api/apps/v1" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/util/json" "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/dynamic" + apiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing" "k8s.io/kubernetes/test/integration/framework" ) +// TestVolumeTemplateNoopUpdate ensures embedded StatefulSet objects with embedded PersistentVolumes can be updated +func TestVolumeTemplateNoopUpdate(t *testing.T) { + // Start the server with default storage setup + server, err := apiservertesting.StartTestServer(t, apiservertesting.NewDefaultTestServerOptions(), nil, framework.SharedEtcd()) + if err != nil { + t.Fatal(err) + } + defer server.TearDownFn() + + c, err := dynamic.NewForConfig(server.ClientConfig) + if err != nil { + t.Fatal(err) + } + + // Use an unstructured client to ensure we send exactly the bytes we expect for the embedded PVC template + sts := &unstructured.Unstructured{} + err = json.Unmarshal([]byte(`{ + "apiVersion": "apps/v1", + "kind": "StatefulSet", + "metadata": {"name": "web"}, + "spec": { + "selector": {"matchLabels": {"app": "nginx"}}, + "serviceName": "nginx", + "replicas": 3, + "template": { + "metadata": {"labels": {"app": "nginx"}}, + "spec": { + "terminationGracePeriodSeconds": 10, + "containers": [{ + "name": "nginx", + "image": "k8s.gcr.io/nginx-slim:0.8", + "ports": [{"containerPort": 80,"name": "web"}], + "volumeMounts": [{"name": "www","mountPath": "/usr/share/nginx/html"}] + }] + } + }, + "volumeClaimTemplates": [{ + "apiVersion": "v1", + "kind": "PersistentVolumeClaim", + "metadata": {"name": "www"}, + "spec": { + "accessModes": ["ReadWriteOnce"], + "storageClassName": "my-storage-class", + "resources": {"requests": {"storage": "1Gi"}} + } + } + ] + } + }`), &sts.Object) + if err != nil { + t.Fatal(err) + } + + stsClient := c.Resource(appsv1.SchemeGroupVersion.WithResource("statefulsets")).Namespace("default") + + // Create the statefulset + persistedSTS, err := stsClient.Create(sts, metav1.CreateOptions{}) + if err != nil { + t.Fatal(err) + } + + // Update with the original spec (all the same defaulting should apply, should be a no-op and pass validation + originalSpec, ok, err := unstructured.NestedFieldCopy(sts.Object, "spec") + if err != nil || !ok { + t.Fatal(err, ok) + } + err = unstructured.SetNestedField(persistedSTS.Object, originalSpec, "spec") + if err != nil { + t.Fatal(err) + } + _, err = stsClient.Update(persistedSTS, metav1.UpdateOptions{}) + if err != nil { + t.Fatal(err) + } +} + func TestSpecReplicasChange(t *testing.T) { s, closeFn, rm, informers, c := scSetup(t) defer closeFn()