Ensure controller revision data is valid json

This commit is contained in:
Jordan Liggitt 2024-06-13 18:26:15 -04:00
parent 6c556cb9c2
commit d6d78c5581
No known key found for this signature in database
12 changed files with 103 additions and 123 deletions

View File

@ -22,6 +22,7 @@ import (
fuzz "github.com/google/gofuzz"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/kubernetes/pkg/apis/apps"
@ -30,6 +31,11 @@ import (
// Funcs returns the fuzzer functions for the apps api group.
var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(r *apps.ControllerRevision, c fuzz.Continue) {
c.FuzzNoCustom(r)
// match the fuzzer default content for runtime.Object
r.Data = runtime.RawExtension{Raw: []byte(`{"apiVersion":"unknown.group/unknown","kind":"Something","someKey":"someValue"}`)}
},
func(s *apps.StatefulSet, c fuzz.Continue) {
c.FuzzNoCustom(s) // fuzz self without calling this function again

View File

@ -331,7 +331,7 @@ type ControllerRevision struct {
metav1.ObjectMeta
// Data is the Object representing the state.
Data runtime.Object
Data runtime.RawExtension
// Revision indicates the revision of the state represented by Data.
Revision int64

View File

@ -347,9 +347,7 @@ func RegisterConversions(s *runtime.Scheme) error {
func autoConvert_v1_ControllerRevision_To_apps_ControllerRevision(in *v1.ControllerRevision, out *apps.ControllerRevision, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := runtime.Convert_runtime_RawExtension_To_runtime_Object(&in.Data, &out.Data, s); err != nil {
return err
}
out.Data = in.Data
out.Revision = in.Revision
return nil
}
@ -361,9 +359,7 @@ func Convert_v1_ControllerRevision_To_apps_ControllerRevision(in *v1.ControllerR
func autoConvert_apps_ControllerRevision_To_v1_ControllerRevision(in *apps.ControllerRevision, out *v1.ControllerRevision, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := runtime.Convert_runtime_Object_To_runtime_RawExtension(&in.Data, &out.Data, s); err != nil {
return err
}
out.Data = in.Data
out.Revision = in.Revision
return nil
}
@ -375,17 +371,7 @@ func Convert_apps_ControllerRevision_To_v1_ControllerRevision(in *apps.Controlle
func autoConvert_v1_ControllerRevisionList_To_apps_ControllerRevisionList(in *v1.ControllerRevisionList, out *apps.ControllerRevisionList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]apps.ControllerRevision, len(*in))
for i := range *in {
if err := Convert_v1_ControllerRevision_To_apps_ControllerRevision(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
out.Items = *(*[]apps.ControllerRevision)(unsafe.Pointer(&in.Items))
return nil
}
@ -396,17 +382,7 @@ func Convert_v1_ControllerRevisionList_To_apps_ControllerRevisionList(in *v1.Con
func autoConvert_apps_ControllerRevisionList_To_v1_ControllerRevisionList(in *apps.ControllerRevisionList, out *v1.ControllerRevisionList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]v1.ControllerRevision, len(*in))
for i := range *in {
if err := Convert_apps_ControllerRevision_To_v1_ControllerRevision(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
out.Items = *(*[]v1.ControllerRevision)(unsafe.Pointer(&in.Items))
return nil
}

View File

@ -278,9 +278,7 @@ func RegisterConversions(s *runtime.Scheme) error {
func autoConvert_v1beta1_ControllerRevision_To_apps_ControllerRevision(in *v1beta1.ControllerRevision, out *apps.ControllerRevision, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := runtime.Convert_runtime_RawExtension_To_runtime_Object(&in.Data, &out.Data, s); err != nil {
return err
}
out.Data = in.Data
out.Revision = in.Revision
return nil
}
@ -292,9 +290,7 @@ func Convert_v1beta1_ControllerRevision_To_apps_ControllerRevision(in *v1beta1.C
func autoConvert_apps_ControllerRevision_To_v1beta1_ControllerRevision(in *apps.ControllerRevision, out *v1beta1.ControllerRevision, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := runtime.Convert_runtime_Object_To_runtime_RawExtension(&in.Data, &out.Data, s); err != nil {
return err
}
out.Data = in.Data
out.Revision = in.Revision
return nil
}
@ -306,17 +302,7 @@ func Convert_apps_ControllerRevision_To_v1beta1_ControllerRevision(in *apps.Cont
func autoConvert_v1beta1_ControllerRevisionList_To_apps_ControllerRevisionList(in *v1beta1.ControllerRevisionList, out *apps.ControllerRevisionList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]apps.ControllerRevision, len(*in))
for i := range *in {
if err := Convert_v1beta1_ControllerRevision_To_apps_ControllerRevision(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
out.Items = *(*[]apps.ControllerRevision)(unsafe.Pointer(&in.Items))
return nil
}
@ -327,17 +313,7 @@ func Convert_v1beta1_ControllerRevisionList_To_apps_ControllerRevisionList(in *v
func autoConvert_apps_ControllerRevisionList_To_v1beta1_ControllerRevisionList(in *apps.ControllerRevisionList, out *v1beta1.ControllerRevisionList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]v1beta1.ControllerRevision, len(*in))
for i := range *in {
if err := Convert_apps_ControllerRevision_To_v1beta1_ControllerRevision(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
out.Items = *(*[]v1beta1.ControllerRevision)(unsafe.Pointer(&in.Items))
return nil
}

View File

@ -378,9 +378,7 @@ func RegisterConversions(s *runtime.Scheme) error {
func autoConvert_v1beta2_ControllerRevision_To_apps_ControllerRevision(in *v1beta2.ControllerRevision, out *apps.ControllerRevision, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := runtime.Convert_runtime_RawExtension_To_runtime_Object(&in.Data, &out.Data, s); err != nil {
return err
}
out.Data = in.Data
out.Revision = in.Revision
return nil
}
@ -392,9 +390,7 @@ func Convert_v1beta2_ControllerRevision_To_apps_ControllerRevision(in *v1beta2.C
func autoConvert_apps_ControllerRevision_To_v1beta2_ControllerRevision(in *apps.ControllerRevision, out *v1beta2.ControllerRevision, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := runtime.Convert_runtime_Object_To_runtime_RawExtension(&in.Data, &out.Data, s); err != nil {
return err
}
out.Data = in.Data
out.Revision = in.Revision
return nil
}
@ -406,17 +402,7 @@ func Convert_apps_ControllerRevision_To_v1beta2_ControllerRevision(in *apps.Cont
func autoConvert_v1beta2_ControllerRevisionList_To_apps_ControllerRevisionList(in *v1beta2.ControllerRevisionList, out *apps.ControllerRevisionList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]apps.ControllerRevision, len(*in))
for i := range *in {
if err := Convert_v1beta2_ControllerRevision_To_apps_ControllerRevision(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
out.Items = *(*[]apps.ControllerRevision)(unsafe.Pointer(&in.Items))
return nil
}
@ -427,17 +413,7 @@ func Convert_v1beta2_ControllerRevisionList_To_apps_ControllerRevisionList(in *v
func autoConvert_apps_ControllerRevisionList_To_v1beta2_ControllerRevisionList(in *apps.ControllerRevisionList, out *v1beta2.ControllerRevisionList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]v1beta2.ControllerRevision, len(*in))
for i := range *in {
if err := Convert_apps_ControllerRevision_To_v1beta2_ControllerRevision(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
out.Items = *(*[]v1beta2.ControllerRevision)(unsafe.Pointer(&in.Items))
return nil
}

View File

@ -17,6 +17,7 @@ limitations under the License.
package validation
import (
"encoding/json"
"fmt"
"strconv"
@ -251,20 +252,34 @@ func ValidateStatefulSetStatusUpdate(statefulSet, oldStatefulSet *apps.StatefulS
// trailing dashes are allowed.
var ValidateControllerRevisionName = apimachineryvalidation.NameIsDNSSubdomain
// ValidateControllerRevision collects errors for the fields of state and returns those errors as an ErrorList. If the
// validateControllerRevision collects errors for the fields of state and returns those errors as an ErrorList. If the
// returned list is empty, state is valid. Validation is performed to ensure that state is a valid ObjectMeta, its name
// is valid, and that it doesn't exceed the MaxControllerRevisionSize.
func ValidateControllerRevision(revision *apps.ControllerRevision) field.ErrorList {
func validateControllerRevision(revision *apps.ControllerRevision) field.ErrorList {
errs := field.ErrorList{}
errs = append(errs, apivalidation.ValidateObjectMeta(&revision.ObjectMeta, true, ValidateControllerRevisionName, field.NewPath("metadata"))...)
if revision.Data == nil {
errs = append(errs, field.Required(field.NewPath("data"), "data is mandatory"))
}
errs = append(errs, apivalidation.ValidateNonnegativeField(revision.Revision, field.NewPath("revision"))...)
return errs
}
func ValidateControllerRevisionCreate(revision *apps.ControllerRevision) field.ErrorList {
errs := field.ErrorList{}
errs = append(errs, validateControllerRevision(revision)...)
var v any
if revision.Data.Raw == nil {
errs = append(errs, field.Required(field.NewPath("data"), "data is mandatory"))
} else if err := json.Unmarshal(revision.Data.Raw, &v); err != nil {
errs = append(errs, field.Invalid(field.NewPath("data"), "<value omitted>", fmt.Sprintf("error parsing data: %v", err.Error())))
} else if v == nil {
errs = append(errs, field.Required(field.NewPath("data"), "data is mandatory"))
} else if _, isObject := v.(map[string]any); !isObject {
errs = append(errs, field.Required(field.NewPath("data"), "data must be a valid JSON object"))
}
return errs
}
// ValidateControllerRevisionUpdate collects errors pertaining to the mutation of an ControllerRevision Object. If the
// returned ErrorList is empty the update operation is valid. Any mutation to the ControllerRevision's Data or Revision
// is considered to be invalid.
@ -272,7 +287,7 @@ func ValidateControllerRevisionUpdate(newHistory, oldHistory *apps.ControllerRev
errs := field.ErrorList{}
errs = append(errs, apivalidation.ValidateObjectMetaUpdate(&newHistory.ObjectMeta, &oldHistory.ObjectMeta, field.NewPath("metadata"))...)
errs = append(errs, ValidateControllerRevision(newHistory)...)
errs = append(errs, validateControllerRevision(newHistory)...)
errs = append(errs, apivalidation.ValidateImmutableField(newHistory.Data, oldHistory.Data, field.NewPath("data"))...)
return errs
}

View File

@ -17,12 +17,14 @@ limitations under the License.
package validation
import (
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
@ -969,7 +971,7 @@ func TestValidateStatefulSetUpdate(t *testing.T) {
}
func TestValidateControllerRevision(t *testing.T) {
newControllerRevision := func(name, namespace string, data runtime.Object, revision int64) apps.ControllerRevision {
newControllerRevision := func(name, namespace string, data runtime.RawExtension, revision int64) apps.ControllerRevision {
return apps.ControllerRevision{
ObjectMeta: metav1.ObjectMeta{
Name: name,
@ -993,15 +995,17 @@ func TestValidateControllerRevision(t *testing.T) {
}
ss := mkStatefulSet(&podTemplate)
ssJSON, _ := json.Marshal(ss)
raw := runtime.RawExtension{Raw: ssJSON}
var (
valid = newControllerRevision("validname", "validns", &ss, 0)
badRevision = newControllerRevision("validname", "validns", &ss, -1)
emptyName = newControllerRevision("", "validns", &ss, 0)
invalidName = newControllerRevision("NoUppercaseOrSpecialCharsLike=Equals", "validns", &ss, 0)
emptyNs = newControllerRevision("validname", "", &ss, 100)
invalidNs = newControllerRevision("validname", "NoUppercaseOrSpecialCharsLike=Equals", &ss, 100)
nilData = newControllerRevision("validname", "NoUppercaseOrSpecialCharsLike=Equals", nil, 100)
valid = newControllerRevision("validname", "validns", raw, 0)
badRevision = newControllerRevision("validname", "validns", raw, -1)
emptyName = newControllerRevision("", "validns", raw, 0)
invalidName = newControllerRevision("NoUppercaseOrSpecialCharsLike=Equals", "validns", raw, 0)
emptyNs = newControllerRevision("validname", "", raw, 100)
invalidNs = newControllerRevision("validname", "NoUppercaseOrSpecialCharsLike=Equals", raw, 100)
nilData = newControllerRevision("validname", "NoUppercaseOrSpecialCharsLike=Equals", runtime.RawExtension{}, 100)
)
tests := map[string]struct {
@ -1015,11 +1019,19 @@ func TestValidateControllerRevision(t *testing.T) {
"empty namespace": {emptyNs, false},
"invalid namespace": {invalidNs, false},
"nil data": {nilData, false},
"json error": {newControllerRevision("validname", "validns", runtime.RawExtension{Raw: []byte(`{`)}, 0), false},
"json bool": {newControllerRevision("validname", "validns", runtime.RawExtension{Raw: []byte(`true`)}, 0), false},
"json int": {newControllerRevision("validname", "validns", runtime.RawExtension{Raw: []byte(`0`)}, 0), false},
"json float": {newControllerRevision("validname", "validns", runtime.RawExtension{Raw: []byte(`0.5`)}, 0), false},
"json null": {newControllerRevision("validname", "validns", runtime.RawExtension{Raw: []byte(`null`)}, 0), false},
"json array": {newControllerRevision("validname", "validns", runtime.RawExtension{Raw: []byte(`[]`)}, 0), false},
"json string": {newControllerRevision("validname", "validns", runtime.RawExtension{Raw: []byte(`"test"`)}, 0), false},
"json object": {newControllerRevision("validname", "validns", runtime.RawExtension{Raw: []byte(`{}`)}, 0), true},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
errs := ValidateControllerRevision(&tc.history)
errs := ValidateControllerRevisionCreate(&tc.history)
if tc.isValid && len(errs) > 0 {
t.Errorf("%v: unexpected error: %v", name, errs)
}
@ -1031,7 +1043,7 @@ func TestValidateControllerRevision(t *testing.T) {
}
func TestValidateControllerRevisionUpdate(t *testing.T) {
newControllerRevision := func(version, name, namespace string, data runtime.Object, revision int64) apps.ControllerRevision {
newControllerRevision := func(version, name, namespace string, data runtime.RawExtension, revision int64) apps.ControllerRevision {
return apps.ControllerRevision{
ObjectMeta: metav1.ObjectMeta{
Name: name,
@ -1058,11 +1070,16 @@ func TestValidateControllerRevisionUpdate(t *testing.T) {
ss := mkStatefulSet(&podTemplate, tweakName("abc"))
modifiedss := mkStatefulSet(&podTemplate, tweakName("cdf"))
ssJSON, _ := json.Marshal(ss)
modifiedSSJSON, _ := json.Marshal(modifiedss)
raw := runtime.RawExtension{Raw: ssJSON}
modifiedRaw := runtime.RawExtension{Raw: modifiedSSJSON}
var (
valid = newControllerRevision("1", "validname", "validns", &ss, 0)
noVersion = newControllerRevision("", "validname", "validns", &ss, 0)
changedData = newControllerRevision("1", "validname", "validns", &modifiedss, 0)
changedRevision = newControllerRevision("1", "validname", "validns", &ss, 1)
valid = newControllerRevision("1", "validname", "validns", raw, 0)
noVersion = newControllerRevision("", "validname", "validns", raw, 0)
changedData = newControllerRevision("1", "validname", "validns", modifiedRaw, 0)
changedRevision = newControllerRevision("1", "validname", "validns", raw, 1)
)
cases := []struct {

View File

@ -33,9 +33,7 @@ func (in *ControllerRevision) DeepCopyInto(out *ControllerRevision) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
if in.Data != nil {
out.Data = in.Data.DeepCopyObject()
}
in.Data.DeepCopyInto(&out.Data)
return
}

View File

@ -23,6 +23,7 @@ import (
v1 "k8s.io/api/core/v1"
apinamingtest "k8s.io/apimachinery/pkg/api/apitesting/naming"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/kubernetes/pkg/api/legacyscheme"
@ -70,6 +71,7 @@ var typesAllowedTags = map[reflect.Type]bool{
reflect.TypeOf(metav1.GroupVersionResource{}): true,
reflect.TypeOf(metav1.Status{}): true,
reflect.TypeOf(metav1.Condition{}): true,
reflect.TypeOf(runtime.RawExtension{}): true,
}
// These fields are limited exceptions to the standard JSON naming structure.

View File

@ -17,6 +17,7 @@ limitations under the License.
package storage
import (
"encoding/json"
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -43,7 +44,7 @@ func TestCreate(t *testing.T) {
invalidName = stripObjectMeta(newControllerRevision("NoUppercaseOrSpecialCharsLike=Equals", "validns", newObject(), 0))
emptyNs = stripObjectMeta(newControllerRevision("validname", "", newObject(), 100))
invalidNs = stripObjectMeta(newControllerRevision("validname", "NoUppercaseOrSpecialCharsLike=Equals", newObject(), 100))
nilData = stripObjectMeta(newControllerRevision("validname", "validns", nil, 0))
nilData = stripObjectMeta(newControllerRevision("validname", "validns", runtime.RawExtension{Raw: nil}, 0))
)
test.TestCreate(
valid,
@ -74,12 +75,11 @@ func TestUpdate(t *testing.T) {
updateData := func(obj runtime.Object) runtime.Object {
rev := obj.(*apps.ControllerRevision)
modified := newObject()
ss := modified.(*apps.StatefulSet)
ss := newStatefulSet()
ss.Name = "cde"
update := &apps.ControllerRevision{
ObjectMeta: rev.ObjectMeta,
Data: ss,
Data: newRawExtensionFromObject(ss),
Revision: rev.Revision + 1,
}
return update
@ -136,7 +136,7 @@ func TestWatch(t *testing.T) {
)
}
func newControllerRevision(name, namespace string, data runtime.Object, revision int64) *apps.ControllerRevision {
func newControllerRevision(name, namespace string, data runtime.RawExtension, revision int64) *apps.ControllerRevision {
return &apps.ControllerRevision{
ObjectMeta: metav1.ObjectMeta{
Name: name,
@ -167,7 +167,7 @@ func newStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServer) {
return storage, server
}
func newObject() runtime.Object {
func newStatefulSet() *apps.StatefulSet {
return &apps.StatefulSet{
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
Spec: apps.StatefulSetSpec{
@ -184,3 +184,10 @@ func newObject() runtime.Object {
},
}
}
func newRawExtensionFromObject(obj runtime.Object) runtime.RawExtension {
jsonData, _ := json.Marshal(obj)
return runtime.RawExtension{Raw: jsonData}
}
func newObject() runtime.RawExtension {
return newRawExtensionFromObject(newStatefulSet())
}

View File

@ -62,7 +62,7 @@ func (strategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
func (strategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
revision := obj.(*apps.ControllerRevision)
return validation.ValidateControllerRevision(revision)
return validation.ValidateControllerRevisionCreate(revision)
}
// WarningsOnCreate returns warnings for the creation of the given object.

View File

@ -17,6 +17,7 @@ limitations under the License.
package controllerrevision
import (
"encoding/json"
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -47,7 +48,7 @@ func TestStrategy_Validate(t *testing.T) {
invalidName = newControllerRevision("NoUppercaseOrSpecialCharsLike=Equals", "validns", newObject(), 0)
emptyNs = newControllerRevision("validname", "", newObject(), 100)
invalidNs = newControllerRevision("validname", "NoUppercaseOrSpecialCharsLike=Equals", newObject(), 100)
nilData = newControllerRevision("validname", "validns", nil, 0)
nilData = newControllerRevision("validname", "validns", runtime.RawExtension{Raw: nil}, 0)
)
tests := map[string]struct {
@ -79,11 +80,10 @@ func TestStrategy_ValidateUpdate(t *testing.T) {
var (
valid = newControllerRevision("validname", "validns", newObject(), 0)
changedData = newControllerRevision("validname", "validns",
func() runtime.Object {
modified := newObject()
ss := modified.(*apps.StatefulSet)
func() runtime.RawExtension {
ss := newStatefulSet()
ss.Name = "cde"
return modified
return newRawExtensionFromObject(ss)
}(), 0)
changedRevision = newControllerRevision("validname", "validns", newObject(), 1)
)
@ -125,7 +125,7 @@ func TestStrategy_ValidateUpdate(t *testing.T) {
}
}
func newControllerRevision(name, namespace string, data runtime.Object, revision int64) *apps.ControllerRevision {
func newControllerRevision(name, namespace string, data runtime.RawExtension, revision int64) *apps.ControllerRevision {
return &apps.ControllerRevision{
ObjectMeta: metav1.ObjectMeta{
Name: name,
@ -138,7 +138,7 @@ func newControllerRevision(name, namespace string, data runtime.Object, revision
}
}
func newObject() runtime.Object {
func newStatefulSet() *apps.StatefulSet {
return &apps.StatefulSet{
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
Spec: apps.StatefulSetSpec{
@ -155,3 +155,10 @@ func newObject() runtime.Object {
},
}
}
func newRawExtensionFromObject(obj runtime.Object) runtime.RawExtension {
jsonData, _ := json.Marshal(obj)
return runtime.RawExtension{Raw: jsonData}
}
func newObject() runtime.RawExtension {
return newRawExtensionFromObject(newStatefulSet())
}