From 0bb9261eb84c958517cd1f798e0e559ad9f217d7 Mon Sep 17 00:00:00 2001 From: "Dr. Stefan Schimanski" Date: Thu, 12 Apr 2018 16:24:40 +0200 Subject: [PATCH] sample-apiserver: add v1beta1 with advanced conversion example from v1alpha1 --- .../sample-apiserver/hack/update-codegen.sh | 2 +- .../pkg/apis/wardle/fuzzer/fuzzer.go | 44 ++++++++++++ .../pkg/apis/wardle/install/install.go | 4 +- .../pkg/apis/wardle/install/roundtrip_test.go | 5 +- .../sample-apiserver/pkg/apis/wardle/types.go | 13 ++++ .../pkg/apis/wardle/v1alpha1/conversion.go | 72 +++++++++++++++++++ .../pkg/apis/wardle/v1alpha1/defaults.go | 32 +++++++++ .../pkg/apis/wardle/v1alpha1/register.go | 2 +- .../pkg/apis/wardle/v1alpha1/types.go | 11 +++ .../pkg/apis/wardle/v1beta1/doc.go | 22 ++++++ .../pkg/apis/wardle/v1beta1/register.go | 62 ++++++++++++++++ .../pkg/apis/wardle/v1beta1/types.go | 65 +++++++++++++++++ .../pkg/apis/wardle/validation/validation.go | 54 ++++++++++++++ .../pkg/apiserver/apiserver.go | 5 ++ .../pkg/apiserver/scheme_test.go | 3 +- .../pkg/registry/wardle/flunder/strategy.go | 4 +- test/integration/examples/apiserver_test.go | 39 +++++----- 17 files changed, 415 insertions(+), 24 deletions(-) create mode 100644 staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/fuzzer/fuzzer.go create mode 100644 staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/conversion.go create mode 100644 staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/defaults.go create mode 100644 staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/doc.go create mode 100644 staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/register.go create mode 100644 staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/types.go create mode 100644 staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/validation/validation.go diff --git a/staging/src/k8s.io/sample-apiserver/hack/update-codegen.sh b/staging/src/k8s.io/sample-apiserver/hack/update-codegen.sh index 0c3cce6ee3d..b0b0cefc765 100755 --- a/staging/src/k8s.io/sample-apiserver/hack/update-codegen.sh +++ b/staging/src/k8s.io/sample-apiserver/hack/update-codegen.sh @@ -27,7 +27,7 @@ CODEGEN_PKG=${CODEGEN_PKG:-$(cd ${SCRIPT_ROOT}; ls -d -1 ./vendor/k8s.io/code-ge # instead of the $GOPATH directly. For normal projects this can be dropped. ${CODEGEN_PKG}/generate-internal-groups.sh all \ k8s.io/sample-apiserver/pkg/client k8s.io/sample-apiserver/pkg/apis k8s.io/sample-apiserver/pkg/apis \ - wardle:v1alpha1 \ + "wardle:v1alpha1,v1beta1" \ --output-base "$(dirname ${BASH_SOURCE})/../../.." \ --go-header-file ${SCRIPT_ROOT}/hack/boilerplate.go.txt diff --git a/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/fuzzer/fuzzer.go b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/fuzzer/fuzzer.go new file mode 100644 index 00000000000..9278a59f580 --- /dev/null +++ b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/fuzzer/fuzzer.go @@ -0,0 +1,44 @@ +/* +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 fuzzer + +import ( + fuzz "github.com/google/gofuzz" + "k8s.io/sample-apiserver/pkg/apis/wardle" + + runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" +) + +// Funcs returns the fuzzer functions for the apps api group. +var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { + return []interface{}{ + func(s *wardle.FlunderSpec, c fuzz.Continue) { + c.FuzzNoCustom(s) // fuzz self without calling this function again + + if len(s.FlunderReference) != 0 && len(s.FischerReference) != 0 { + s.FischerReference = "" + } + if len(s.FlunderReference) != 0 { + s.ReferenceType = wardle.FlunderReferenceType + } else if len(s.FischerReference) != 0 { + s.ReferenceType = wardle.FischerReferenceType + } else { + s.ReferenceType = "" + } + }, + } +} diff --git a/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install/install.go b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install/install.go index f7e2504b133..3c65d4be0e7 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install/install.go +++ b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install/install.go @@ -23,6 +23,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/sample-apiserver/pkg/apis/wardle" "k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1" + "k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1" ) // Install registers the API group and adds types to a scheme @@ -31,11 +32,12 @@ func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *r &announced.GroupMetaFactoryArgs{ GroupName: wardle.GroupName, RootScopedKinds: sets.NewString("Fischer", "FischerList"), - VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version}, + VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version, v1beta1.SchemeGroupVersion.Version}, AddInternalObjectsToScheme: wardle.AddToScheme, }, announced.VersionToSchemeFunc{ v1alpha1.SchemeGroupVersion.Version: v1alpha1.AddToScheme, + v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme, }, ).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil { panic(err) diff --git a/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install/roundtrip_test.go b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install/roundtrip_test.go index ecdc81ca0de..d50b32dfd9f 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install/roundtrip_test.go +++ b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/install/roundtrip_test.go @@ -19,9 +19,10 @@ package install import ( "testing" - roundtrip "k8s.io/apimachinery/pkg/api/testing/roundtrip" + "k8s.io/apimachinery/pkg/api/testing/roundtrip" + wardlefuzzer "k8s.io/sample-apiserver/pkg/apis/wardle/fuzzer" ) func TestRoundTripTypes(t *testing.T) { - roundtrip.RoundTripTestForAPIGroup(t, Install, nil) + roundtrip.RoundTripTestForAPIGroup(t, Install, wardlefuzzer.Funcs) } diff --git a/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/types.go b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/types.go index fc5a6ee2c02..f7c7efcfedc 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/types.go +++ b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/types.go @@ -28,7 +28,20 @@ type FlunderList struct { Items []Flunder } +type ReferenceType string + +const ( + FlunderReferenceType = ReferenceType("Flunder") + FischerReferenceType = ReferenceType("Fischer") +) + type FlunderSpec struct { + // A name of another flunder, mutually exclusive to the FischerReference. + FlunderReference string + // A name of a fischer, mutually exclusive to the FlunderReference. + FischerReference string + // The reference type. + ReferenceType ReferenceType } type FlunderStatus struct { diff --git a/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/conversion.go b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/conversion.go new file mode 100644 index 00000000000..d310cd6129a --- /dev/null +++ b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/conversion.go @@ -0,0 +1,72 @@ +/* +Copyright 2018 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 v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/conversion" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/sample-apiserver/pkg/apis/wardle" +) + +func addConversionFuncs(scheme *runtime.Scheme) error { + // Add non-generated conversion functions to handle the *int32 -> int32 + // conversion. A pointer is useful in the versioned type so we can default + // it, but a plain int32 is more convenient in the internal type. These + // functions are the same as the autogenerated ones in every other way. + err := scheme.AddConversionFuncs( + Convert_v1alpha1_FlunderSpec_To_wardle_FlunderSpec, + Convert_wardle_FlunderSpec_To_v1alpha1_FlunderSpec, + ) + if err != nil { + return err + } + + return nil +} + +// Convert_v1alpha1_FlunderSpec_To_wardle_FlunderSpec is an autogenerated conversion function. +func Convert_v1alpha1_FlunderSpec_To_wardle_FlunderSpec(in *FlunderSpec, out *wardle.FlunderSpec, s conversion.Scope) error { + if in.ReferenceType != nil { + // assume that ReferenceType is defaulted + switch *in.ReferenceType { + case FlunderReferenceType: + out.ReferenceType = wardle.FlunderReferenceType + out.FlunderReference = in.Reference + case FischerReferenceType: + out.ReferenceType = wardle.FischerReferenceType + out.FischerReference = in.Reference + } + } + + return nil +} + +// Convert_wardle_FlunderSpec_To_v1alpha1_FlunderSpec is an autogenerated conversion function. +func Convert_wardle_FlunderSpec_To_v1alpha1_FlunderSpec(in *wardle.FlunderSpec, out *FlunderSpec, s conversion.Scope) error { + switch in.ReferenceType { + case wardle.FlunderReferenceType: + t := FlunderReferenceType + out.ReferenceType = &t + out.Reference = in.FlunderReference + case wardle.FischerReferenceType: + t := FischerReferenceType + out.ReferenceType = &t + out.Reference = in.FischerReference + } + + return nil +} diff --git a/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/defaults.go b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/defaults.go new file mode 100644 index 00000000000..194dfecc756 --- /dev/null +++ b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/defaults.go @@ -0,0 +1,32 @@ +/* +Copyright 2018 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 v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/runtime" +) + +func addDefaultingFuncs(scheme *runtime.Scheme) error { + return RegisterDefaults(scheme) +} + +func SetDefaults_FlunderSpec(obj *FlunderSpec) { + if (obj.ReferenceType == nil || len(*obj.ReferenceType) == 0) && len(obj.Reference) != 0 { + t := FlunderReferenceType + obj.ReferenceType = &t + } +} diff --git a/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/register.go b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/register.go index 4ceaf3d394f..a2d4c99f535 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/register.go +++ b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/register.go @@ -39,7 +39,7 @@ 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(addKnownTypes) + localSchemeBuilder.Register(addKnownTypes, addConversionFuncs, addDefaultingFuncs) } // Adds the list of known types to the given scheme. diff --git a/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/types.go b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/types.go index 31c8ed331d9..3332e7c1ec1 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/types.go +++ b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1/types.go @@ -28,7 +28,18 @@ type FlunderList struct { Items []Flunder `json:"items" protobuf:"bytes,2,rep,name=items"` } +type ReferenceType string + +const ( + FlunderReferenceType = ReferenceType("Flunder") + FischerReferenceType = ReferenceType("Fischer") +) + type FlunderSpec struct { + // A name of another flunder or fischer, depending on the reference type. + Reference string `json:"reference,omitempty" protobuf:"bytes,1,opt,name=reference"` + // The reference type, defaults to "Flunder" if reference is set. + ReferenceType *ReferenceType `json:"referenceType,omitempty" protobuf:"bytes,2,opt,name=referenceType"` } type FlunderStatus struct { diff --git a/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/doc.go b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/doc.go new file mode 100644 index 00000000000..ca385a2e711 --- /dev/null +++ b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/doc.go @@ -0,0 +1,22 @@ +/* +Copyright 2018 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. +*/ + +// +k8s:deepcopy-gen=package +// +k8s:conversion-gen=k8s.io/sample-apiserver/pkg/apis/wardle + +// Package v1beta1 is the v1beta1 version of the API. +// +groupName=wardle.k8s.io +package v1beta1 diff --git a/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/register.go b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/register.go new file mode 100644 index 00000000000..cd0dd06bd54 --- /dev/null +++ b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/register.go @@ -0,0 +1,62 @@ +/* +Copyright 2018 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 ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName holds the API group name. +const GroupName = "wardle.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"} + +var ( + // SchemeBuilder allows to add this group to a scheme. + // TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api. + // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. + SchemeBuilder runtime.SchemeBuilder + localSchemeBuilder = &SchemeBuilder + + // AddToScheme adds this group to a scheme. + AddToScheme = localSchemeBuilder.AddToScheme +) + +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(addKnownTypes) +} + +// Adds the list of known types to the given scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &Flunder{}, + &FlunderList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} diff --git a/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/types.go b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/types.go new file mode 100644 index 00000000000..78980b127ee --- /dev/null +++ b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1/types.go @@ -0,0 +1,65 @@ +/* +Copyright 2018 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 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// FlunderList is a list of Flunder objects. +type FlunderList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + Items []Flunder `json:"items" protobuf:"bytes,2,rep,name=items"` +} + +// ReferenceType defines the type of an object reference. +type ReferenceType string + +const ( + // FlunderReferenceType is used for Flunder references. + FlunderReferenceType = ReferenceType("Flunder") + // FischerReferenceType is used for Fischer references. + FischerReferenceType = ReferenceType("Fischer") +) + +// FlunderSpec is the specification of a Flunder. +type FlunderSpec struct { + // A name of another flunder, mutually exclusive to the FischerReference. + FlunderReference string `json:"flunderReference,omitempty" protobuf:"bytes,1,opt,name=flunderReference"` + // A name of a fischer, mutually exclusive to the FlunderReference. + FischerReference string `json:"fischerReference,omitempty" protobuf:"bytes,2,opt,name=fischerReference"` + // The reference type. + ReferenceType ReferenceType `json:"referenceType,omitempty" protobuf:"bytes,3,opt,name=referenceType"` +} + +// FlunderStatus is the status of a Flunder. +type FlunderStatus struct { +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Flunder is an example type with a spec and a status. +type Flunder struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + Spec FlunderSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"` + Status FlunderStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"` +} diff --git a/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/validation/validation.go b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/validation/validation.go new file mode 100644 index 00000000000..dc6f3c56d4b --- /dev/null +++ b/staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/validation/validation.go @@ -0,0 +1,54 @@ +/* +Copyright 2016 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 validation + +import ( + "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/sample-apiserver/pkg/apis/wardle" +) + +// ValidateFlunder validates a Flunder. +func ValidateFlunder(f *wardle.Flunder) field.ErrorList { + allErrs := field.ErrorList{} + + allErrs = append(allErrs, ValidateFlunderSpec(&f.Spec, field.NewPath("spec"))...) + + return allErrs +} + +// ValidateFlunderSpec validates a FlunderSpec. +func ValidateFlunderSpec(s *wardle.FlunderSpec, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + + if len(s.FlunderReference) != 0 && len(s.FischerReference) != 0 { + allErrs = append(allErrs, field.Invalid(fldPath.Child("fischerReference"), s.FischerReference, "cannot be set with flunderReference at the same time")) + } else if len(s.FlunderReference) != 0 && s.ReferenceType != wardle.FlunderReferenceType { + allErrs = append(allErrs, field.Invalid(fldPath.Child("flunderReference"), s.FlunderReference, "cannot be set if referenceType is not Flunder")) + } else if len(s.FischerReference) != 0 && s.ReferenceType != wardle.FischerReferenceType { + allErrs = append(allErrs, field.Invalid(fldPath.Child("fischerReference"), s.FischerReference, "cannot be set if referenceType is not Fischer")) + } else if len(s.FischerReference) == 0 && s.ReferenceType == wardle.FischerReferenceType { + allErrs = append(allErrs, field.Invalid(fldPath.Child("fischerReference"), s.FischerReference, "cannot be empty if referenceType is Fischer")) + } else if len(s.FlunderReference) == 0 && s.ReferenceType == wardle.FlunderReferenceType { + allErrs = append(allErrs, field.Invalid(fldPath.Child("flunderReference"), s.FlunderReference, "cannot be empty if referenceType is Flunder")) + } + + if len(s.ReferenceType) != 0 && s.ReferenceType != wardle.FischerReferenceType && s.ReferenceType != wardle.FlunderReferenceType { + allErrs = append(allErrs, field.Invalid(fldPath.Child("referenceType"), s.ReferenceType, "must be Flunder or Fischer")) + } + + return allErrs +} diff --git a/staging/src/k8s.io/sample-apiserver/pkg/apiserver/apiserver.go b/staging/src/k8s.io/sample-apiserver/pkg/apiserver/apiserver.go index 7de9d375734..75adaf44ec5 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/apiserver/apiserver.go +++ b/staging/src/k8s.io/sample-apiserver/pkg/apiserver/apiserver.go @@ -112,11 +112,16 @@ func (c completedConfig) New() (*WardleServer, error) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(wardle.GroupName, registry, Scheme, metav1.ParameterCodec, Codecs) apiGroupInfo.GroupMeta.GroupVersion = v1alpha1.SchemeGroupVersion + v1alpha1storage := map[string]rest.Storage{} v1alpha1storage["flunders"] = wardleregistry.RESTInPeace(flunderstorage.NewREST(Scheme, c.GenericConfig.RESTOptionsGetter)) v1alpha1storage["fischers"] = wardleregistry.RESTInPeace(fischerstorage.NewREST(Scheme, c.GenericConfig.RESTOptionsGetter)) apiGroupInfo.VersionedResourcesStorageMap["v1alpha1"] = v1alpha1storage + v1beta1storage := map[string]rest.Storage{} + v1beta1storage["flunders"] = wardleregistry.RESTInPeace(flunderstorage.NewREST(Scheme, c.GenericConfig.RESTOptionsGetter)) + apiGroupInfo.VersionedResourcesStorageMap["v1beta1"] = v1beta1storage + if err := s.GenericAPIServer.InstallAPIGroup(&apiGroupInfo); err != nil { return nil, err } diff --git a/staging/src/k8s.io/sample-apiserver/pkg/apiserver/scheme_test.go b/staging/src/k8s.io/sample-apiserver/pkg/apiserver/scheme_test.go index 070dd3c009f..060a8be7e5e 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/apiserver/scheme_test.go +++ b/staging/src/k8s.io/sample-apiserver/pkg/apiserver/scheme_test.go @@ -20,8 +20,9 @@ import ( "testing" "k8s.io/apimachinery/pkg/api/testing/roundtrip" + wardlefuzzer "k8s.io/sample-apiserver/pkg/apis/wardle/fuzzer" ) func TestRoundTripTypes(t *testing.T) { - roundtrip.RoundTripTestForScheme(t, Scheme, nil) + roundtrip.RoundTripTestForScheme(t, Scheme, wardlefuzzer.Funcs) } diff --git a/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/flunder/strategy.go b/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/flunder/strategy.go index b20b909d724..e94879acb10 100644 --- a/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/flunder/strategy.go +++ b/staging/src/k8s.io/sample-apiserver/pkg/registry/wardle/flunder/strategy.go @@ -26,6 +26,7 @@ import ( "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/storage" "k8s.io/apiserver/pkg/storage/names" + "k8s.io/sample-apiserver/pkg/apis/wardle/validation" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/sample-apiserver/pkg/apis/wardle" @@ -77,7 +78,8 @@ func (flunderStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old } func (flunderStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { - return field.ErrorList{} + flunder := obj.(*wardle.Flunder) + return validation.ValidateFlunder(flunder) } func (flunderStrategy) AllowCreateOnUpdate() bool { diff --git a/test/integration/examples/apiserver_test.go b/test/integration/examples/apiserver_test.go index 642ee5ea72b..9fc1df3947d 100644 --- a/test/integration/examples/apiserver_test.go +++ b/test/integration/examples/apiserver_test.go @@ -46,17 +46,11 @@ import ( "k8s.io/kubernetes/cmd/kube-apiserver/app" "k8s.io/kubernetes/cmd/kube-apiserver/app/options" "k8s.io/kubernetes/test/integration/framework" - "k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1" + wardlev1alpha1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1" + wardlev1beta1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1" sampleserver "k8s.io/sample-apiserver/pkg/cmd/server" ) -var groupVersion = v1alpha1.SchemeGroupVersion - -var groupVersionForDiscovery = metav1.GroupVersionForDiscovery{ - GroupVersion: groupVersion.String(), - Version: groupVersion.Version, -} - func TestAggregatedAPIServer(t *testing.T) { stopCh := make(chan struct{}) defer close(stopCh) @@ -423,10 +417,21 @@ func testAPIGroupList(t *testing.T, client rest.Interface) { t.Fatalf("Error in unmarshalling response from server %s: %v", "/apis", err) } assert.Equal(t, 1, len(apiGroupList.Groups)) - assert.Equal(t, groupVersion.Group, apiGroupList.Groups[0].Name) - assert.Equal(t, 1, len(apiGroupList.Groups[0].Versions)) - assert.Equal(t, groupVersionForDiscovery, apiGroupList.Groups[0].Versions[0]) - assert.Equal(t, groupVersionForDiscovery, apiGroupList.Groups[0].PreferredVersion) + assert.Equal(t, wardlev1alpha1.GroupName, apiGroupList.Groups[0].Name) + assert.Equal(t, 2, len(apiGroupList.Groups[0].Versions)) + + v1alpha1 := metav1.GroupVersionForDiscovery{ + GroupVersion: wardlev1alpha1.SchemeGroupVersion.String(), + Version: wardlev1alpha1.SchemeGroupVersion.Version, + } + v1beta1 := metav1.GroupVersionForDiscovery{ + GroupVersion: wardlev1beta1.SchemeGroupVersion.String(), + Version: wardlev1beta1.SchemeGroupVersion.Version, + } + + assert.Equal(t, v1alpha1, apiGroupList.Groups[0].Versions[0]) + assert.Equal(t, v1beta1, apiGroupList.Groups[0].Versions[1]) + assert.Equal(t, v1alpha1, apiGroupList.Groups[0].PreferredVersion) } func testAPIGroup(t *testing.T, client rest.Interface) { @@ -440,10 +445,10 @@ func testAPIGroup(t *testing.T, client rest.Interface) { if err != nil { t.Fatalf("Error in unmarshalling response from server %s: %v", "/apis/wardle.k8s.io", err) } - assert.Equal(t, groupVersion.Group, apiGroup.Name) - assert.Equal(t, 1, len(apiGroup.Versions)) - assert.Equal(t, groupVersion.String(), apiGroup.Versions[0].GroupVersion) - assert.Equal(t, groupVersion.Version, apiGroup.Versions[0].Version) + assert.Equal(t, wardlev1alpha1.SchemeGroupVersion.Group, apiGroup.Name) + assert.Equal(t, 2, len(apiGroup.Versions)) + assert.Equal(t, wardlev1alpha1.SchemeGroupVersion.String(), apiGroup.Versions[0].GroupVersion) + assert.Equal(t, wardlev1alpha1.SchemeGroupVersion.Version, apiGroup.Versions[0].Version) assert.Equal(t, apiGroup.PreferredVersion, apiGroup.Versions[0]) } @@ -458,7 +463,7 @@ func testAPIResourceList(t *testing.T, client rest.Interface) { if err != nil { t.Fatalf("Error in unmarshalling response from server %s: %v", "/apis/wardle.k8s.io/v1alpha1", err) } - assert.Equal(t, groupVersion.String(), apiResourceList.GroupVersion) + assert.Equal(t, wardlev1alpha1.SchemeGroupVersion.String(), apiResourceList.GroupVersion) assert.Equal(t, 2, len(apiResourceList.APIResources)) assert.Equal(t, "fischers", apiResourceList.APIResources[0].Name) assert.False(t, apiResourceList.APIResources[0].Namespaced)