update scheme to use GroupVersion

This commit is contained in:
deads2k 2015-11-18 10:34:16 -05:00
parent 47e496364d
commit ed95a6d77f
34 changed files with 273 additions and 228 deletions

View File

@ -23,9 +23,9 @@ import (
"os" "os"
"path" "path"
"runtime" "runtime"
"strings"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
_ "k8s.io/kubernetes/pkg/api/v1" _ "k8s.io/kubernetes/pkg/api/v1"
_ "k8s.io/kubernetes/pkg/apis/componentconfig" _ "k8s.io/kubernetes/pkg/apis/componentconfig"
_ "k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1" _ "k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1"
@ -84,33 +84,24 @@ func main() {
data := new(bytes.Buffer) data := new(bytes.Buffer)
group, version := path.Split(*groupVersion) gv := unversioned.ParseGroupVersionOrDie(*groupVersion)
group = strings.TrimRight(group, "/")
_, err := data.WriteString(fmt.Sprintf("package %v\n", version)) _, err := data.WriteString(fmt.Sprintf("package %v\n", gv.Version))
if err != nil { if err != nil {
glog.Fatalf("Error while writing package line: %v", err) glog.Fatalf("Error while writing package line: %v", err)
} }
var schemeVersion string versionPath := pkgPath(gv.Group, gv.Version)
if *groupVersion == "" || *groupVersion == "/" {
// This occurs when we generate deep-copy for internal version.
schemeVersion = ""
} else {
schemeVersion = *groupVersion
}
versionPath := pkgPath(group, version)
generator := kruntime.NewConversionGenerator(api.Scheme.Raw(), versionPath) generator := kruntime.NewConversionGenerator(api.Scheme.Raw(), versionPath)
apiShort := generator.AddImport(path.Join(pkgBase, "api")) apiShort := generator.AddImport(path.Join(pkgBase, "api"))
generator.AddImport(path.Join(pkgBase, "api/resource")) generator.AddImport(path.Join(pkgBase, "api/resource"))
// TODO(wojtek-t): Change the overwrites to a flag. // TODO(wojtek-t): Change the overwrites to a flag.
generator.OverwritePackage(version, "") generator.OverwritePackage(gv.Version, "")
for _, knownType := range api.Scheme.KnownTypes(schemeVersion) { for _, knownType := range api.Scheme.KnownTypes(gv) {
if knownType.PkgPath() != versionPath { if knownType.PkgPath() != versionPath {
continue 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) glog.Errorf("Error while generating conversion functions for %v: %v", knownType, err)
} }
} }

View File

@ -26,6 +26,7 @@ import (
"strings" "strings"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
_ "k8s.io/kubernetes/pkg/api/v1" _ "k8s.io/kubernetes/pkg/api/v1"
_ "k8s.io/kubernetes/pkg/apis/componentconfig" _ "k8s.io/kubernetes/pkg/apis/componentconfig"
_ "k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1" _ "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. // types inside the api package don't need to say "api.Scheme"; all others do.
func destScheme(group, version string) string { func destScheme(gv unversioned.GroupVersion) string {
if group == "" && version == "" { if gv == api.SchemeGroupVersion {
return "Scheme" return "Scheme"
} }
return "api.Scheme" return "api.Scheme"
@ -93,18 +94,18 @@ func main() {
data := new(bytes.Buffer) data := new(bytes.Buffer)
group, version := path.Split(*groupVersion) gv := unversioned.ParseGroupVersionOrDie(*groupVersion)
group = strings.TrimRight(group, "/")
registerTo := destScheme(group, version) registerTo := destScheme(gv)
var pkgname string var pkgname string
if group == "" { if gv.Group == "" {
// the internal version of v1 is registered in package api // the internal version of v1 is registered in package api
pkgname = "api" pkgname = "api"
} else { } else {
pkgname = group pkgname = gv.Group
} }
if len(version) != 0 { if len(gv.Version) != 0 {
pkgname = version pkgname = gv.Version
} }
_, err := data.WriteString(fmt.Sprintf("package %s\n", pkgname)) _, err := data.WriteString(fmt.Sprintf("package %s\n", pkgname))
@ -112,7 +113,7 @@ func main() {
glog.Fatalf("Error while writing package line: %v", err) 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 := kruntime.NewDeepCopyGenerator(api.Scheme.Raw(), versionPath, sets.NewString("k8s.io/kubernetes"))
generator.AddImport(path.Join(pkgBase, "api")) generator.AddImport(path.Join(pkgBase, "api"))
@ -126,14 +127,7 @@ func main() {
} }
} }
var schemeVersion string for _, knownType := range api.Scheme.KnownTypes(gv) {
if *groupVersion == "" || *groupVersion == "/" {
// This occurs when we generate deep-copy for internal version.
schemeVersion = ""
} else {
schemeVersion = *groupVersion
}
for _, knownType := range api.Scheme.KnownTypes(schemeVersion) {
if knownType.PkgPath() != versionPath { if knownType.PkgPath() != versionPath {
continue continue
} }

View File

@ -24,6 +24,7 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/testapi"
apitesting "k8s.io/kubernetes/pkg/api/testing" apitesting "k8s.io/kubernetes/pkg/api/testing"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
"github.com/google/gofuzz" "github.com/google/gofuzz"
@ -31,10 +32,10 @@ import (
func TestDeepCopyApiObjects(t *testing.T) { func TestDeepCopyApiObjects(t *testing.T) {
for i := 0; i < *fuzzIters; i++ { for i := 0; i < *fuzzIters; i++ {
for _, version := range []string{"", testapi.Default.Version()} { for _, gv := range []unversioned.GroupVersion{testapi.Default.InternalGroupVersion(), *testapi.Default.GroupVersion()} {
f := apitesting.FuzzerFor(t, version, rand.NewSource(rand.Int63())) f := apitesting.FuzzerFor(t, gv.String(), rand.NewSource(rand.Int63()))
for kind := range api.Scheme.KnownTypes(version) { for kind := range api.Scheme.KnownTypes(gv) {
doDeepCopyTest(t, version, kind, f) doDeepCopyTest(t, gv.String(), kind, f)
} }
} }
} }

View File

@ -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 // enumerate all supported versions, get the kinds, and register with the mapper how to address
// our resources. // our resources.
for _, gv := range defaultGroupVersions { for _, gv := range defaultGroupVersions {
for kind, oType := range Scheme.KnownTypes(gv.String()) { for kind, oType := range Scheme.KnownTypes(gv) {
gvk := gv.WithKind(kind) gvk := gv.WithKind(kind)
// TODO: Remove import path prefix check. // TODO: Remove import path prefix check.
// We check the import path prefix because we currently stuff both "api" and "extensions" objects // 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. // into the same group within Scheme since Scheme has no notion of groups yet.

View File

@ -24,8 +24,11 @@ import (
// Scheme is the default instance of runtime.Scheme to which types in the Kubernetes API are already registered. // Scheme is the default instance of runtime.Scheme to which types in the Kubernetes API are already registered.
var Scheme = runtime.NewScheme() var Scheme = runtime.NewScheme()
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = unversioned.GroupVersion{Group: "", Version: ""}
func init() { func init() {
Scheme.AddKnownTypes("", Scheme.AddKnownTypes(SchemeGroupVersion,
&Pod{}, &Pod{},
&PodList{}, &PodList{},
&PodStatusResult{}, &PodStatusResult{},
@ -69,12 +72,13 @@ func init() {
) )
// Register Unversioned types // Register Unversioned types
Scheme.AddKnownTypes("", &unversioned.ListOptions{}) // TODO this should not be done here
Scheme.AddKnownTypes("", &unversioned.Status{}) Scheme.AddKnownTypes(SchemeGroupVersion, &unversioned.ListOptions{})
Scheme.AddKnownTypes("", &unversioned.APIVersions{}) Scheme.AddKnownTypes(SchemeGroupVersion, &unversioned.Status{})
Scheme.AddKnownTypes("", &unversioned.APIGroupList{}) Scheme.AddKnownTypes(SchemeGroupVersion, &unversioned.APIVersions{})
Scheme.AddKnownTypes("", &unversioned.APIGroup{}) Scheme.AddKnownTypes(SchemeGroupVersion, &unversioned.APIGroupList{})
Scheme.AddKnownTypes("", &unversioned.APIResourceList{}) Scheme.AddKnownTypes(SchemeGroupVersion, &unversioned.APIGroup{})
Scheme.AddKnownTypes(SchemeGroupVersion, &unversioned.APIResourceList{})
} }
func (*Pod) IsAnAPIObject() {} func (*Pod) IsAnAPIObject() {}

View File

@ -135,7 +135,7 @@ func TestRoundTripTypes(t *testing.T) {
// api.Scheme.Log(t) // api.Scheme.Log(t)
// defer api.Scheme.Log(nil) // defer api.Scheme.Log(nil)
for kind := range api.Scheme.KnownTypes("") { for kind := range api.Scheme.KnownTypes(testapi.Default.InternalGroupVersion()) {
if nonRoundTrippableTypes.Has(kind) { if nonRoundTrippableTypes.Has(kind) {
continue continue
} }

View File

@ -24,12 +24,12 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
_ "k8s.io/kubernetes/pkg/api/install" _ "k8s.io/kubernetes/pkg/api/install"
"k8s.io/kubernetes/pkg/api/unversioned"
_ "k8s.io/kubernetes/pkg/apis/extensions/install" _ "k8s.io/kubernetes/pkg/apis/extensions/install"
_ "k8s.io/kubernetes/pkg/apis/metrics/install" _ "k8s.io/kubernetes/pkg/apis/metrics/install"
"k8s.io/kubernetes/pkg/api/latest" "k8s.io/kubernetes/pkg/api/latest"
"k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/unversioned"
apiutil "k8s.io/kubernetes/pkg/api/util" apiutil "k8s.io/kubernetes/pkg/api/util"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
) )
@ -89,11 +89,13 @@ func (g TestGroup) GroupAndVersion() string {
} }
func (g TestGroup) GroupVersion() *unversioned.GroupVersion { func (g TestGroup) GroupVersion() *unversioned.GroupVersion {
gv, err := unversioned.ParseGroupVersion(g.GroupVersionUnderTest) return &unversioned.GroupVersion{Group: g.Group, Version: g.VersionUnderTest}
if err != nil { }
panic(err)
} // InternalGroupVersion returns the group,version used to identify the internal
return &gv // 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 // Codec returns the codec for the API version to test against, as set by the

View File

@ -49,6 +49,7 @@ type GroupVersion struct {
Version string Version string
} }
// IsEmpty returns true if group and version are empty
func (gv GroupVersion) IsEmpty() bool { func (gv GroupVersion) IsEmpty() bool {
return len(gv.Group) == 0 && len(gv.Version) == 0 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 // String puts "group" and "version" into a single "group/version" string. For the legacy v1
// it returns "v1". // it returns "v1".
func (gv GroupVersion) String() string { 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() { if gv.IsEmpty() {
return "" return ""
} }
@ -72,7 +73,8 @@ func (gv GroupVersion) String() string {
// ParseGroupVersion turns "group/version" string into a GroupVersion struct. It reports error // ParseGroupVersion turns "group/version" string into a GroupVersion struct. It reports error
// if it cannot parse the string. // if it cannot parse the string.
func ParseGroupVersion(gv string) (GroupVersion, error) { 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 == "/") { if (len(gv) == 0) || (gv == "/") {
return GroupVersion{}, nil return GroupVersion{}, nil
} }
@ -99,6 +101,7 @@ func ParseGroupVersionOrDie(gv string) GroupVersion {
return ret return ret
} }
// WithKind creates a GroupVersionKind based on the method receiver's GroupVersion and the passed Kind.
func (gv GroupVersion) WithKind(kind string) GroupVersionKind { func (gv GroupVersion) WithKind(kind string) GroupVersionKind {
return GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: kind} return GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: kind}
} }

View File

@ -23,12 +23,15 @@ import (
"k8s.io/kubernetes/pkg/runtime" "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 // 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() { func init() {
// Check if v1 is in the list of supported API versions. // Check if v1 is in the list of supported API versions.
if !registered.IsRegisteredAPIGroupVersion(unversioned.GroupVersion{Group: "", Version: "v1"}) { if !registered.IsRegisteredAPIGroupVersion(SchemeGroupVersion) {
return return
} }
@ -40,7 +43,7 @@ func init() {
// Adds the list of known types to api.Scheme. // Adds the list of known types to api.Scheme.
func addKnownTypes() { func addKnownTypes() {
api.Scheme.AddKnownTypes("v1", api.Scheme.AddKnownTypes(SchemeGroupVersion,
&Pod{}, &Pod{},
&PodList{}, &PodList{},
&PodStatusResult{}, &PodStatusResult{},
@ -85,7 +88,7 @@ func addKnownTypes() {
) )
// Add common types // Add common types
api.Scheme.AddKnownTypes("v1", &unversioned.Status{}) api.Scheme.AddKnownTypes(SchemeGroupVersion, &unversioned.Status{})
} }
func (*Pod) IsAnAPIObject() {} func (*Pod) IsAnAPIObject() {}

View File

@ -18,15 +18,19 @@ package componentconfig
import ( import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
) )
func init() { func init() {
addKnownTypes() addKnownTypes()
} }
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = unversioned.GroupVersion{Group: "componentconfig", Version: ""}
func addKnownTypes() { func addKnownTypes() {
// TODO this will get cleaned up with the scheme types are fixed // TODO this will get cleaned up with the scheme types are fixed
api.Scheme.AddKnownTypes("componentconfig/", api.Scheme.AddKnownTypes(SchemeGroupVersion,
&KubeProxyConfiguration{}, &KubeProxyConfiguration{},
) )
} }

View File

@ -18,10 +18,14 @@ package v1alpha1
import ( import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/runtime" "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() { func init() {
addKnownTypes() addKnownTypes()
@ -29,7 +33,7 @@ func init() {
} }
func addKnownTypes() { func addKnownTypes() {
api.Scheme.AddKnownTypes("componentconfig/v1alpha1", api.Scheme.AddKnownTypes(SchemeGroupVersion,
&KubeProxyConfiguration{}, &KubeProxyConfiguration{},
) )
} }

View File

@ -18,8 +18,12 @@ package extensions
import ( import (
"k8s.io/kubernetes/pkg/api" "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() { func init() {
// Register the API. // Register the API.
addKnownTypes() addKnownTypes()
@ -28,7 +32,7 @@ func init() {
// Adds the list of known types to api.Scheme. // Adds the list of known types to api.Scheme.
func addKnownTypes() { func addKnownTypes() {
// TODO this gets cleaned up when the types are fixed // TODO this gets cleaned up when the types are fixed
api.Scheme.AddKnownTypes("extensions/", api.Scheme.AddKnownTypes(SchemeGroupVersion,
&ClusterAutoscaler{}, &ClusterAutoscaler{},
&ClusterAutoscalerList{}, &ClusterAutoscalerList{},
&Deployment{}, &Deployment{},

View File

@ -18,10 +18,14 @@ package v1beta1
import ( import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/runtime" "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() { func init() {
addKnownTypes() addKnownTypes()
@ -31,7 +35,7 @@ func init() {
// Adds the list of known types to api.Scheme. // Adds the list of known types to api.Scheme.
func addKnownTypes() { func addKnownTypes() {
api.Scheme.AddKnownTypes("extensions/v1beta1", api.Scheme.AddKnownTypes(SchemeGroupVersion,
&ClusterAutoscaler{}, &ClusterAutoscaler{},
&ClusterAutoscalerList{}, &ClusterAutoscalerList{},
&Deployment{}, &Deployment{},

View File

@ -18,6 +18,7 @@ package metrics
import ( import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
) )
func init() { func init() {
@ -25,10 +26,13 @@ func init() {
addKnownTypes() 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. // Adds the list of known types to api.Scheme.
func addKnownTypes() { func addKnownTypes() {
// TODO this will get cleaned up with the scheme types are fixed // TODO this will get cleaned up with the scheme types are fixed
api.Scheme.AddKnownTypes("metrics/", api.Scheme.AddKnownTypes(SchemeGroupVersion,
&RawNode{}, &RawNode{},
&RawPod{}, &RawPod{},
) )

View File

@ -18,10 +18,14 @@ package v1alpha1
import ( import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/runtime" "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() { func init() {
// Register the API. // Register the API.
@ -30,7 +34,7 @@ func init() {
// Adds the list of known types to api.Scheme. // Adds the list of known types to api.Scheme.
func addKnownTypes() { func addKnownTypes() {
api.Scheme.AddKnownTypes("metrics/v1alpha1", api.Scheme.AddKnownTypes(SchemeGroupVersion,
&RawNode{}, &RawNode{},
&RawPod{}, &RawPod{},
) )

View File

@ -113,21 +113,21 @@ func newMapper() *meta.DefaultRESTMapper {
func addGrouplessTypes() { func addGrouplessTypes() {
api.Scheme.AddKnownTypes( 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{}) &unversioned.ListOptions{}, &api.DeleteOptions{}, &apiservertesting.SimpleGetOptions{}, &apiservertesting.SimpleRoot{})
api.Scheme.AddKnownTypes(grouplessGroupVersion.String(), &api.Pod{}) api.Scheme.AddKnownTypes(grouplessGroupVersion, &api.Pod{})
} }
func addTestTypes() { func addTestTypes() {
api.Scheme.AddKnownTypes( 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{}) &unversioned.ListOptions{}, &api.DeleteOptions{}, &apiservertesting.SimpleGetOptions{}, &apiservertesting.SimpleRoot{})
api.Scheme.AddKnownTypes(testGroupVersion.String(), &api.Pod{}) api.Scheme.AddKnownTypes(testGroupVersion, &api.Pod{})
} }
func addNewTestTypes() { func addNewTestTypes() {
api.Scheme.AddKnownTypes( 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{}) &unversioned.ListOptions{}, &api.DeleteOptions{}, &apiservertesting.SimpleGetOptions{}, &apiservertesting.SimpleRoot{})
} }
@ -137,7 +137,7 @@ func init() {
// "internal" version // "internal" version
api.Scheme.AddKnownTypes( api.Scheme.AddKnownTypes(
testInternalGroupVersion.String(), &apiservertesting.Simple{}, &apiservertesting.SimpleList{}, &unversioned.Status{}, testInternalGroupVersion, &apiservertesting.Simple{}, &apiservertesting.SimpleList{}, &unversioned.Status{},
&unversioned.ListOptions{}, &apiservertesting.SimpleGetOptions{}, &apiservertesting.SimpleRoot{}) &unversioned.ListOptions{}, &apiservertesting.SimpleGetOptions{}, &apiservertesting.SimpleRoot{})
api.Scheme.AddInternalGroupVersion(testInternalGroupVersion) api.Scheme.AddInternalGroupVersion(testInternalGroupVersion)
addGrouplessTypes() addGrouplessTypes()
@ -149,9 +149,8 @@ func init() {
// enumerate all supported versions, get the kinds, and register with // enumerate all supported versions, get the kinds, and register with
// the mapper how to address our resources // the mapper how to address our resources
for _, gv := range groupVersions { for _, gv := range groupVersions {
for kind := range api.Scheme.KnownTypes(gv.String()) { for kind := range api.Scheme.KnownTypes(gv) {
gvk := gv.WithKind(kind) gvk := gv.WithKind(kind)
root := bool(kind == "SimpleRoot") root := bool(kind == "SimpleRoot")
if root { if root {
nsMapper.Add(gvk, meta.RESTScopeRoot, false) nsMapper.Add(gvk, meta.RESTScopeRoot, false)

View File

@ -17,14 +17,19 @@ limitations under the License.
package api package api
import ( import (
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
) )
// Scheme is the default instance of runtime.Scheme to which types in the Kubernetes API are already registered. // Scheme is the default instance of runtime.Scheme to which types in the Kubernetes API are already registered.
var Scheme = runtime.NewScheme() 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() { func init() {
Scheme.AddKnownTypes("", Scheme.AddKnownTypes(SchemeGroupVersion,
&Config{}, &Config{},
) )
} }

View File

@ -17,15 +17,20 @@ limitations under the License.
package v1 package v1
import ( import (
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
"k8s.io/kubernetes/pkg/runtime" "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 // 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() { func init() {
api.Scheme.AddKnownTypes("v1", api.Scheme.AddKnownTypes(SchemeGroupVersion,
&Config{}, &Config{},
) )
} }

View File

@ -124,14 +124,14 @@ func (s *Scheme) DecodeInto(data []byte, obj interface{}) error {
return s.DecodeIntoWithSpecifiedVersionKind(data, obj, unversioned.GroupVersionKind{}) return s.DecodeIntoWithSpecifiedVersionKind(data, obj, unversioned.GroupVersionKind{})
} }
// DecodeIntoWithSpecifiedVersionKind compares the passed in specifiedVersion and // DecodeIntoWithSpecifiedVersionKind compares the passed in requestGroupVersionKind
// specifiedKind with data.Version and data.Kind, defaulting data.Version and // 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.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. // data.Version and data.Kind are not empty and differ from the specified value.
// The function then implements the functionality of DecodeInto. // The function then implements the functionality of DecodeInto.
// If specifiedVersion and specifiedKind are empty, the function degenerates to // If specifiedVersion and specifiedKind are empty, the function degenerates to
// DecodeInto. // 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 { if len(data) == 0 {
return errors.New("empty input") return errors.New("empty input")
} }
@ -140,16 +140,16 @@ func (s *Scheme) DecodeIntoWithSpecifiedVersionKind(data []byte, obj interface{}
return err return err
} }
if dataVersion == "" { if dataVersion == "" {
dataVersion = gvk.GroupVersion().String() dataVersion = requestedGVK.GroupVersion().String()
} }
if dataKind == "" { if dataKind == "" {
dataKind = gvk.Kind dataKind = requestedGVK.Kind
} }
if (len(gvk.Group) > 0 || len(gvk.Version) > 0) && (dataVersion != gvk.GroupVersion().String()) { 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, gvk.GroupVersion())) 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) { 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, gvk)) 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) objVersion, objKind, err := s.ObjectVersionAndKind(obj)

View File

@ -77,7 +77,7 @@ func (s *Scheme) EncodeToVersionStream(obj interface{}, destVersion string, stre
return err 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) 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)
} }

View File

@ -130,8 +130,8 @@ func TestMetaValues(t *testing.T) {
s := NewScheme() s := NewScheme()
s.InternalVersions[internalGV.Group] = internalGV s.InternalVersions[internalGV.Group] = internalGV
s.AddKnownTypeWithName(internalGV.String(), "Simple", &InternalSimple{}) s.AddKnownTypeWithName(internalGV.WithKind("Simple"), &InternalSimple{})
s.AddKnownTypeWithName(externalGV.String(), "Simple", &ExternalSimple{}) s.AddKnownTypeWithName(externalGV.WithKind("Simple"), &ExternalSimple{})
internalToExternalCalls := 0 internalToExternalCalls := 0
externalToInternalCalls := 0 externalToInternalCalls := 0

View File

@ -27,16 +27,11 @@ import (
type Scheme struct { type Scheme struct {
// versionMap allows one to figure out the go type of an object with // versionMap allows one to figure out the go type of an object with
// the given version and name. // 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. // typeToGroupVersion allows one to find metadata for a given go object.
// The reflect.Type we index by should *not* be a pointer. If the same type // The reflect.Type we index by should *not* be a pointer.
// is registered for multiple versions, the last one wins. typeToGVK map[reflect.Type][]unversioned.GroupVersionKind
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
// converter stores all registered conversion functions. It also has // converter stores all registered conversion functions. It also has
// default coverting behavior. // default coverting behavior.
@ -65,11 +60,10 @@ type Scheme struct {
// NewScheme manufactures a new scheme. // NewScheme manufactures a new scheme.
func NewScheme() *Scheme { func NewScheme() *Scheme {
s := &Scheme{ s := &Scheme{
versionMap: map[string]map[string]reflect.Type{}, gvkToType: map[unversioned.GroupVersionKind]reflect.Type{},
typeToVersion: map[reflect.Type]string{}, typeToGVK: map[reflect.Type][]unversioned.GroupVersionKind{},
typeToKind: map[reflect.Type][]string{}, converter: NewConverter(),
converter: NewConverter(), cloner: NewCloner(),
cloner: NewCloner(),
// TODO remove this hard coded list. As step one, hardcode it here so this pull doesn't become even bigger // 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{ 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. // a conversion. Defaults to the go name of the type if the type is not registered.
func (s *Scheme) nameFunc(t reflect.Type) string { func (s *Scheme) nameFunc(t reflect.Type) string {
// find the preferred names for this type // find the preferred names for this type
names, ok := s.typeToKind[t] gvks, ok := s.typeToGVK[t]
if !ok { if !ok {
return t.Name() return t.Name()
} }
if internal, ok := s.versionMap[""]; ok {
for _, name := range names { for _, gvk := range gvks {
if t, ok := internal[name]; ok { internalGV, exists := s.InternalVersions[gvk.Group]
return s.typeToKind[t][0] 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. // 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 // All objects passed to types should be pointers to structs. The name that go reports for
// the struct becomes the "kind" field when encoding. // the struct becomes the "kind" field when encoding.
func (s *Scheme) AddKnownTypes(version string, types ...interface{}) { func (s *Scheme) AddKnownTypes(gv unversioned.GroupVersion, types ...interface{}) {
knownTypes, found := s.versionMap[version]
if !found {
knownTypes = map[string]reflect.Type{}
s.versionMap[version] = knownTypes
}
for _, obj := range types { for _, obj := range types {
t := reflect.TypeOf(obj) t := reflect.TypeOf(obj)
if t.Kind() != reflect.Ptr { if t.Kind() != reflect.Ptr {
@ -125,21 +121,17 @@ func (s *Scheme) AddKnownTypes(version string, types ...interface{}) {
if t.Kind() != reflect.Struct { if t.Kind() != reflect.Struct {
panic("All types must be pointers to structs.") panic("All types must be pointers to structs.")
} }
knownTypes[t.Name()] = t
s.typeToVersion[t] = version gvk := gv.WithKind(t.Name())
s.typeToKind[t] = append(s.typeToKind[t], 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 // 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 // be encoded as. Useful for testing when you don't want to make multiple packages to define
// your structs. // your structs.
func (s *Scheme) AddKnownTypeWithName(version, kind string, obj interface{}) { func (s *Scheme) AddKnownTypeWithName(gvk unversioned.GroupVersionKind, obj interface{}) {
knownTypes, found := s.versionMap[version]
if !found {
knownTypes = map[string]reflect.Type{}
s.versionMap[version] = knownTypes
}
t := reflect.TypeOf(obj) t := reflect.TypeOf(obj)
if t.Kind() != reflect.Ptr { if t.Kind() != reflect.Ptr {
panic("All types must be pointers to structs.") 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 { if t.Kind() != reflect.Struct {
panic("All types must be pointers to structs.") panic("All types must be pointers to structs.")
} }
knownTypes[kind] = t
s.typeToVersion[t] = version s.gvkToType[gvk] = t
s.typeToKind[t] = append(s.typeToKind[t], kind) s.typeToGVK[t] = append(s.typeToGVK[t], gvk)
} }
// KnownTypes returns an array of the types that are known for a particular version. // KnownTypes returns an array of the types that are known for a particular version.
func (s *Scheme) KnownTypes(version string) map[string]reflect.Type { func (s *Scheme) KnownTypes(gv unversioned.GroupVersion) map[string]reflect.Type {
all, ok := s.versionMap[version] types := map[string]reflect.Type{}
if !ok {
return map[string]reflect.Type{} for gvk, t := range s.gvkToType {
} if gv != gvk.GroupVersion() {
types := make(map[string]reflect.Type) continue
for k, v := range all { }
types[k] = v
types[gvk.Kind] = t
} }
return types return types
} }
@ -175,12 +170,8 @@ func (s *Scheme) NewObject(gvString, kind string) (interface{}, error) {
} }
gvk := gv.WithKind(kind) gvk := gv.WithKind(kind)
if types, ok := s.versionMap[gvString]; ok { if t, exists := s.gvkToType[gvk]; exists {
if t, ok := types[kind]; ok { return reflect.New(t).Interface(), nil
return reflect.New(t).Interface(), nil
}
return nil, &notRegisteredErr{gvk: gvk}
} }
return nil, &notRegisteredErr{gvk: gvk} return nil, &notRegisteredErr{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 // Recognizes returns true if the scheme is able to handle the provided version and kind
// of an object. // of an object.
func (s *Scheme) Recognizes(version, kind string) bool { func (s *Scheme) Recognizes(gvString, kind string) bool {
m, ok := s.versionMap[version] gv, err := unversioned.ParseGroupVersion(gvString)
if !ok { if err != nil {
return false return false
} }
_, ok = m[kind] gvk := gv.WithKind(kind)
return ok
_, exists := s.gvkToType[gvk]
return exists
} }
// RegisterInputDefaults sets the provided field mapping function and field matching // 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) 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 { if !ok {
return nil, fmt.Errorf("%v cannot be converted into version %q", t, outVersion) return nil, fmt.Errorf("%v cannot be converted into version %q", t, outVersion)
} }
outKind := kinds[0] outKind := gvks[0]
inVersion, _, err := s.ObjectVersionAndKind(in) inVersion, _, err := s.ObjectVersionAndKind(in)
if err != nil { if err != nil {
return nil, err return nil, err
} }
out, err := s.NewObject(outVersion, outKind) out, err := s.NewObject(outVersion, outKind.Kind)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -370,7 +363,7 @@ func (s *Scheme) ConvertToVersion(in interface{}, outVersion string) (interface{
return nil, err 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 return nil, err
} }
@ -406,13 +399,13 @@ func (s *Scheme) ObjectVersionAndKind(obj interface{}) (apiVersion, kind string,
return "", "", err return "", "", err
} }
t := v.Type() t := v.Type()
version, vOK := s.typeToVersion[t]
kinds, kOK := s.typeToKind[t] gvks, ok := s.typeToGVK[t]
if !vOK || !kOK { if !ok {
return "", "", &notRegisteredErr{t: t} return "", "", &notRegisteredErr{t: t}
} }
apiVersion = version apiVersion = gvks[0].GroupVersion().String()
kind = kinds[0] kind = gvks[0].Kind
return return
} }

View File

@ -109,16 +109,19 @@ var TestObjectFuzzer = fuzz.New().NilChance(.5).NumElements(1, 100).Funcs(
// Returns a new Scheme set up with the test objects. // Returns a new Scheme set up with the test objects.
func GetTestScheme() *Scheme { func GetTestScheme() *Scheme {
internalGV := unversioned.GroupVersion{}
externalGV := unversioned.GroupVersion{Version: "v1"}
s := NewScheme() s := NewScheme()
// Ordinarily, we wouldn't add TestType2, but because this is a test and // 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 // both types are from the same package, we need to get it into the system
// so that converter will match it with ExternalType2. // so that converter will match it with ExternalType2.
s.AddKnownTypes("", &TestType1{}, &TestType2{}, &ExternalInternalSame{}) s.AddKnownTypes(internalGV, &TestType1{}, &TestType2{}, &ExternalInternalSame{})
s.AddKnownTypes("v1", &ExternalInternalSame{}) s.AddKnownTypes(externalGV, &ExternalInternalSame{})
s.AddKnownTypeWithName("v1", "TestType1", &ExternalTestType1{}) s.AddKnownTypeWithName(externalGV.WithKind("TestType1"), &ExternalTestType1{})
s.AddKnownTypeWithName("v1", "TestType2", &ExternalTestType2{}) s.AddKnownTypeWithName(externalGV.WithKind("TestType2"), &ExternalTestType2{})
s.AddKnownTypeWithName("", "TestType3", &TestType1{}) s.AddKnownTypeWithName(internalGV.WithKind("TestType3"), &TestType1{})
s.AddKnownTypeWithName("v1", "TestType3", &ExternalTestType1{}) s.AddKnownTypeWithName(externalGV.WithKind("TestType3"), &ExternalTestType1{})
s.MetaFactory = testMetaFactory{} s.MetaFactory = testMetaFactory{}
return s return s
} }
@ -229,13 +232,16 @@ func TestMultipleNames(t *testing.T) {
} }
func TestConvertTypesWhenDefaultNamesMatch(t *testing.T) { func TestConvertTypesWhenDefaultNamesMatch(t *testing.T) {
internalGV := unversioned.GroupVersion{}
externalGV := unversioned.GroupVersion{Version: "v1"}
s := NewScheme() s := NewScheme()
// create two names internally, with TestType1 being preferred // create two names internally, with TestType1 being preferred
s.AddKnownTypeWithName("", "TestType1", &TestType1{}) s.AddKnownTypeWithName(internalGV.WithKind("TestType1"), &TestType1{})
s.AddKnownTypeWithName("", "OtherType1", &TestType1{}) s.AddKnownTypeWithName(internalGV.WithKind("OtherType1"), &TestType1{})
// create two names externally, with TestType1 being preferred // create two names externally, with TestType1 being preferred
s.AddKnownTypeWithName("v1", "TestType1", &ExternalTestType1{}) s.AddKnownTypeWithName(externalGV.WithKind("TestType1"), &ExternalTestType1{})
s.AddKnownTypeWithName("v1", "OtherType1", &ExternalTestType1{}) s.AddKnownTypeWithName(externalGV.WithKind("OtherType1"), &ExternalTestType1{})
s.MetaFactory = testMetaFactory{} s.MetaFactory = testMetaFactory{}
ext := &ExternalTestType1{} ext := &ExternalTestType1{}
@ -267,11 +273,11 @@ func TestConvertTypesWhenDefaultNamesMatch(t *testing.T) {
func TestKnownTypes(t *testing.T) { func TestKnownTypes(t *testing.T) {
s := GetTestScheme() 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") 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"} { for _, s := range []string{"TestType1", "TestType2", "TestType3", "ExternalInternalSame"} {
if _, ok := types[s]; !ok { if _, ok := types[s]; !ok {
t.Errorf("missing type %q", s) t.Errorf("missing type %q", s)

View File

@ -85,10 +85,10 @@ var validVersionGV = unversioned.GroupVersion{Group: "apitest", Version: validVe
func newExternalScheme() (*runtime.Scheme, meta.RESTMapper, runtime.Codec) { func newExternalScheme() (*runtime.Scheme, meta.RESTMapper, runtime.Codec) {
scheme := runtime.NewScheme() scheme := runtime.NewScheme()
scheme.AddInternalGroupVersion(internalGV) scheme.AddInternalGroupVersion(internalGV)
scheme.AddKnownTypeWithName(internalGV.String(), "Type", &internalType{}) scheme.AddKnownTypeWithName(internalGV.WithKind("Type"), &internalType{})
scheme.AddKnownTypeWithName(unlikelyGV.String(), "Type", &externalType{}) 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. //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()) codec := runtime.CodecFor(scheme, unlikelyGV.String())
mapper := meta.NewDefaultRESTMapper([]unversioned.GroupVersion{unlikelyGV, validVersionGV}, func(version string) (*meta.VersionInterfaces, error) { 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()) }, versionErrIfFalse(version == validVersionGV.String() || version == unlikelyGV.String())
}) })
for _, gv := range []unversioned.GroupVersion{unlikelyGV, validVersionGV} { for _, gv := range []unversioned.GroupVersion{unlikelyGV, validVersionGV} {
for kind := range scheme.KnownTypes(gv.String()) { for kind := range scheme.KnownTypes(gv) {
gvk := gv.WithKind(kind) gvk := gv.WithKind(kind)
mixedCase := false mixedCase := false

View File

@ -40,8 +40,8 @@ import (
) )
func init() { func init() {
api.Scheme.AddKnownTypes("", &kubectltesting.TestStruct{}) api.Scheme.AddKnownTypes(testapi.Default.InternalGroupVersion(), &kubectltesting.TestStruct{})
api.Scheme.AddKnownTypes(testapi.Default.Version(), &kubectltesting.TestStruct{}) api.Scheme.AddKnownTypes(*testapi.Default.GroupVersion(), &kubectltesting.TestStruct{})
} }
var testData = kubectltesting.TestStruct{ var testData = kubectltesting.TestStruct{

View File

@ -76,6 +76,7 @@ type codecWrapper struct {
version string version string
} }
// codecWrapper implements Decoder
var _ Decoder = &codecWrapper{} var _ Decoder = &codecWrapper{}
// Encode implements Codec // Encode implements Codec

View File

@ -30,7 +30,7 @@ import (
) )
type ConversionGenerator interface { type ConversionGenerator interface {
GenerateConversionsForType(version string, reflection reflect.Type) error GenerateConversionsForType(groupVersion unversioned.GroupVersion, reflection reflect.Type) error
WriteConversionFunctions(w io.Writer) error WriteConversionFunctions(w io.Writer) error
RegisterConversionFunctions(w io.Writer, pkg string) error RegisterConversionFunctions(w io.Writer, pkg string) error
AddImport(pkg string) string AddImport(pkg string) string
@ -87,12 +87,7 @@ func (g *conversionGenerator) AddImport(pkg string) string {
return g.addImportByPath(pkg) return g.addImportByPath(pkg)
} }
func (g *conversionGenerator) GenerateConversionsForType(gvString string, reflection reflect.Type) error { func (g *conversionGenerator) GenerateConversionsForType(gv unversioned.GroupVersion, reflection reflect.Type) error {
gv, err := unversioned.ParseGroupVersion(gvString)
if err != nil {
return err
}
kind := reflection.Name() kind := reflection.Name()
// TODO this is equivalent to what it did before, but it needs to be fixed for the proper group // 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] internalGV, exists := g.scheme.InternalVersions[gv.Group]

View File

@ -20,6 +20,7 @@ import (
"reflect" "reflect"
"testing" "testing"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
) )
@ -45,10 +46,14 @@ func (*InternalComplex) IsAnAPIObject() {}
func (*ExternalComplex) IsAnAPIObject() {} func (*ExternalComplex) IsAnAPIObject() {}
func TestStringMapConversion(t *testing.T) { func TestStringMapConversion(t *testing.T) {
internalGV := unversioned.GroupVersion{Group: "test.group", Version: ""}
externalGV := unversioned.GroupVersion{Group: "test.group", Version: "external"}
scheme := runtime.NewScheme() scheme := runtime.NewScheme()
scheme.Log(t) scheme.Log(t)
scheme.AddKnownTypeWithName("", "Complex", &InternalComplex{}) scheme.AddInternalGroupVersion(internalGV)
scheme.AddKnownTypeWithName("external", "Complex", &ExternalComplex{}) scheme.AddKnownTypeWithName(internalGV.WithKind("Complex"), &InternalComplex{})
scheme.AddKnownTypeWithName(externalGV.WithKind("Complex"), &ExternalComplex{})
testCases := map[string]struct { testCases := map[string]struct {
input map[string][]string input map[string][]string

View File

@ -63,14 +63,15 @@ func (*EmbeddedTestExternal) IsAnAPIObject() {}
func TestDecodeEmptyRawExtensionAsObject(t *testing.T) { func TestDecodeEmptyRawExtensionAsObject(t *testing.T) {
internalGV := unversioned.GroupVersion{Group: "test.group", Version: ""} 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 := runtime.NewScheme()
s.AddInternalGroupVersion(internalGV) s.AddInternalGroupVersion(internalGV)
s.AddKnownTypes(internalGV.String(), &ObjectTest{}) s.AddKnownTypes(internalGV, &ObjectTest{})
s.AddKnownTypeWithName(externalGVK.GroupVersion().String(), externalGVK.Kind, &ObjectTestExternal{}) 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 { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
@ -79,7 +80,7 @@ func TestDecodeEmptyRawExtensionAsObject(t *testing.T) {
t.Fatalf("unexpected object: %#v", test.Items[0]) 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 { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
@ -95,10 +96,10 @@ func TestArrayOfRuntimeObject(t *testing.T) {
s := runtime.NewScheme() s := runtime.NewScheme()
s.AddInternalGroupVersion(internalGV) s.AddInternalGroupVersion(internalGV)
s.AddKnownTypes(internalGV.String(), &EmbeddedTest{}) s.AddKnownTypes(internalGV, &EmbeddedTest{})
s.AddKnownTypeWithName(externalGV.String(), "EmbeddedTest", &EmbeddedTestExternal{}) s.AddKnownTypeWithName(externalGV.WithKind("EmbeddedTest"), &EmbeddedTestExternal{})
s.AddKnownTypes(internalGV.String(), &ObjectTest{}) s.AddKnownTypes(internalGV, &ObjectTest{})
s.AddKnownTypeWithName(externalGV.String(), "ObjectTest", &ObjectTestExternal{}) s.AddKnownTypeWithName(externalGV.WithKind("ObjectTest"), &ObjectTestExternal{})
internal := &ObjectTest{ internal := &ObjectTest{
Items: []runtime.Object{ Items: []runtime.Object{
@ -162,8 +163,8 @@ func TestEmbeddedObject(t *testing.T) {
s := runtime.NewScheme() s := runtime.NewScheme()
s.AddInternalGroupVersion(internalGV) s.AddInternalGroupVersion(internalGV)
s.AddKnownTypes(internalGV.String(), &EmbeddedTest{}) s.AddKnownTypes(internalGV, &EmbeddedTest{})
s.AddKnownTypeWithName(externalGV.String(), embeddedTestExternalGVK.Kind, &EmbeddedTestExternal{}) s.AddKnownTypeWithName(embeddedTestExternalGVK, &EmbeddedTestExternal{})
outer := &EmbeddedTest{ outer := &EmbeddedTest{
ID: "outer", ID: "outer",
@ -226,8 +227,8 @@ func TestDeepCopyOfEmbeddedObject(t *testing.T) {
s := runtime.NewScheme() s := runtime.NewScheme()
s.AddInternalGroupVersion(internalGV) s.AddInternalGroupVersion(internalGV)
s.AddKnownTypes(internalGV.String(), &EmbeddedTest{}) s.AddKnownTypes(internalGV, &EmbeddedTest{})
s.AddKnownTypeWithName(externalGV.String(), embeddedTestExternalGVK.Kind, &EmbeddedTestExternal{}) s.AddKnownTypeWithName(embeddedTestExternalGVK, &EmbeddedTestExternal{})
original := &EmbeddedTest{ original := &EmbeddedTest{
ID: "outer", ID: "outer",

View File

@ -259,31 +259,33 @@ func NewScheme(internalGroupVersions ...unversioned.GroupVersion) *Scheme {
return s 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) { func (s *Scheme) AddInternalGroupVersion(gv unversioned.GroupVersion) {
s.raw.InternalVersions[gv.Group] = gv s.raw.InternalVersions[gv.Group] = gv
} }
// AddKnownTypes registers the types of the arguments to the marshaller of the package api. // 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. // 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)) interfaces := make([]interface{}, len(types))
for i := range types { for i := range types {
interfaces[i] = types[i] 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 // 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 // be encoded as. Useful for testing when you don't want to make multiple packages to define
// your structs. // your structs.
func (s *Scheme) AddKnownTypeWithName(version, kind string, obj Object) { func (s *Scheme) AddKnownTypeWithName(gvk unversioned.GroupVersionKind, obj Object) {
s.raw.AddKnownTypeWithName(version, kind, obj) s.raw.AddKnownTypeWithName(gvk, obj)
} }
// KnownTypes returns the types known for the given version. // KnownTypes returns the types known for the given version.
// Return value must be treated as read-only. // Return value must be treated as read-only.
func (s *Scheme) KnownTypes(version string) map[string]reflect.Type { func (s *Scheme) KnownTypes(gv unversioned.GroupVersion) map[string]reflect.Type {
return s.raw.KnownTypes(version) return s.raw.KnownTypes(gv)
} }
// DataVersionAndKind will return the APIVersion and Kind of the given wire-format // 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) 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 { func (s *Scheme) DecodeIntoWithSpecifiedVersionKind(data []byte, obj Object, gvk unversioned.GroupVersionKind) error {
return s.raw.DecodeIntoWithSpecifiedVersionKind(data, obj, gvk) return s.raw.DecodeIntoWithSpecifiedVersionKind(data, obj, gvk)
} }

View File

@ -46,13 +46,11 @@ func (*ExternalSimple) IsAnAPIObject() {}
func TestScheme(t *testing.T) { func TestScheme(t *testing.T) {
internalGV := unversioned.GroupVersion{Group: "test.group", Version: ""} internalGV := unversioned.GroupVersion{Group: "test.group", Version: ""}
externalGV := unversioned.GroupVersion{Group: "test.group", Version: "testExternal"} externalGV := unversioned.GroupVersion{Group: "test.group", Version: "testExternal"}
internalGVK := internalGV.WithKind("Simple")
externalGVK := externalGV.WithKind("Simple")
scheme := runtime.NewScheme() scheme := runtime.NewScheme()
scheme.AddInternalGroupVersion(internalGV) scheme.AddInternalGroupVersion(internalGV)
scheme.AddKnownTypeWithName(internalGV.String(), internalGVK.Kind, &InternalSimple{}) scheme.AddKnownTypeWithName(internalGV.WithKind("Simple"), &InternalSimple{})
scheme.AddKnownTypeWithName(externalGV.String(), externalGVK.Kind, &ExternalSimple{}) scheme.AddKnownTypeWithName(externalGV.WithKind("Simple"), &ExternalSimple{})
// test that scheme is an ObjectTyper // test that scheme is an ObjectTyper
var _ runtime.ObjectTyper = scheme var _ runtime.ObjectTyper = scheme
@ -138,8 +136,10 @@ func TestScheme(t *testing.T) {
} }
func TestInvalidObjectValueKind(t *testing.T) { func TestInvalidObjectValueKind(t *testing.T) {
internalGV := unversioned.GroupVersion{Group: "", Version: ""}
scheme := runtime.NewScheme() scheme := runtime.NewScheme()
scheme.AddKnownTypeWithName("", "Simple", &InternalSimple{}) scheme.AddKnownTypeWithName(internalGV.WithKind("Simple"), &InternalSimple{})
embedded := &runtime.EmbeddedObject{} embedded := &runtime.EmbeddedObject{}
switch obj := embedded.Object.(type) { switch obj := embedded.Object.(type) {
@ -210,8 +210,8 @@ func TestExternalToInternalMapping(t *testing.T) {
scheme := runtime.NewScheme() scheme := runtime.NewScheme()
scheme.AddInternalGroupVersion(internalGV) scheme.AddInternalGroupVersion(internalGV)
scheme.AddKnownTypeWithName(internalGV.String(), "OptionalExtensionType", &InternalOptionalExtensionType{}) scheme.AddKnownTypeWithName(internalGV.WithKind("OptionalExtensionType"), &InternalOptionalExtensionType{})
scheme.AddKnownTypeWithName(externalGV.String(), "OptionalExtensionType", &ExternalOptionalExtensionType{}) scheme.AddKnownTypeWithName(externalGV.WithKind("OptionalExtensionType"), &ExternalOptionalExtensionType{})
table := []struct { table := []struct {
obj runtime.Object obj runtime.Object
@ -246,14 +246,14 @@ func TestExtensionMapping(t *testing.T) {
scheme := runtime.NewScheme() scheme := runtime.NewScheme()
scheme.AddInternalGroupVersion(internalGV) scheme.AddInternalGroupVersion(internalGV)
scheme.AddKnownTypeWithName(internalGV.String(), "ExtensionType", &InternalExtensionType{}) scheme.AddKnownTypeWithName(internalGV.WithKind("ExtensionType"), &InternalExtensionType{})
scheme.AddKnownTypeWithName(internalGV.String(), "OptionalExtensionType", &InternalOptionalExtensionType{}) scheme.AddKnownTypeWithName(internalGV.WithKind("OptionalExtensionType"), &InternalOptionalExtensionType{})
scheme.AddKnownTypeWithName(internalGV.String(), "A", &ExtensionA{}) scheme.AddKnownTypeWithName(internalGV.WithKind("A"), &ExtensionA{})
scheme.AddKnownTypeWithName(internalGV.String(), "B", &ExtensionB{}) scheme.AddKnownTypeWithName(internalGV.WithKind("B"), &ExtensionB{})
scheme.AddKnownTypeWithName(externalGV.String(), "ExtensionType", &ExternalExtensionType{}) scheme.AddKnownTypeWithName(externalGV.WithKind("ExtensionType"), &ExternalExtensionType{})
scheme.AddKnownTypeWithName(externalGV.String(), "OptionalExtensionType", &ExternalOptionalExtensionType{}) scheme.AddKnownTypeWithName(externalGV.WithKind("OptionalExtensionType"), &ExternalOptionalExtensionType{})
scheme.AddKnownTypeWithName(externalGV.String(), "A", &ExtensionA{}) scheme.AddKnownTypeWithName(externalGV.WithKind("A"), &ExtensionA{})
scheme.AddKnownTypeWithName(externalGV.String(), "B", &ExtensionB{}) scheme.AddKnownTypeWithName(externalGV.WithKind("B"), &ExtensionB{})
table := []struct { table := []struct {
obj runtime.Object obj runtime.Object
@ -304,8 +304,8 @@ func TestEncode(t *testing.T) {
scheme := runtime.NewScheme() scheme := runtime.NewScheme()
scheme.AddInternalGroupVersion(internalGV) scheme.AddInternalGroupVersion(internalGV)
scheme.AddKnownTypeWithName(internalGV.String(), "Simple", &InternalSimple{}) scheme.AddKnownTypeWithName(internalGV.WithKind("Simple"), &InternalSimple{})
scheme.AddKnownTypeWithName(externalGV.String(), "Simple", &ExternalSimple{}) scheme.AddKnownTypeWithName(externalGV.WithKind("Simple"), &ExternalSimple{})
codec := runtime.CodecFor(scheme, externalGV.String()) codec := runtime.CodecFor(scheme, externalGV.String())
test := &InternalSimple{ test := &InternalSimple{
TestString: "I'm the same", TestString: "I'm the same",

View File

@ -47,8 +47,8 @@ var codec runtime.Codec
func init() { func init() {
scheme = runtime.NewScheme() scheme = runtime.NewScheme()
scheme.AddKnownTypes("", &storagetesting.TestResource{}) scheme.AddKnownTypes(testapi.Default.InternalGroupVersion(), &storagetesting.TestResource{})
scheme.AddKnownTypes(testapi.Default.Version(), &storagetesting.TestResource{}) scheme.AddKnownTypes(*testapi.Default.GroupVersion(), &storagetesting.TestResource{})
codec = runtime.CodecFor(scheme, testapi.Default.Version()) codec = runtime.CodecFor(scheme, testapi.Default.Version())
scheme.AddConversionFuncs( scheme.AddConversionFuncs(
func(in *storagetesting.TestResource, out *storagetesting.TestResource, s conversion.Scope) error { func(in *storagetesting.TestResource, out *storagetesting.TestResource, s conversion.Scope) error {

View File

@ -17,14 +17,19 @@ limitations under the License.
package api package api
import ( import (
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
) )
// Scheme is the default instance of runtime.Scheme to which types in the Kubernetes API are already registered. // Scheme is the default instance of runtime.Scheme to which types in the Kubernetes API are already registered.
var Scheme = runtime.NewScheme() 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() { func init() {
Scheme.AddKnownTypes("", Scheme.AddKnownTypes(SchemeGroupVersion,
&Policy{}, &Policy{},
) )
} }

View File

@ -17,15 +17,20 @@ limitations under the License.
package v1 package v1
import ( import (
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/plugin/pkg/scheduler/api" "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 // 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() { func init() {
api.Scheme.AddKnownTypes("v1", api.Scheme.AddKnownTypes(SchemeGroupVersion,
&Policy{}, &Policy{},
) )
} }