diff --git a/cmd/genconversion/conversion.go b/cmd/genconversion/conversion.go index f4c9de18e84..ee2ca60ffde 100644 --- a/cmd/genconversion/conversion.go +++ b/cmd/genconversion/conversion.go @@ -23,9 +23,9 @@ import ( "os" "path" "runtime" - "strings" "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/unversioned" _ "k8s.io/kubernetes/pkg/api/v1" _ "k8s.io/kubernetes/pkg/apis/componentconfig" _ "k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1" @@ -84,33 +84,24 @@ func main() { data := new(bytes.Buffer) - group, version := path.Split(*groupVersion) - group = strings.TrimRight(group, "/") + gv := unversioned.ParseGroupVersionOrDie(*groupVersion) - _, err := data.WriteString(fmt.Sprintf("package %v\n", version)) + _, err := data.WriteString(fmt.Sprintf("package %v\n", gv.Version)) if err != nil { glog.Fatalf("Error while writing package line: %v", err) } - var schemeVersion string - if *groupVersion == "" || *groupVersion == "/" { - // This occurs when we generate deep-copy for internal version. - schemeVersion = "" - } else { - schemeVersion = *groupVersion - } - - versionPath := pkgPath(group, version) + versionPath := pkgPath(gv.Group, gv.Version) generator := kruntime.NewConversionGenerator(api.Scheme.Raw(), versionPath) apiShort := generator.AddImport(path.Join(pkgBase, "api")) generator.AddImport(path.Join(pkgBase, "api/resource")) // TODO(wojtek-t): Change the overwrites to a flag. - generator.OverwritePackage(version, "") - for _, knownType := range api.Scheme.KnownTypes(schemeVersion) { + generator.OverwritePackage(gv.Version, "") + for _, knownType := range api.Scheme.KnownTypes(gv) { if knownType.PkgPath() != versionPath { continue } - if err := generator.GenerateConversionsForType(*groupVersion, knownType); err != nil { + if err := generator.GenerateConversionsForType(gv, knownType); err != nil { glog.Errorf("Error while generating conversion functions for %v: %v", knownType, err) } } diff --git a/cmd/gendeepcopy/deep_copy.go b/cmd/gendeepcopy/deep_copy.go index 59818de182b..963264ab7e3 100644 --- a/cmd/gendeepcopy/deep_copy.go +++ b/cmd/gendeepcopy/deep_copy.go @@ -26,6 +26,7 @@ import ( "strings" "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/unversioned" _ "k8s.io/kubernetes/pkg/api/v1" _ "k8s.io/kubernetes/pkg/apis/componentconfig" _ "k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1" @@ -50,8 +51,8 @@ var ( ) // types inside the api package don't need to say "api.Scheme"; all others do. -func destScheme(group, version string) string { - if group == "" && version == "" { +func destScheme(gv unversioned.GroupVersion) string { + if gv == api.SchemeGroupVersion { return "Scheme" } return "api.Scheme" @@ -93,18 +94,18 @@ func main() { data := new(bytes.Buffer) - group, version := path.Split(*groupVersion) - group = strings.TrimRight(group, "/") - registerTo := destScheme(group, version) + gv := unversioned.ParseGroupVersionOrDie(*groupVersion) + + registerTo := destScheme(gv) var pkgname string - if group == "" { + if gv.Group == "" { // the internal version of v1 is registered in package api pkgname = "api" } else { - pkgname = group + pkgname = gv.Group } - if len(version) != 0 { - pkgname = version + if len(gv.Version) != 0 { + pkgname = gv.Version } _, err := data.WriteString(fmt.Sprintf("package %s\n", pkgname)) @@ -112,7 +113,7 @@ func main() { glog.Fatalf("Error while writing package line: %v", err) } - versionPath := pkgPath(group, version) + versionPath := pkgPath(gv.Group, gv.Version) generator := kruntime.NewDeepCopyGenerator(api.Scheme.Raw(), versionPath, sets.NewString("k8s.io/kubernetes")) generator.AddImport(path.Join(pkgBase, "api")) @@ -126,14 +127,7 @@ func main() { } } - var schemeVersion string - if *groupVersion == "" || *groupVersion == "/" { - // This occurs when we generate deep-copy for internal version. - schemeVersion = "" - } else { - schemeVersion = *groupVersion - } - for _, knownType := range api.Scheme.KnownTypes(schemeVersion) { + for _, knownType := range api.Scheme.KnownTypes(gv) { if knownType.PkgPath() != versionPath { continue } diff --git a/pkg/api/copy_test.go b/pkg/api/copy_test.go index 0744873ce3b..b5abf9864e8 100644 --- a/pkg/api/copy_test.go +++ b/pkg/api/copy_test.go @@ -24,6 +24,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/testapi" apitesting "k8s.io/kubernetes/pkg/api/testing" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/util" "github.com/google/gofuzz" @@ -31,10 +32,10 @@ import ( func TestDeepCopyApiObjects(t *testing.T) { for i := 0; i < *fuzzIters; i++ { - for _, version := range []string{"", testapi.Default.Version()} { - f := apitesting.FuzzerFor(t, version, rand.NewSource(rand.Int63())) - for kind := range api.Scheme.KnownTypes(version) { - doDeepCopyTest(t, version, kind, f) + for _, gv := range []unversioned.GroupVersion{testapi.Default.InternalGroupVersion(), *testapi.Default.GroupVersion()} { + f := apitesting.FuzzerFor(t, gv.String(), rand.NewSource(rand.Int63())) + for kind := range api.Scheme.KnownTypes(gv) { + doDeepCopyTest(t, gv.String(), kind, f) } } } diff --git a/pkg/api/mapper.go b/pkg/api/mapper.go index 50df8893cd2..e2468fdadf3 100644 --- a/pkg/api/mapper.go +++ b/pkg/api/mapper.go @@ -41,9 +41,8 @@ func NewDefaultRESTMapper(defaultGroupVersions []unversioned.GroupVersion, inter // enumerate all supported versions, get the kinds, and register with the mapper how to address // our resources. for _, gv := range defaultGroupVersions { - for kind, oType := range Scheme.KnownTypes(gv.String()) { + for kind, oType := range Scheme.KnownTypes(gv) { gvk := gv.WithKind(kind) - // TODO: Remove import path prefix check. // We check the import path prefix because we currently stuff both "api" and "extensions" objects // into the same group within Scheme since Scheme has no notion of groups yet. diff --git a/pkg/api/register.go b/pkg/api/register.go index 97404cf9a1e..05e634b7ba8 100644 --- a/pkg/api/register.go +++ b/pkg/api/register.go @@ -24,8 +24,11 @@ import ( // Scheme is the default instance of runtime.Scheme to which types in the Kubernetes API are already registered. var Scheme = runtime.NewScheme() +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = unversioned.GroupVersion{Group: "", Version: ""} + func init() { - Scheme.AddKnownTypes("", + Scheme.AddKnownTypes(SchemeGroupVersion, &Pod{}, &PodList{}, &PodStatusResult{}, @@ -69,12 +72,13 @@ func init() { ) // Register Unversioned types - Scheme.AddKnownTypes("", &unversioned.ListOptions{}) - Scheme.AddKnownTypes("", &unversioned.Status{}) - Scheme.AddKnownTypes("", &unversioned.APIVersions{}) - Scheme.AddKnownTypes("", &unversioned.APIGroupList{}) - Scheme.AddKnownTypes("", &unversioned.APIGroup{}) - Scheme.AddKnownTypes("", &unversioned.APIResourceList{}) + // TODO this should not be done here + Scheme.AddKnownTypes(SchemeGroupVersion, &unversioned.ListOptions{}) + Scheme.AddKnownTypes(SchemeGroupVersion, &unversioned.Status{}) + Scheme.AddKnownTypes(SchemeGroupVersion, &unversioned.APIVersions{}) + Scheme.AddKnownTypes(SchemeGroupVersion, &unversioned.APIGroupList{}) + Scheme.AddKnownTypes(SchemeGroupVersion, &unversioned.APIGroup{}) + Scheme.AddKnownTypes(SchemeGroupVersion, &unversioned.APIResourceList{}) } func (*Pod) IsAnAPIObject() {} diff --git a/pkg/api/serialization_test.go b/pkg/api/serialization_test.go index 5b32f8af6a5..247f2dbcac2 100644 --- a/pkg/api/serialization_test.go +++ b/pkg/api/serialization_test.go @@ -135,7 +135,7 @@ func TestRoundTripTypes(t *testing.T) { // api.Scheme.Log(t) // defer api.Scheme.Log(nil) - for kind := range api.Scheme.KnownTypes("") { + for kind := range api.Scheme.KnownTypes(testapi.Default.InternalGroupVersion()) { if nonRoundTrippableTypes.Has(kind) { continue } diff --git a/pkg/api/testapi/testapi.go b/pkg/api/testapi/testapi.go index 970ae920e6e..54939a905df 100644 --- a/pkg/api/testapi/testapi.go +++ b/pkg/api/testapi/testapi.go @@ -24,12 +24,12 @@ import ( "k8s.io/kubernetes/pkg/api" _ "k8s.io/kubernetes/pkg/api/install" - "k8s.io/kubernetes/pkg/api/unversioned" _ "k8s.io/kubernetes/pkg/apis/extensions/install" _ "k8s.io/kubernetes/pkg/apis/metrics/install" "k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/meta" + "k8s.io/kubernetes/pkg/api/unversioned" apiutil "k8s.io/kubernetes/pkg/api/util" "k8s.io/kubernetes/pkg/runtime" ) @@ -89,11 +89,13 @@ func (g TestGroup) GroupAndVersion() string { } func (g TestGroup) GroupVersion() *unversioned.GroupVersion { - gv, err := unversioned.ParseGroupVersion(g.GroupVersionUnderTest) - if err != nil { - panic(err) - } - return &gv + return &unversioned.GroupVersion{Group: g.Group, Version: g.VersionUnderTest} +} + +// InternalGroupVersion returns the group,version used to identify the internal +// types for this API +func (g TestGroup) InternalGroupVersion() unversioned.GroupVersion { + return unversioned.GroupVersion{Group: g.Group} } // Codec returns the codec for the API version to test against, as set by the diff --git a/pkg/api/unversioned/group_version.go b/pkg/api/unversioned/group_version.go index 4e76ac8938f..946d3e26a0a 100644 --- a/pkg/api/unversioned/group_version.go +++ b/pkg/api/unversioned/group_version.go @@ -49,6 +49,7 @@ type GroupVersion struct { Version string } +// IsEmpty returns true if group and version are empty func (gv GroupVersion) IsEmpty() bool { return len(gv.Group) == 0 && len(gv.Version) == 0 } @@ -56,7 +57,7 @@ func (gv GroupVersion) IsEmpty() bool { // String puts "group" and "version" into a single "group/version" string. For the legacy v1 // it returns "v1". func (gv GroupVersion) String() string { - // special case the internal apiVersion for kube + // special case the internal apiVersion for the legacy kube types if gv.IsEmpty() { return "" } @@ -72,7 +73,8 @@ func (gv GroupVersion) String() string { // ParseGroupVersion turns "group/version" string into a GroupVersion struct. It reports error // if it cannot parse the string. func ParseGroupVersion(gv string) (GroupVersion, error) { - // this can be the internal version for kube + // this can be the internal version for the legacy kube types + // TODO once we've cleared the last uses as strings, this special case should be removed. if (len(gv) == 0) || (gv == "/") { return GroupVersion{}, nil } @@ -99,6 +101,7 @@ func ParseGroupVersionOrDie(gv string) GroupVersion { return ret } +// WithKind creates a GroupVersionKind based on the method receiver's GroupVersion and the passed Kind. func (gv GroupVersion) WithKind(kind string) GroupVersionKind { return GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: kind} } diff --git a/pkg/api/v1/register.go b/pkg/api/v1/register.go index 6b8ab7172eb..db459260c89 100644 --- a/pkg/api/v1/register.go +++ b/pkg/api/v1/register.go @@ -23,12 +23,15 @@ import ( "k8s.io/kubernetes/pkg/runtime" ) +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = unversioned.GroupVersion{Group: "", Version: "v1"} + // Codec encodes internal objects to the v1 scheme -var Codec = runtime.CodecFor(api.Scheme, "v1") +var Codec = runtime.CodecFor(api.Scheme, SchemeGroupVersion.String()) func init() { // Check if v1 is in the list of supported API versions. - if !registered.IsRegisteredAPIGroupVersion(unversioned.GroupVersion{Group: "", Version: "v1"}) { + if !registered.IsRegisteredAPIGroupVersion(SchemeGroupVersion) { return } @@ -40,7 +43,7 @@ func init() { // Adds the list of known types to api.Scheme. func addKnownTypes() { - api.Scheme.AddKnownTypes("v1", + api.Scheme.AddKnownTypes(SchemeGroupVersion, &Pod{}, &PodList{}, &PodStatusResult{}, @@ -85,7 +88,7 @@ func addKnownTypes() { ) // Add common types - api.Scheme.AddKnownTypes("v1", &unversioned.Status{}) + api.Scheme.AddKnownTypes(SchemeGroupVersion, &unversioned.Status{}) } func (*Pod) IsAnAPIObject() {} diff --git a/pkg/apis/componentconfig/register.go b/pkg/apis/componentconfig/register.go index c1b6bbb5bfb..a34dd497c2a 100644 --- a/pkg/apis/componentconfig/register.go +++ b/pkg/apis/componentconfig/register.go @@ -18,15 +18,19 @@ package componentconfig import ( "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/unversioned" ) func init() { addKnownTypes() } +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = unversioned.GroupVersion{Group: "componentconfig", Version: ""} + func addKnownTypes() { // TODO this will get cleaned up with the scheme types are fixed - api.Scheme.AddKnownTypes("componentconfig/", + api.Scheme.AddKnownTypes(SchemeGroupVersion, &KubeProxyConfiguration{}, ) } diff --git a/pkg/apis/componentconfig/v1alpha1/register.go b/pkg/apis/componentconfig/v1alpha1/register.go index ac34bb09b6a..503d6b9ef29 100644 --- a/pkg/apis/componentconfig/v1alpha1/register.go +++ b/pkg/apis/componentconfig/v1alpha1/register.go @@ -18,10 +18,14 @@ package v1alpha1 import ( "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/runtime" ) -var Codec = runtime.CodecFor(api.Scheme, "componentconfig/v1alpha1") +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = unversioned.GroupVersion{Group: "componentconfig", Version: "v1alpha1"} + +var Codec = runtime.CodecFor(api.Scheme, SchemeGroupVersion.String()) func init() { addKnownTypes() @@ -29,7 +33,7 @@ func init() { } func addKnownTypes() { - api.Scheme.AddKnownTypes("componentconfig/v1alpha1", + api.Scheme.AddKnownTypes(SchemeGroupVersion, &KubeProxyConfiguration{}, ) } diff --git a/pkg/apis/extensions/register.go b/pkg/apis/extensions/register.go index cdd251171f6..04bde3b3537 100644 --- a/pkg/apis/extensions/register.go +++ b/pkg/apis/extensions/register.go @@ -18,8 +18,12 @@ package extensions import ( "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/unversioned" ) +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = unversioned.GroupVersion{Group: "extensions", Version: ""} + func init() { // Register the API. addKnownTypes() @@ -28,7 +32,7 @@ func init() { // Adds the list of known types to api.Scheme. func addKnownTypes() { // TODO this gets cleaned up when the types are fixed - api.Scheme.AddKnownTypes("extensions/", + api.Scheme.AddKnownTypes(SchemeGroupVersion, &ClusterAutoscaler{}, &ClusterAutoscalerList{}, &Deployment{}, diff --git a/pkg/apis/extensions/v1beta1/register.go b/pkg/apis/extensions/v1beta1/register.go index 05c4b09c0af..f41a5d88c1e 100644 --- a/pkg/apis/extensions/v1beta1/register.go +++ b/pkg/apis/extensions/v1beta1/register.go @@ -18,10 +18,14 @@ package v1beta1 import ( "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/runtime" ) -var Codec = runtime.CodecFor(api.Scheme, "extensions/v1beta1") +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = unversioned.GroupVersion{Group: "extensions", Version: "v1beta1"} + +var Codec = runtime.CodecFor(api.Scheme, SchemeGroupVersion.String()) func init() { addKnownTypes() @@ -31,7 +35,7 @@ func init() { // Adds the list of known types to api.Scheme. func addKnownTypes() { - api.Scheme.AddKnownTypes("extensions/v1beta1", + api.Scheme.AddKnownTypes(SchemeGroupVersion, &ClusterAutoscaler{}, &ClusterAutoscalerList{}, &Deployment{}, diff --git a/pkg/apis/metrics/register.go b/pkg/apis/metrics/register.go index 6ff816526a6..98b0773473f 100644 --- a/pkg/apis/metrics/register.go +++ b/pkg/apis/metrics/register.go @@ -18,6 +18,7 @@ package metrics import ( "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/unversioned" ) func init() { @@ -25,10 +26,13 @@ func init() { addKnownTypes() } +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = unversioned.GroupVersion{Group: "metrics", Version: ""} + // Adds the list of known types to api.Scheme. func addKnownTypes() { // TODO this will get cleaned up with the scheme types are fixed - api.Scheme.AddKnownTypes("metrics/", + api.Scheme.AddKnownTypes(SchemeGroupVersion, &RawNode{}, &RawPod{}, ) diff --git a/pkg/apis/metrics/v1alpha1/register.go b/pkg/apis/metrics/v1alpha1/register.go index 466c16c286e..1bc7ab64110 100644 --- a/pkg/apis/metrics/v1alpha1/register.go +++ b/pkg/apis/metrics/v1alpha1/register.go @@ -18,10 +18,14 @@ package v1alpha1 import ( "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/runtime" ) -var Codec = runtime.CodecFor(api.Scheme, "metrics/v1alpha1") +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = unversioned.GroupVersion{Group: "metrics", Version: "v1alpha1"} + +var Codec = runtime.CodecFor(api.Scheme, SchemeGroupVersion.String()) func init() { // Register the API. @@ -30,7 +34,7 @@ func init() { // Adds the list of known types to api.Scheme. func addKnownTypes() { - api.Scheme.AddKnownTypes("metrics/v1alpha1", + api.Scheme.AddKnownTypes(SchemeGroupVersion, &RawNode{}, &RawPod{}, ) diff --git a/pkg/apiserver/apiserver_test.go b/pkg/apiserver/apiserver_test.go index 2e2b9041905..49b7ca69335 100644 --- a/pkg/apiserver/apiserver_test.go +++ b/pkg/apiserver/apiserver_test.go @@ -113,21 +113,21 @@ func newMapper() *meta.DefaultRESTMapper { func addGrouplessTypes() { api.Scheme.AddKnownTypes( - grouplessGroupVersion.String(), &apiservertesting.Simple{}, &apiservertesting.SimpleList{}, &unversioned.Status{}, + grouplessGroupVersion, &apiservertesting.Simple{}, &apiservertesting.SimpleList{}, &unversioned.Status{}, &unversioned.ListOptions{}, &api.DeleteOptions{}, &apiservertesting.SimpleGetOptions{}, &apiservertesting.SimpleRoot{}) - api.Scheme.AddKnownTypes(grouplessGroupVersion.String(), &api.Pod{}) + api.Scheme.AddKnownTypes(grouplessGroupVersion, &api.Pod{}) } func addTestTypes() { api.Scheme.AddKnownTypes( - testGroupVersion.String(), &apiservertesting.Simple{}, &apiservertesting.SimpleList{}, &unversioned.Status{}, + testGroupVersion, &apiservertesting.Simple{}, &apiservertesting.SimpleList{}, &unversioned.Status{}, &unversioned.ListOptions{}, &api.DeleteOptions{}, &apiservertesting.SimpleGetOptions{}, &apiservertesting.SimpleRoot{}) - api.Scheme.AddKnownTypes(testGroupVersion.String(), &api.Pod{}) + api.Scheme.AddKnownTypes(testGroupVersion, &api.Pod{}) } func addNewTestTypes() { api.Scheme.AddKnownTypes( - newGroupVersion.String(), &apiservertesting.Simple{}, &apiservertesting.SimpleList{}, &unversioned.Status{}, + newGroupVersion, &apiservertesting.Simple{}, &apiservertesting.SimpleList{}, &unversioned.Status{}, &unversioned.ListOptions{}, &api.DeleteOptions{}, &apiservertesting.SimpleGetOptions{}, &apiservertesting.SimpleRoot{}) } @@ -137,7 +137,7 @@ func init() { // "internal" version api.Scheme.AddKnownTypes( - testInternalGroupVersion.String(), &apiservertesting.Simple{}, &apiservertesting.SimpleList{}, &unversioned.Status{}, + testInternalGroupVersion, &apiservertesting.Simple{}, &apiservertesting.SimpleList{}, &unversioned.Status{}, &unversioned.ListOptions{}, &apiservertesting.SimpleGetOptions{}, &apiservertesting.SimpleRoot{}) api.Scheme.AddInternalGroupVersion(testInternalGroupVersion) addGrouplessTypes() @@ -149,9 +149,8 @@ func init() { // enumerate all supported versions, get the kinds, and register with // the mapper how to address our resources for _, gv := range groupVersions { - for kind := range api.Scheme.KnownTypes(gv.String()) { + for kind := range api.Scheme.KnownTypes(gv) { gvk := gv.WithKind(kind) - root := bool(kind == "SimpleRoot") if root { nsMapper.Add(gvk, meta.RESTScopeRoot, false) diff --git a/pkg/client/unversioned/clientcmd/api/register.go b/pkg/client/unversioned/clientcmd/api/register.go index 52482289290..b5946dc7bd4 100644 --- a/pkg/client/unversioned/clientcmd/api/register.go +++ b/pkg/client/unversioned/clientcmd/api/register.go @@ -17,14 +17,19 @@ limitations under the License. package api import ( + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/runtime" ) // Scheme is the default instance of runtime.Scheme to which types in the Kubernetes API are already registered. var Scheme = runtime.NewScheme() +// SchemeGroupVersion is group version used to register these objects +// TODO this should be in the "kubeconfig" group +var SchemeGroupVersion = unversioned.GroupVersion{Group: "", Version: ""} + func init() { - Scheme.AddKnownTypes("", + Scheme.AddKnownTypes(SchemeGroupVersion, &Config{}, ) } diff --git a/pkg/client/unversioned/clientcmd/api/v1/register.go b/pkg/client/unversioned/clientcmd/api/v1/register.go index c2cfeaf6c88..c9e96039c72 100644 --- a/pkg/client/unversioned/clientcmd/api/v1/register.go +++ b/pkg/client/unversioned/clientcmd/api/v1/register.go @@ -17,15 +17,20 @@ limitations under the License. package v1 import ( + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" "k8s.io/kubernetes/pkg/runtime" ) +// SchemeGroupVersion is group version used to register these objects +// TODO this should be in the "kubeconfig" group +var SchemeGroupVersion = unversioned.GroupVersion{Group: "", Version: "v1"} + // Codec encodes internal objects to the v1 scheme -var Codec = runtime.CodecFor(api.Scheme, "v1") +var Codec = runtime.CodecFor(api.Scheme, SchemeGroupVersion.String()) func init() { - api.Scheme.AddKnownTypes("v1", + api.Scheme.AddKnownTypes(SchemeGroupVersion, &Config{}, ) } diff --git a/pkg/conversion/decode.go b/pkg/conversion/decode.go index d3ed57f1202..f99509af03d 100644 --- a/pkg/conversion/decode.go +++ b/pkg/conversion/decode.go @@ -124,14 +124,14 @@ func (s *Scheme) DecodeInto(data []byte, obj interface{}) error { return s.DecodeIntoWithSpecifiedVersionKind(data, obj, unversioned.GroupVersionKind{}) } -// DecodeIntoWithSpecifiedVersionKind compares the passed in specifiedVersion and -// specifiedKind with data.Version and data.Kind, defaulting data.Version and +// DecodeIntoWithSpecifiedVersionKind compares the passed in requestGroupVersionKind +// with data.Version and data.Kind, defaulting data.Version and // data.Kind to the specified value if they are empty, or generating an error if // data.Version and data.Kind are not empty and differ from the specified value. // The function then implements the functionality of DecodeInto. // If specifiedVersion and specifiedKind are empty, the function degenerates to // DecodeInto. -func (s *Scheme) DecodeIntoWithSpecifiedVersionKind(data []byte, obj interface{}, gvk unversioned.GroupVersionKind) error { +func (s *Scheme) DecodeIntoWithSpecifiedVersionKind(data []byte, obj interface{}, requestedGVK unversioned.GroupVersionKind) error { if len(data) == 0 { return errors.New("empty input") } @@ -140,16 +140,16 @@ func (s *Scheme) DecodeIntoWithSpecifiedVersionKind(data []byte, obj interface{} return err } if dataVersion == "" { - dataVersion = gvk.GroupVersion().String() + dataVersion = requestedGVK.GroupVersion().String() } if dataKind == "" { - dataKind = gvk.Kind + dataKind = requestedGVK.Kind } - if (len(gvk.Group) > 0 || len(gvk.Version) > 0) && (dataVersion != gvk.GroupVersion().String()) { - return errors.New(fmt.Sprintf("The apiVersion in the data (%s) does not match the specified apiVersion(%v)", dataVersion, gvk.GroupVersion())) + if (len(requestedGVK.Group) > 0 || len(requestedGVK.Version) > 0) && (dataVersion != requestedGVK.GroupVersion().String()) { + return errors.New(fmt.Sprintf("The apiVersion in the data (%s) does not match the specified apiVersion(%v)", dataVersion, requestedGVK.GroupVersion())) } - if len(gvk.Kind) > 0 && (dataKind != gvk.Kind) { - return errors.New(fmt.Sprintf("The kind in the data (%s) does not match the specified kind(%v)", dataKind, gvk)) + if len(requestedGVK.Kind) > 0 && (dataKind != requestedGVK.Kind) { + return errors.New(fmt.Sprintf("The kind in the data (%s) does not match the specified kind(%v)", dataKind, requestedGVK)) } objVersion, objKind, err := s.ObjectVersionAndKind(obj) diff --git a/pkg/conversion/encode.go b/pkg/conversion/encode.go index 07cd333c223..2455bc5a1a2 100644 --- a/pkg/conversion/encode.go +++ b/pkg/conversion/encode.go @@ -77,7 +77,7 @@ func (s *Scheme) EncodeToVersionStream(obj interface{}, destVersion string, stre return err } - if _, registered := s.typeToVersion[v.Type()]; !registered { + if _, registered := s.typeToGVK[v.Type()]; !registered { return fmt.Errorf("type %v is not registered for %q and it will be impossible to Decode it, therefore Encode will refuse to encode it.", v.Type(), destVersion) } diff --git a/pkg/conversion/meta_test.go b/pkg/conversion/meta_test.go index a05572eae94..b1b98b6bb73 100644 --- a/pkg/conversion/meta_test.go +++ b/pkg/conversion/meta_test.go @@ -130,8 +130,8 @@ func TestMetaValues(t *testing.T) { s := NewScheme() s.InternalVersions[internalGV.Group] = internalGV - s.AddKnownTypeWithName(internalGV.String(), "Simple", &InternalSimple{}) - s.AddKnownTypeWithName(externalGV.String(), "Simple", &ExternalSimple{}) + s.AddKnownTypeWithName(internalGV.WithKind("Simple"), &InternalSimple{}) + s.AddKnownTypeWithName(externalGV.WithKind("Simple"), &ExternalSimple{}) internalToExternalCalls := 0 externalToInternalCalls := 0 diff --git a/pkg/conversion/scheme.go b/pkg/conversion/scheme.go index 19013ab6802..85b9f9bb25a 100644 --- a/pkg/conversion/scheme.go +++ b/pkg/conversion/scheme.go @@ -27,16 +27,11 @@ import ( type Scheme struct { // versionMap allows one to figure out the go type of an object with // the given version and name. - versionMap map[string]map[string]reflect.Type + gvkToType map[unversioned.GroupVersionKind]reflect.Type - // typeToVersion allows one to figure out the version for a given go object. - // The reflect.Type we index by should *not* be a pointer. If the same type - // is registered for multiple versions, the last one wins. - typeToVersion map[reflect.Type]string - - // typeToKind allows one to figure out the desired "kind" field for a given - // go object. Requirements and caveats are the same as typeToVersion. - typeToKind map[reflect.Type][]string + // typeToGroupVersion allows one to find metadata for a given go object. + // The reflect.Type we index by should *not* be a pointer. + typeToGVK map[reflect.Type][]unversioned.GroupVersionKind // converter stores all registered conversion functions. It also has // default coverting behavior. @@ -65,11 +60,10 @@ type Scheme struct { // NewScheme manufactures a new scheme. func NewScheme() *Scheme { s := &Scheme{ - versionMap: map[string]map[string]reflect.Type{}, - typeToVersion: map[reflect.Type]string{}, - typeToKind: map[reflect.Type][]string{}, - converter: NewConverter(), - cloner: NewCloner(), + gvkToType: map[unversioned.GroupVersionKind]reflect.Type{}, + typeToGVK: map[reflect.Type][]unversioned.GroupVersionKind{}, + converter: NewConverter(), + cloner: NewCloner(), // TODO remove this hard coded list. As step one, hardcode it here so this pull doesn't become even bigger InternalVersions: map[string]unversioned.GroupVersion{ "": {}, @@ -92,30 +86,32 @@ func (s *Scheme) Log(l DebugLogger) { // a conversion. Defaults to the go name of the type if the type is not registered. func (s *Scheme) nameFunc(t reflect.Type) string { // find the preferred names for this type - names, ok := s.typeToKind[t] + gvks, ok := s.typeToGVK[t] if !ok { return t.Name() } - if internal, ok := s.versionMap[""]; ok { - for _, name := range names { - if t, ok := internal[name]; ok { - return s.typeToKind[t][0] - } + + for _, gvk := range gvks { + internalGV, exists := s.InternalVersions[gvk.Group] + if !exists { + internalGV := gvk.GroupVersion() + internalGV.Version = "" + } + internalGVK := internalGV.WithKind(gvk.Kind) + + if internalType, exists := s.gvkToType[internalGVK]; exists { + return s.typeToGVK[internalType][0].Kind } } - return names[0] + + return gvks[0].Kind } -// AddKnownTypes registers all types passed in 'types' as being members of version 'version. +// AddKnownTypes registers all types passed in 'types' as being members of version 'version'. // Encode() will refuse objects unless their type has been registered with AddKnownTypes. // All objects passed to types should be pointers to structs. The name that go reports for // the struct becomes the "kind" field when encoding. -func (s *Scheme) AddKnownTypes(version string, types ...interface{}) { - knownTypes, found := s.versionMap[version] - if !found { - knownTypes = map[string]reflect.Type{} - s.versionMap[version] = knownTypes - } +func (s *Scheme) AddKnownTypes(gv unversioned.GroupVersion, types ...interface{}) { for _, obj := range types { t := reflect.TypeOf(obj) if t.Kind() != reflect.Ptr { @@ -125,21 +121,17 @@ func (s *Scheme) AddKnownTypes(version string, types ...interface{}) { if t.Kind() != reflect.Struct { panic("All types must be pointers to structs.") } - knownTypes[t.Name()] = t - s.typeToVersion[t] = version - s.typeToKind[t] = append(s.typeToKind[t], t.Name()) + + gvk := gv.WithKind(t.Name()) + s.gvkToType[gvk] = t + s.typeToGVK[t] = append(s.typeToGVK[t], gvk) } } // AddKnownTypeWithName is like AddKnownTypes, but it lets you specify what this type should // be encoded as. Useful for testing when you don't want to make multiple packages to define // your structs. -func (s *Scheme) AddKnownTypeWithName(version, kind string, obj interface{}) { - knownTypes, found := s.versionMap[version] - if !found { - knownTypes = map[string]reflect.Type{} - s.versionMap[version] = knownTypes - } +func (s *Scheme) AddKnownTypeWithName(gvk unversioned.GroupVersionKind, obj interface{}) { t := reflect.TypeOf(obj) if t.Kind() != reflect.Ptr { panic("All types must be pointers to structs.") @@ -148,21 +140,24 @@ func (s *Scheme) AddKnownTypeWithName(version, kind string, obj interface{}) { if t.Kind() != reflect.Struct { panic("All types must be pointers to structs.") } - knownTypes[kind] = t - s.typeToVersion[t] = version - s.typeToKind[t] = append(s.typeToKind[t], kind) + + s.gvkToType[gvk] = t + s.typeToGVK[t] = append(s.typeToGVK[t], gvk) + } // KnownTypes returns an array of the types that are known for a particular version. -func (s *Scheme) KnownTypes(version string) map[string]reflect.Type { - all, ok := s.versionMap[version] - if !ok { - return map[string]reflect.Type{} - } - types := make(map[string]reflect.Type) - for k, v := range all { - types[k] = v +func (s *Scheme) KnownTypes(gv unversioned.GroupVersion) map[string]reflect.Type { + types := map[string]reflect.Type{} + + for gvk, t := range s.gvkToType { + if gv != gvk.GroupVersion() { + continue + } + + types[gvk.Kind] = t } + return types } @@ -175,12 +170,8 @@ func (s *Scheme) NewObject(gvString, kind string) (interface{}, error) { } gvk := gv.WithKind(kind) - if types, ok := s.versionMap[gvString]; ok { - if t, ok := types[kind]; ok { - return reflect.New(t).Interface(), nil - } - - return nil, ¬RegisteredErr{gvk: gvk} + if t, exists := s.gvkToType[gvk]; exists { + return reflect.New(t).Interface(), nil } return nil, ¬RegisteredErr{gvk: gvk} @@ -292,13 +283,15 @@ func (s *Scheme) AddDefaultingFuncs(defaultingFuncs ...interface{}) error { // Recognizes returns true if the scheme is able to handle the provided version and kind // of an object. -func (s *Scheme) Recognizes(version, kind string) bool { - m, ok := s.versionMap[version] - if !ok { +func (s *Scheme) Recognizes(gvString, kind string) bool { + gv, err := unversioned.ParseGroupVersion(gvString) + if err != nil { return false } - _, ok = m[kind] - return ok + gvk := gv.WithKind(kind) + + _, exists := s.gvkToType[gvk] + return exists } // RegisterInputDefaults sets the provided field mapping function and field matching @@ -349,18 +342,18 @@ func (s *Scheme) ConvertToVersion(in interface{}, outVersion string) (interface{ return nil, fmt.Errorf("only pointers to struct types may be converted: %v", t) } - kinds, ok := s.typeToKind[t] + gvks, ok := s.typeToGVK[t] if !ok { return nil, fmt.Errorf("%v cannot be converted into version %q", t, outVersion) } - outKind := kinds[0] + outKind := gvks[0] inVersion, _, err := s.ObjectVersionAndKind(in) if err != nil { return nil, err } - out, err := s.NewObject(outVersion, outKind) + out, err := s.NewObject(outVersion, outKind.Kind) if err != nil { return nil, err } @@ -370,7 +363,7 @@ func (s *Scheme) ConvertToVersion(in interface{}, outVersion string) (interface{ return nil, err } - if err := s.SetVersionAndKind(outVersion, outKind, out); err != nil { + if err := s.SetVersionAndKind(outVersion, outKind.Kind, out); err != nil { return nil, err } @@ -406,13 +399,13 @@ func (s *Scheme) ObjectVersionAndKind(obj interface{}) (apiVersion, kind string, return "", "", err } t := v.Type() - version, vOK := s.typeToVersion[t] - kinds, kOK := s.typeToKind[t] - if !vOK || !kOK { + + gvks, ok := s.typeToGVK[t] + if !ok { return "", "", ¬RegisteredErr{t: t} } - apiVersion = version - kind = kinds[0] + apiVersion = gvks[0].GroupVersion().String() + kind = gvks[0].Kind return } diff --git a/pkg/conversion/scheme_test.go b/pkg/conversion/scheme_test.go index 07be9dbdad5..f7cf484db68 100644 --- a/pkg/conversion/scheme_test.go +++ b/pkg/conversion/scheme_test.go @@ -109,16 +109,19 @@ var TestObjectFuzzer = fuzz.New().NilChance(.5).NumElements(1, 100).Funcs( // Returns a new Scheme set up with the test objects. func GetTestScheme() *Scheme { + internalGV := unversioned.GroupVersion{} + externalGV := unversioned.GroupVersion{Version: "v1"} + s := NewScheme() // Ordinarily, we wouldn't add TestType2, but because this is a test and // both types are from the same package, we need to get it into the system // so that converter will match it with ExternalType2. - s.AddKnownTypes("", &TestType1{}, &TestType2{}, &ExternalInternalSame{}) - s.AddKnownTypes("v1", &ExternalInternalSame{}) - s.AddKnownTypeWithName("v1", "TestType1", &ExternalTestType1{}) - s.AddKnownTypeWithName("v1", "TestType2", &ExternalTestType2{}) - s.AddKnownTypeWithName("", "TestType3", &TestType1{}) - s.AddKnownTypeWithName("v1", "TestType3", &ExternalTestType1{}) + s.AddKnownTypes(internalGV, &TestType1{}, &TestType2{}, &ExternalInternalSame{}) + s.AddKnownTypes(externalGV, &ExternalInternalSame{}) + s.AddKnownTypeWithName(externalGV.WithKind("TestType1"), &ExternalTestType1{}) + s.AddKnownTypeWithName(externalGV.WithKind("TestType2"), &ExternalTestType2{}) + s.AddKnownTypeWithName(internalGV.WithKind("TestType3"), &TestType1{}) + s.AddKnownTypeWithName(externalGV.WithKind("TestType3"), &ExternalTestType1{}) s.MetaFactory = testMetaFactory{} return s } @@ -229,13 +232,16 @@ func TestMultipleNames(t *testing.T) { } func TestConvertTypesWhenDefaultNamesMatch(t *testing.T) { + internalGV := unversioned.GroupVersion{} + externalGV := unversioned.GroupVersion{Version: "v1"} + s := NewScheme() // create two names internally, with TestType1 being preferred - s.AddKnownTypeWithName("", "TestType1", &TestType1{}) - s.AddKnownTypeWithName("", "OtherType1", &TestType1{}) + s.AddKnownTypeWithName(internalGV.WithKind("TestType1"), &TestType1{}) + s.AddKnownTypeWithName(internalGV.WithKind("OtherType1"), &TestType1{}) // create two names externally, with TestType1 being preferred - s.AddKnownTypeWithName("v1", "TestType1", &ExternalTestType1{}) - s.AddKnownTypeWithName("v1", "OtherType1", &ExternalTestType1{}) + s.AddKnownTypeWithName(externalGV.WithKind("TestType1"), &ExternalTestType1{}) + s.AddKnownTypeWithName(externalGV.WithKind("OtherType1"), &ExternalTestType1{}) s.MetaFactory = testMetaFactory{} ext := &ExternalTestType1{} @@ -267,11 +273,11 @@ func TestConvertTypesWhenDefaultNamesMatch(t *testing.T) { func TestKnownTypes(t *testing.T) { s := GetTestScheme() - if len(s.KnownTypes("v2")) != 0 { + if len(s.KnownTypes(unversioned.GroupVersion{Group: "group", Version: "v2"})) != 0 { t.Errorf("should have no known types for v2") } - types := s.KnownTypes("v1") + types := s.KnownTypes(unversioned.GroupVersion{Version: "v1"}) for _, s := range []string{"TestType1", "TestType2", "TestType3", "ExternalInternalSame"} { if _, ok := types[s]; !ok { t.Errorf("missing type %q", s) diff --git a/pkg/kubectl/cmd/cmd_test.go b/pkg/kubectl/cmd/cmd_test.go index 9c7be7bbdae..76e55d5c167 100644 --- a/pkg/kubectl/cmd/cmd_test.go +++ b/pkg/kubectl/cmd/cmd_test.go @@ -85,10 +85,10 @@ var validVersionGV = unversioned.GroupVersion{Group: "apitest", Version: validVe func newExternalScheme() (*runtime.Scheme, meta.RESTMapper, runtime.Codec) { scheme := runtime.NewScheme() scheme.AddInternalGroupVersion(internalGV) - scheme.AddKnownTypeWithName(internalGV.String(), "Type", &internalType{}) - scheme.AddKnownTypeWithName(unlikelyGV.String(), "Type", &externalType{}) + scheme.AddKnownTypeWithName(internalGV.WithKind("Type"), &internalType{}) + scheme.AddKnownTypeWithName(unlikelyGV.WithKind("Type"), &externalType{}) //This tests that kubectl will not confuse the external scheme with the internal scheme, even when they accidentally have versions of the same name. - scheme.AddKnownTypeWithName(validVersionGV.String(), "Type", &ExternalType2{}) + scheme.AddKnownTypeWithName(validVersionGV.WithKind("Type"), &ExternalType2{}) codec := runtime.CodecFor(scheme, unlikelyGV.String()) mapper := meta.NewDefaultRESTMapper([]unversioned.GroupVersion{unlikelyGV, validVersionGV}, func(version string) (*meta.VersionInterfaces, error) { @@ -99,7 +99,7 @@ func newExternalScheme() (*runtime.Scheme, meta.RESTMapper, runtime.Codec) { }, versionErrIfFalse(version == validVersionGV.String() || version == unlikelyGV.String()) }) for _, gv := range []unversioned.GroupVersion{unlikelyGV, validVersionGV} { - for kind := range scheme.KnownTypes(gv.String()) { + for kind := range scheme.KnownTypes(gv) { gvk := gv.WithKind(kind) mixedCase := false diff --git a/pkg/kubectl/resource_printer_test.go b/pkg/kubectl/resource_printer_test.go index 20cd5e5263d..ea02a2b3921 100644 --- a/pkg/kubectl/resource_printer_test.go +++ b/pkg/kubectl/resource_printer_test.go @@ -40,8 +40,8 @@ import ( ) func init() { - api.Scheme.AddKnownTypes("", &kubectltesting.TestStruct{}) - api.Scheme.AddKnownTypes(testapi.Default.Version(), &kubectltesting.TestStruct{}) + api.Scheme.AddKnownTypes(testapi.Default.InternalGroupVersion(), &kubectltesting.TestStruct{}) + api.Scheme.AddKnownTypes(*testapi.Default.GroupVersion(), &kubectltesting.TestStruct{}) } var testData = kubectltesting.TestStruct{ diff --git a/pkg/runtime/codec.go b/pkg/runtime/codec.go index d69269e4791..99f3c395740 100644 --- a/pkg/runtime/codec.go +++ b/pkg/runtime/codec.go @@ -76,6 +76,7 @@ type codecWrapper struct { version string } +// codecWrapper implements Decoder var _ Decoder = &codecWrapper{} // Encode implements Codec diff --git a/pkg/runtime/conversion_generator.go b/pkg/runtime/conversion_generator.go index 8913d82633d..3fcce258868 100644 --- a/pkg/runtime/conversion_generator.go +++ b/pkg/runtime/conversion_generator.go @@ -30,7 +30,7 @@ import ( ) type ConversionGenerator interface { - GenerateConversionsForType(version string, reflection reflect.Type) error + GenerateConversionsForType(groupVersion unversioned.GroupVersion, reflection reflect.Type) error WriteConversionFunctions(w io.Writer) error RegisterConversionFunctions(w io.Writer, pkg string) error AddImport(pkg string) string @@ -87,12 +87,7 @@ func (g *conversionGenerator) AddImport(pkg string) string { return g.addImportByPath(pkg) } -func (g *conversionGenerator) GenerateConversionsForType(gvString string, reflection reflect.Type) error { - gv, err := unversioned.ParseGroupVersion(gvString) - if err != nil { - return err - } - +func (g *conversionGenerator) GenerateConversionsForType(gv unversioned.GroupVersion, reflection reflect.Type) error { kind := reflection.Name() // TODO this is equivalent to what it did before, but it needs to be fixed for the proper group internalGV, exists := g.scheme.InternalVersions[gv.Group] diff --git a/pkg/runtime/conversion_test.go b/pkg/runtime/conversion_test.go index b3dcc561c27..e200526ee00 100644 --- a/pkg/runtime/conversion_test.go +++ b/pkg/runtime/conversion_test.go @@ -20,6 +20,7 @@ import ( "reflect" "testing" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/runtime" ) @@ -45,10 +46,14 @@ func (*InternalComplex) IsAnAPIObject() {} func (*ExternalComplex) IsAnAPIObject() {} func TestStringMapConversion(t *testing.T) { + internalGV := unversioned.GroupVersion{Group: "test.group", Version: ""} + externalGV := unversioned.GroupVersion{Group: "test.group", Version: "external"} + scheme := runtime.NewScheme() scheme.Log(t) - scheme.AddKnownTypeWithName("", "Complex", &InternalComplex{}) - scheme.AddKnownTypeWithName("external", "Complex", &ExternalComplex{}) + scheme.AddInternalGroupVersion(internalGV) + scheme.AddKnownTypeWithName(internalGV.WithKind("Complex"), &InternalComplex{}) + scheme.AddKnownTypeWithName(externalGV.WithKind("Complex"), &ExternalComplex{}) testCases := map[string]struct { input map[string][]string diff --git a/pkg/runtime/embedded_test.go b/pkg/runtime/embedded_test.go index ebb31846531..bc29ea0b2b6 100644 --- a/pkg/runtime/embedded_test.go +++ b/pkg/runtime/embedded_test.go @@ -63,14 +63,15 @@ func (*EmbeddedTestExternal) IsAnAPIObject() {} func TestDecodeEmptyRawExtensionAsObject(t *testing.T) { internalGV := unversioned.GroupVersion{Group: "test.group", Version: ""} - externalGVK := unversioned.GroupVersionKind{Group: "test.group", Version: "v1test", Kind: "ObjectTest"} + externalGV := unversioned.GroupVersion{Group: "test.group", Version: "v1test"} + externalGVK := externalGV.WithKind("ObjectTest") s := runtime.NewScheme() s.AddInternalGroupVersion(internalGV) - s.AddKnownTypes(internalGV.String(), &ObjectTest{}) - s.AddKnownTypeWithName(externalGVK.GroupVersion().String(), externalGVK.Kind, &ObjectTestExternal{}) + s.AddKnownTypes(internalGV, &ObjectTest{}) + s.AddKnownTypeWithName(externalGVK, &ObjectTestExternal{}) - obj, err := s.Decode([]byte(`{"kind":"` + externalGVK.Kind + `","apiVersion":"` + externalGVK.GroupVersion().String() + `","items":[{}]}`)) + obj, err := s.Decode([]byte(`{"kind":"` + externalGVK.Kind + `","apiVersion":"` + externalGV.String() + `","items":[{}]}`)) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -79,7 +80,7 @@ func TestDecodeEmptyRawExtensionAsObject(t *testing.T) { t.Fatalf("unexpected object: %#v", test.Items[0]) } - obj, err = s.Decode([]byte(`{"kind":"` + externalGVK.Kind + `","apiVersion":"` + externalGVK.GroupVersion().String() + `","items":[{"kind":"Other","apiVersion":"v1"}]}`)) + obj, err = s.Decode([]byte(`{"kind":"` + externalGVK.Kind + `","apiVersion":"` + externalGV.String() + `","items":[{"kind":"Other","apiVersion":"v1"}]}`)) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -95,10 +96,10 @@ func TestArrayOfRuntimeObject(t *testing.T) { s := runtime.NewScheme() s.AddInternalGroupVersion(internalGV) - s.AddKnownTypes(internalGV.String(), &EmbeddedTest{}) - s.AddKnownTypeWithName(externalGV.String(), "EmbeddedTest", &EmbeddedTestExternal{}) - s.AddKnownTypes(internalGV.String(), &ObjectTest{}) - s.AddKnownTypeWithName(externalGV.String(), "ObjectTest", &ObjectTestExternal{}) + s.AddKnownTypes(internalGV, &EmbeddedTest{}) + s.AddKnownTypeWithName(externalGV.WithKind("EmbeddedTest"), &EmbeddedTestExternal{}) + s.AddKnownTypes(internalGV, &ObjectTest{}) + s.AddKnownTypeWithName(externalGV.WithKind("ObjectTest"), &ObjectTestExternal{}) internal := &ObjectTest{ Items: []runtime.Object{ @@ -162,8 +163,8 @@ func TestEmbeddedObject(t *testing.T) { s := runtime.NewScheme() s.AddInternalGroupVersion(internalGV) - s.AddKnownTypes(internalGV.String(), &EmbeddedTest{}) - s.AddKnownTypeWithName(externalGV.String(), embeddedTestExternalGVK.Kind, &EmbeddedTestExternal{}) + s.AddKnownTypes(internalGV, &EmbeddedTest{}) + s.AddKnownTypeWithName(embeddedTestExternalGVK, &EmbeddedTestExternal{}) outer := &EmbeddedTest{ ID: "outer", @@ -226,8 +227,8 @@ func TestDeepCopyOfEmbeddedObject(t *testing.T) { s := runtime.NewScheme() s.AddInternalGroupVersion(internalGV) - s.AddKnownTypes(internalGV.String(), &EmbeddedTest{}) - s.AddKnownTypeWithName(externalGV.String(), embeddedTestExternalGVK.Kind, &EmbeddedTestExternal{}) + s.AddKnownTypes(internalGV, &EmbeddedTest{}) + s.AddKnownTypeWithName(embeddedTestExternalGVK, &EmbeddedTestExternal{}) original := &EmbeddedTest{ ID: "outer", diff --git a/pkg/runtime/scheme.go b/pkg/runtime/scheme.go index 49c9bd468eb..6e1162d4685 100644 --- a/pkg/runtime/scheme.go +++ b/pkg/runtime/scheme.go @@ -259,31 +259,33 @@ func NewScheme(internalGroupVersions ...unversioned.GroupVersion) *Scheme { return s } +// AddInternalGroupVersion registers an internal GroupVersion with the scheme. This can later be +// used to lookup the internal GroupVersion for a given Group func (s *Scheme) AddInternalGroupVersion(gv unversioned.GroupVersion) { s.raw.InternalVersions[gv.Group] = gv } // AddKnownTypes registers the types of the arguments to the marshaller of the package api. // Encode() refuses the object unless its type is registered with AddKnownTypes. -func (s *Scheme) AddKnownTypes(version string, types ...Object) { +func (s *Scheme) AddKnownTypes(gv unversioned.GroupVersion, types ...Object) { interfaces := make([]interface{}, len(types)) for i := range types { interfaces[i] = types[i] } - s.raw.AddKnownTypes(version, interfaces...) + s.raw.AddKnownTypes(gv, interfaces...) } // AddKnownTypeWithName is like AddKnownTypes, but it lets you specify what this type should // be encoded as. Useful for testing when you don't want to make multiple packages to define // your structs. -func (s *Scheme) AddKnownTypeWithName(version, kind string, obj Object) { - s.raw.AddKnownTypeWithName(version, kind, obj) +func (s *Scheme) AddKnownTypeWithName(gvk unversioned.GroupVersionKind, obj Object) { + s.raw.AddKnownTypeWithName(gvk, obj) } // KnownTypes returns the types known for the given version. // Return value must be treated as read-only. -func (s *Scheme) KnownTypes(version string) map[string]reflect.Type { - return s.raw.KnownTypes(version) +func (s *Scheme) KnownTypes(gv unversioned.GroupVersion) map[string]reflect.Type { + return s.raw.KnownTypes(gv) } // DataVersionAndKind will return the APIVersion and Kind of the given wire-format @@ -495,6 +497,8 @@ func (s *Scheme) DecodeInto(data []byte, obj Object) error { return s.raw.DecodeInto(data, obj) } +// DecodeIntoWithSpecifiedVersionKind coerces the data into the obj, assuming that the data is +// of type GroupVersionKind func (s *Scheme) DecodeIntoWithSpecifiedVersionKind(data []byte, obj Object, gvk unversioned.GroupVersionKind) error { return s.raw.DecodeIntoWithSpecifiedVersionKind(data, obj, gvk) } diff --git a/pkg/runtime/scheme_test.go b/pkg/runtime/scheme_test.go index 508eb2962a5..03e8ca2c558 100644 --- a/pkg/runtime/scheme_test.go +++ b/pkg/runtime/scheme_test.go @@ -46,13 +46,11 @@ func (*ExternalSimple) IsAnAPIObject() {} func TestScheme(t *testing.T) { internalGV := unversioned.GroupVersion{Group: "test.group", Version: ""} externalGV := unversioned.GroupVersion{Group: "test.group", Version: "testExternal"} - internalGVK := internalGV.WithKind("Simple") - externalGVK := externalGV.WithKind("Simple") scheme := runtime.NewScheme() scheme.AddInternalGroupVersion(internalGV) - scheme.AddKnownTypeWithName(internalGV.String(), internalGVK.Kind, &InternalSimple{}) - scheme.AddKnownTypeWithName(externalGV.String(), externalGVK.Kind, &ExternalSimple{}) + scheme.AddKnownTypeWithName(internalGV.WithKind("Simple"), &InternalSimple{}) + scheme.AddKnownTypeWithName(externalGV.WithKind("Simple"), &ExternalSimple{}) // test that scheme is an ObjectTyper var _ runtime.ObjectTyper = scheme @@ -138,8 +136,10 @@ func TestScheme(t *testing.T) { } func TestInvalidObjectValueKind(t *testing.T) { + internalGV := unversioned.GroupVersion{Group: "", Version: ""} + scheme := runtime.NewScheme() - scheme.AddKnownTypeWithName("", "Simple", &InternalSimple{}) + scheme.AddKnownTypeWithName(internalGV.WithKind("Simple"), &InternalSimple{}) embedded := &runtime.EmbeddedObject{} switch obj := embedded.Object.(type) { @@ -210,8 +210,8 @@ func TestExternalToInternalMapping(t *testing.T) { scheme := runtime.NewScheme() scheme.AddInternalGroupVersion(internalGV) - scheme.AddKnownTypeWithName(internalGV.String(), "OptionalExtensionType", &InternalOptionalExtensionType{}) - scheme.AddKnownTypeWithName(externalGV.String(), "OptionalExtensionType", &ExternalOptionalExtensionType{}) + scheme.AddKnownTypeWithName(internalGV.WithKind("OptionalExtensionType"), &InternalOptionalExtensionType{}) + scheme.AddKnownTypeWithName(externalGV.WithKind("OptionalExtensionType"), &ExternalOptionalExtensionType{}) table := []struct { obj runtime.Object @@ -246,14 +246,14 @@ func TestExtensionMapping(t *testing.T) { scheme := runtime.NewScheme() scheme.AddInternalGroupVersion(internalGV) - scheme.AddKnownTypeWithName(internalGV.String(), "ExtensionType", &InternalExtensionType{}) - scheme.AddKnownTypeWithName(internalGV.String(), "OptionalExtensionType", &InternalOptionalExtensionType{}) - scheme.AddKnownTypeWithName(internalGV.String(), "A", &ExtensionA{}) - scheme.AddKnownTypeWithName(internalGV.String(), "B", &ExtensionB{}) - scheme.AddKnownTypeWithName(externalGV.String(), "ExtensionType", &ExternalExtensionType{}) - scheme.AddKnownTypeWithName(externalGV.String(), "OptionalExtensionType", &ExternalOptionalExtensionType{}) - scheme.AddKnownTypeWithName(externalGV.String(), "A", &ExtensionA{}) - scheme.AddKnownTypeWithName(externalGV.String(), "B", &ExtensionB{}) + scheme.AddKnownTypeWithName(internalGV.WithKind("ExtensionType"), &InternalExtensionType{}) + scheme.AddKnownTypeWithName(internalGV.WithKind("OptionalExtensionType"), &InternalOptionalExtensionType{}) + scheme.AddKnownTypeWithName(internalGV.WithKind("A"), &ExtensionA{}) + scheme.AddKnownTypeWithName(internalGV.WithKind("B"), &ExtensionB{}) + scheme.AddKnownTypeWithName(externalGV.WithKind("ExtensionType"), &ExternalExtensionType{}) + scheme.AddKnownTypeWithName(externalGV.WithKind("OptionalExtensionType"), &ExternalOptionalExtensionType{}) + scheme.AddKnownTypeWithName(externalGV.WithKind("A"), &ExtensionA{}) + scheme.AddKnownTypeWithName(externalGV.WithKind("B"), &ExtensionB{}) table := []struct { obj runtime.Object @@ -304,8 +304,8 @@ func TestEncode(t *testing.T) { scheme := runtime.NewScheme() scheme.AddInternalGroupVersion(internalGV) - scheme.AddKnownTypeWithName(internalGV.String(), "Simple", &InternalSimple{}) - scheme.AddKnownTypeWithName(externalGV.String(), "Simple", &ExternalSimple{}) + scheme.AddKnownTypeWithName(internalGV.WithKind("Simple"), &InternalSimple{}) + scheme.AddKnownTypeWithName(externalGV.WithKind("Simple"), &ExternalSimple{}) codec := runtime.CodecFor(scheme, externalGV.String()) test := &InternalSimple{ TestString: "I'm the same", diff --git a/pkg/storage/etcd/etcd_helper_test.go b/pkg/storage/etcd/etcd_helper_test.go index 16c9c822231..41319b2dd84 100644 --- a/pkg/storage/etcd/etcd_helper_test.go +++ b/pkg/storage/etcd/etcd_helper_test.go @@ -47,8 +47,8 @@ var codec runtime.Codec func init() { scheme = runtime.NewScheme() - scheme.AddKnownTypes("", &storagetesting.TestResource{}) - scheme.AddKnownTypes(testapi.Default.Version(), &storagetesting.TestResource{}) + scheme.AddKnownTypes(testapi.Default.InternalGroupVersion(), &storagetesting.TestResource{}) + scheme.AddKnownTypes(*testapi.Default.GroupVersion(), &storagetesting.TestResource{}) codec = runtime.CodecFor(scheme, testapi.Default.Version()) scheme.AddConversionFuncs( func(in *storagetesting.TestResource, out *storagetesting.TestResource, s conversion.Scope) error { diff --git a/plugin/pkg/scheduler/api/register.go b/plugin/pkg/scheduler/api/register.go index ce58805dd93..ad70a531dae 100644 --- a/plugin/pkg/scheduler/api/register.go +++ b/plugin/pkg/scheduler/api/register.go @@ -17,14 +17,19 @@ limitations under the License. package api import ( + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/runtime" ) // Scheme is the default instance of runtime.Scheme to which types in the Kubernetes API are already registered. var Scheme = runtime.NewScheme() +// SchemeGroupVersion is group version used to register these objects +// TODO this should be in the "scheduler" group +var SchemeGroupVersion = unversioned.GroupVersion{Group: "", Version: ""} + func init() { - Scheme.AddKnownTypes("", + Scheme.AddKnownTypes(SchemeGroupVersion, &Policy{}, ) } diff --git a/plugin/pkg/scheduler/api/v1/register.go b/plugin/pkg/scheduler/api/v1/register.go index ea019d35c85..5f5cb49064f 100644 --- a/plugin/pkg/scheduler/api/v1/register.go +++ b/plugin/pkg/scheduler/api/v1/register.go @@ -17,15 +17,20 @@ limitations under the License. package v1 import ( + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/plugin/pkg/scheduler/api" ) +// SchemeGroupVersion is group version used to register these objects +// TODO this should be in the "scheduler" group +var SchemeGroupVersion = unversioned.GroupVersion{Group: "", Version: "v1"} + // Codec encodes internal objects to the v1 scheme -var Codec = runtime.CodecFor(api.Scheme, "v1") +var Codec = runtime.CodecFor(api.Scheme, SchemeGroupVersion.String()) func init() { - api.Scheme.AddKnownTypes("v1", + api.Scheme.AddKnownTypes(SchemeGroupVersion, &Policy{}, ) }