Merge pull request #17515 from deads2k/gv-scheme
Auto commit by PR queue bot
This commit is contained in:
@@ -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,25 +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)
|
||||
}
|
||||
|
||||
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(*groupVersion) {
|
||||
generator.OverwritePackage(gv.Version, "")
|
||||
for _, knownType := range api.Scheme.KnownTypes(gv) {
|
||||
if knownType.PkgPath() != versionPath {
|
||||
continue
|
||||
}
|
||||
if err := generator.GenerateConversionsForType(version, knownType); err != nil {
|
||||
if err := generator.GenerateConversionsForType(gv, knownType); err != nil {
|
||||
glog.Errorf("Error while generating conversion functions for %v: %v", knownType, err)
|
||||
}
|
||||
}
|
||||
|
@@ -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"))
|
||||
|
||||
@@ -125,14 +126,8 @@ func main() {
|
||||
generator.OverwritePackage(vals[0], vals[1])
|
||||
}
|
||||
}
|
||||
var schemeVersion string
|
||||
if version == "" {
|
||||
// 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
|
||||
}
|
||||
|
@@ -41,7 +41,7 @@ func BenchmarkPodConversion(b *testing.B) {
|
||||
if err != nil {
|
||||
b.Fatalf("Conversion error: %v", err)
|
||||
}
|
||||
obj, err := scheme.ConvertToVersion(versionedObj, scheme.InternalVersion)
|
||||
obj, err := scheme.ConvertToVersion(versionedObj, scheme.InternalVersions[testapi.Default.Group].String())
|
||||
if err != nil {
|
||||
b.Fatalf("Conversion error: %v", err)
|
||||
}
|
||||
@@ -69,7 +69,7 @@ func BenchmarkNodeConversion(b *testing.B) {
|
||||
if err != nil {
|
||||
b.Fatalf("Conversion error: %v", err)
|
||||
}
|
||||
obj, err := scheme.ConvertToVersion(versionedObj, scheme.InternalVersion)
|
||||
obj, err := scheme.ConvertToVersion(versionedObj, scheme.InternalVersions[testapi.Default.Group].String())
|
||||
if err != nil {
|
||||
b.Fatalf("Conversion error: %v", err)
|
||||
}
|
||||
@@ -97,7 +97,7 @@ func BenchmarkReplicationControllerConversion(b *testing.B) {
|
||||
if err != nil {
|
||||
b.Fatalf("Conversion error: %v", err)
|
||||
}
|
||||
obj, err := scheme.ConvertToVersion(versionedObj, scheme.InternalVersion)
|
||||
obj, err := scheme.ConvertToVersion(versionedObj, scheme.InternalVersions[testapi.Default.Group].String())
|
||||
if err != nil {
|
||||
b.Fatalf("Conversion error: %v", err)
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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.
|
||||
|
@@ -189,9 +189,21 @@ func (m *DefaultRESTMapper) GroupForResource(resource string) (string, error) {
|
||||
// them with group/version tuples.
|
||||
// TODO this should probably become RESTMapping(GroupKind, versions ...string)
|
||||
func (m *DefaultRESTMapper) RESTMapping(kind string, versions ...string) (*RESTMapping, error) {
|
||||
// TODO, this looks really strange, but once this API is update, the version detection becomes clean again
|
||||
// because you won't be able to request cross-group kinds
|
||||
hadVersion := false
|
||||
for _, gvString := range versions {
|
||||
currGroupVersion, err := unversioned.ParseGroupVersion(gvString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(currGroupVersion.Version) != 0 {
|
||||
hadVersion = true
|
||||
}
|
||||
}
|
||||
|
||||
// Pick an appropriate version
|
||||
var groupVersion *unversioned.GroupVersion
|
||||
hadVersion := false
|
||||
for _, v := range versions {
|
||||
if len(v) == 0 {
|
||||
continue
|
||||
@@ -202,7 +214,6 @@ func (m *DefaultRESTMapper) RESTMapping(kind string, versions ...string) (*RESTM
|
||||
}
|
||||
|
||||
currGVK := currGroupVersion.WithKind(kind)
|
||||
hadVersion = true
|
||||
if _, ok := m.kindToPluralResource[currGVK]; ok {
|
||||
groupVersion = &currGroupVersion
|
||||
break
|
||||
|
@@ -28,6 +28,8 @@ import (
|
||||
|
||||
type fakeCodec struct{}
|
||||
|
||||
var _ runtime.Decoder = fakeCodec{}
|
||||
|
||||
func (fakeCodec) Encode(runtime.Object) ([]byte, error) {
|
||||
return []byte{}, nil
|
||||
}
|
||||
@@ -40,7 +42,7 @@ func (fakeCodec) Decode([]byte) (runtime.Object, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (fakeCodec) DecodeToVersion([]byte, string) (runtime.Object, error) {
|
||||
func (fakeCodec) DecodeToVersion([]byte, unversioned.GroupVersion) (runtime.Object, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -48,7 +50,7 @@ func (fakeCodec) DecodeInto([]byte, runtime.Object) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fakeCodec) DecodeIntoWithSpecifiedVersionKind([]byte, runtime.Object, string, string) error {
|
||||
func (fakeCodec) DecodeIntoWithSpecifiedVersionKind([]byte, runtime.Object, unversioned.GroupVersionKind) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@@ -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() {}
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -49,9 +49,19 @@ 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
|
||||
}
|
||||
|
||||
// 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 the legacy kube types
|
||||
if gv.IsEmpty() {
|
||||
return ""
|
||||
}
|
||||
|
||||
// special case of "v1" for backward compatibility
|
||||
if gv.Group == "" && gv.Version == "v1" {
|
||||
return gv.Version
|
||||
@@ -63,6 +73,12 @@ 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 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
|
||||
}
|
||||
|
||||
s := strings.Split(gv, "/")
|
||||
// "v1" is the only special case. Otherwise GroupVersion is expected to contain
|
||||
// one "/" dividing the string into two parts.
|
||||
@@ -85,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}
|
||||
}
|
||||
|
@@ -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() {}
|
||||
|
@@ -18,14 +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() {
|
||||
api.Scheme.AddKnownTypes("",
|
||||
// TODO this will get cleaned up with the scheme types are fixed
|
||||
api.Scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&KubeProxyConfiguration{},
|
||||
)
|
||||
}
|
||||
|
@@ -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{},
|
||||
)
|
||||
}
|
||||
|
@@ -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()
|
||||
@@ -27,7 +31,8 @@ func init() {
|
||||
|
||||
// Adds the list of known types to api.Scheme.
|
||||
func addKnownTypes() {
|
||||
api.Scheme.AddKnownTypes("",
|
||||
// TODO this gets cleaned up when the types are fixed
|
||||
api.Scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&ClusterAutoscaler{},
|
||||
&ClusterAutoscalerList{},
|
||||
&Deployment{},
|
||||
|
@@ -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{},
|
||||
|
@@ -18,6 +18,7 @@ package metrics
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -25,9 +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() {
|
||||
api.Scheme.AddKnownTypes("",
|
||||
// TODO this will get cleaned up with the scheme types are fixed
|
||||
api.Scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&RawNode{},
|
||||
&RawPod{},
|
||||
)
|
||||
|
@@ -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{},
|
||||
)
|
||||
|
@@ -375,11 +375,14 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||
// test/integration/auth_test.go is currently the most comprehensive status code test
|
||||
|
||||
reqScope := RequestScope{
|
||||
ContextFunc: ctxFn,
|
||||
Creater: a.group.Creater,
|
||||
Convertor: a.group.Convertor,
|
||||
Codec: mapping.Codec,
|
||||
APIVersion: a.group.GroupVersion.String(),
|
||||
ContextFunc: ctxFn,
|
||||
Creater: a.group.Creater,
|
||||
Convertor: a.group.Convertor,
|
||||
Codec: mapping.Codec,
|
||||
APIVersion: a.group.GroupVersion.String(),
|
||||
// TODO, this internal version needs to plumbed through from the caller
|
||||
// this works in all the cases we have now
|
||||
InternalVersion: unversioned.GroupVersion{Group: a.group.GroupVersion.Group},
|
||||
ServerAPIVersion: serverGroupVersion.String(),
|
||||
Resource: resource,
|
||||
Subresource: subresource,
|
||||
|
@@ -58,6 +58,7 @@ func convert(obj runtime.Object) (runtime.Object, error) {
|
||||
|
||||
// This creates fake API versions, similar to api/latest.go.
|
||||
var testAPIGroup = "test.group"
|
||||
var testInternalGroupVersion = unversioned.GroupVersion{Group: testAPIGroup, Version: ""}
|
||||
var testGroupVersion = unversioned.GroupVersion{Group: testAPIGroup, Version: "version"}
|
||||
var newGroupVersion = unversioned.GroupVersion{Group: testAPIGroup, Version: "version2"}
|
||||
var prefix = "apis"
|
||||
@@ -112,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{})
|
||||
}
|
||||
|
||||
@@ -136,8 +137,9 @@ func init() {
|
||||
|
||||
// "internal" version
|
||||
api.Scheme.AddKnownTypes(
|
||||
"", &apiservertesting.Simple{}, &apiservertesting.SimpleList{}, &unversioned.Status{},
|
||||
testInternalGroupVersion, &apiservertesting.Simple{}, &apiservertesting.SimpleList{}, &unversioned.Status{},
|
||||
&unversioned.ListOptions{}, &apiservertesting.SimpleGetOptions{}, &apiservertesting.SimpleRoot{})
|
||||
api.Scheme.AddInternalGroupVersion(testInternalGroupVersion)
|
||||
addGrouplessTypes()
|
||||
addTestTypes()
|
||||
addNewTestTypes()
|
||||
@@ -147,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)
|
||||
@@ -1630,7 +1631,7 @@ func TestConnectWithOptions(t *testing.T) {
|
||||
}
|
||||
opts, ok := connectStorage.receivedConnectOptions.(*apiservertesting.SimpleGetOptions)
|
||||
if !ok {
|
||||
t.Errorf("Unexpected options type: %#v", connectStorage.receivedConnectOptions)
|
||||
t.Fatalf("Unexpected options type: %#v", connectStorage.receivedConnectOptions)
|
||||
}
|
||||
if opts.Param1 != "value1" && opts.Param2 != "value2" {
|
||||
t.Errorf("Unexpected options value: %#v", opts)
|
||||
@@ -1677,7 +1678,7 @@ func TestConnectWithOptionsAndPath(t *testing.T) {
|
||||
}
|
||||
opts, ok := connectStorage.receivedConnectOptions.(*apiservertesting.SimpleGetOptions)
|
||||
if !ok {
|
||||
t.Errorf("Unexpected options type: %#v", connectStorage.receivedConnectOptions)
|
||||
t.Fatalf("Unexpected options type: %#v", connectStorage.receivedConnectOptions)
|
||||
}
|
||||
if opts.Param1 != "value1" && opts.Param2 != "value2" {
|
||||
t.Errorf("Unexpected options value: %#v", opts)
|
||||
|
@@ -73,10 +73,11 @@ type RequestScope struct {
|
||||
Creater runtime.ObjectCreater
|
||||
Convertor runtime.ObjectConvertor
|
||||
|
||||
Resource string
|
||||
Subresource string
|
||||
Kind string
|
||||
APIVersion string
|
||||
Resource string
|
||||
Subresource string
|
||||
Kind string
|
||||
APIVersion string
|
||||
InternalVersion unversioned.GroupVersion
|
||||
|
||||
// The version of apiserver resources to use
|
||||
ServerAPIVersion string
|
||||
@@ -148,15 +149,31 @@ func getRequestOptions(req *restful.Request, scope RequestScope, kind string, su
|
||||
newQuery[subpathKey] = []string{req.PathParameter("path")}
|
||||
query = newQuery
|
||||
}
|
||||
versioned, err := scope.Creater.New(scope.ServerAPIVersion, kind)
|
||||
|
||||
// TODO Options a mess. Basically the intent is:
|
||||
// 1. try to decode using the expected external GroupVersion
|
||||
// 2. if that fails, fall back to the old external serialization being used before, which was
|
||||
// "v1" and decode into the unversioned/legacykube group
|
||||
gvString := scope.APIVersion
|
||||
internalGVString := scope.InternalVersion.String()
|
||||
|
||||
versioned, err := scope.Creater.New(gvString, kind)
|
||||
if err != nil {
|
||||
// programmer error
|
||||
return nil, err
|
||||
gvString = "v1"
|
||||
internalGVString = ""
|
||||
|
||||
var secondErr error
|
||||
versioned, secondErr = scope.Creater.New(gvString, kind)
|
||||
// if we have an error, return the original failure
|
||||
if secondErr != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err := scope.Codec.DecodeParametersInto(query, versioned); err != nil {
|
||||
return nil, errors.NewBadRequest(err.Error())
|
||||
}
|
||||
out, err := scope.Convertor.ConvertToVersion(versioned, "")
|
||||
out, err := scope.Convertor.ConvertToVersion(versioned, internalGVString)
|
||||
if err != nil {
|
||||
// programmer error
|
||||
return nil, err
|
||||
@@ -343,7 +360,8 @@ func createHandler(r rest.NamedCreater, scope RequestScope, typer runtime.Object
|
||||
}
|
||||
|
||||
obj := r.New()
|
||||
if err := scope.Codec.DecodeIntoWithSpecifiedVersionKind(body, obj, scope.APIVersion, scope.Kind); err != nil {
|
||||
// TODO this cleans up with proper typing
|
||||
if err := scope.Codec.DecodeIntoWithSpecifiedVersionKind(body, obj, unversioned.ParseGroupVersionOrDie(scope.APIVersion).WithKind(scope.Kind)); err != nil {
|
||||
err = transformDecodeError(typer, err, obj, body)
|
||||
errorJSON(err, scope.Codec, w)
|
||||
return
|
||||
@@ -576,7 +594,7 @@ func UpdateResource(r rest.Updater, scope RequestScope, typer runtime.ObjectType
|
||||
}
|
||||
|
||||
obj := r.New()
|
||||
if err := scope.Codec.DecodeIntoWithSpecifiedVersionKind(body, obj, scope.APIVersion, scope.Kind); err != nil {
|
||||
if err := scope.Codec.DecodeIntoWithSpecifiedVersionKind(body, obj, unversioned.ParseGroupVersionOrDie(scope.APIVersion).WithKind(scope.Kind)); err != nil {
|
||||
err = transformDecodeError(typer, err, obj, body)
|
||||
errorJSON(err, scope.Codec, w)
|
||||
return
|
||||
|
@@ -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{},
|
||||
)
|
||||
}
|
||||
|
@@ -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{},
|
||||
)
|
||||
}
|
||||
|
@@ -38,7 +38,7 @@ import (
|
||||
type ObjectRetriever interface {
|
||||
// Kind should return a resource or a list of resources (depending on the provided kind and
|
||||
// name). It should return an error if the caller should communicate an error to the server.
|
||||
Kind(kind, name string) (runtime.Object, error)
|
||||
Kind(gvk unversioned.GroupVersionKind, name string) (runtime.Object, error)
|
||||
// Add adds a runtime object for test purposes into this object.
|
||||
Add(runtime.Object) error
|
||||
}
|
||||
@@ -59,23 +59,29 @@ type ObjectScheme interface {
|
||||
func ObjectReaction(o ObjectRetriever, mapper meta.RESTMapper) ReactionFunc {
|
||||
|
||||
return func(action Action) (bool, runtime.Object, error) {
|
||||
_, kind, err := mapper.VersionAndKindForResource(action.GetResource())
|
||||
gvString, kind, err := mapper.VersionAndKindForResource(action.GetResource())
|
||||
if err != nil {
|
||||
return false, nil, fmt.Errorf("unrecognized action %s: %v", action.GetResource(), err)
|
||||
}
|
||||
gv, err := unversioned.ParseGroupVersion(gvString)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
gvk := gv.WithKind(kind)
|
||||
|
||||
// TODO: have mapper return a Kind for a subresource?
|
||||
switch castAction := action.(type) {
|
||||
case ListAction:
|
||||
resource, err := o.Kind(kind+"List", "")
|
||||
gvk.Kind += "List"
|
||||
resource, err := o.Kind(gvk, "")
|
||||
return true, resource, err
|
||||
|
||||
case GetAction:
|
||||
resource, err := o.Kind(kind, castAction.GetName())
|
||||
resource, err := o.Kind(gvk, castAction.GetName())
|
||||
return true, resource, err
|
||||
|
||||
case DeleteAction:
|
||||
resource, err := o.Kind(kind, castAction.GetName())
|
||||
resource, err := o.Kind(gvk, castAction.GetName())
|
||||
return true, resource, err
|
||||
|
||||
case CreateAction:
|
||||
@@ -83,7 +89,7 @@ func ObjectReaction(o ObjectRetriever, mapper meta.RESTMapper) ReactionFunc {
|
||||
if err != nil {
|
||||
return true, nil, err
|
||||
}
|
||||
resource, err := o.Kind(kind, meta.Name)
|
||||
resource, err := o.Kind(gvk, meta.Name)
|
||||
return true, resource, err
|
||||
|
||||
case UpdateAction:
|
||||
@@ -91,7 +97,7 @@ func ObjectReaction(o ObjectRetriever, mapper meta.RESTMapper) ReactionFunc {
|
||||
if err != nil {
|
||||
return true, nil, err
|
||||
}
|
||||
resource, err := o.Kind(kind, meta.Name)
|
||||
resource, err := o.Kind(gvk, meta.Name)
|
||||
return true, resource, err
|
||||
|
||||
default:
|
||||
@@ -151,19 +157,24 @@ func NewObjects(scheme ObjectScheme, decoder runtime.ObjectDecoder) ObjectRetrie
|
||||
}
|
||||
}
|
||||
|
||||
func (o objects) Kind(kind, name string) (runtime.Object, error) {
|
||||
empty, _ := o.scheme.New("", kind)
|
||||
func (o objects) Kind(gvk unversioned.GroupVersionKind, name string) (runtime.Object, error) {
|
||||
// TODO our test clients deal in internal versions. We need to plumb that knowledge down here
|
||||
// we might do this via an extra function to the scheme to allow getting internal group versions
|
||||
// I'm punting for now
|
||||
gvk.Version = ""
|
||||
|
||||
empty, _ := o.scheme.New(gvk.GroupVersion().String(), gvk.Kind)
|
||||
nilValue := reflect.Zero(reflect.TypeOf(empty)).Interface().(runtime.Object)
|
||||
|
||||
arr, ok := o.types[kind]
|
||||
arr, ok := o.types[gvk.Kind]
|
||||
if !ok {
|
||||
if strings.HasSuffix(kind, "List") {
|
||||
itemKind := kind[:len(kind)-4]
|
||||
if strings.HasSuffix(gvk.Kind, "List") {
|
||||
itemKind := gvk.Kind[:len(gvk.Kind)-4]
|
||||
arr, ok := o.types[itemKind]
|
||||
if !ok {
|
||||
return empty, nil
|
||||
}
|
||||
out, err := o.scheme.New("", kind)
|
||||
out, err := o.scheme.New(gvk.GroupVersion().String(), gvk.Kind)
|
||||
if err != nil {
|
||||
return nilValue, err
|
||||
}
|
||||
@@ -175,25 +186,25 @@ func (o objects) Kind(kind, name string) (runtime.Object, error) {
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
return nilValue, errors.NewNotFound(kind, name)
|
||||
return nilValue, errors.NewNotFound(gvk.Kind, name)
|
||||
}
|
||||
|
||||
index := o.last[kind]
|
||||
index := o.last[gvk.Kind]
|
||||
if index >= len(arr) {
|
||||
index = len(arr) - 1
|
||||
}
|
||||
if index < 0 {
|
||||
return nilValue, errors.NewNotFound(kind, name)
|
||||
return nilValue, errors.NewNotFound(gvk.Kind, name)
|
||||
}
|
||||
out, err := o.scheme.Copy(arr[index])
|
||||
if err != nil {
|
||||
return nilValue, err
|
||||
}
|
||||
o.last[kind] = index + 1
|
||||
o.last[gvk.Kind] = index + 1
|
||||
|
||||
if status, ok := out.(*unversioned.Status); ok {
|
||||
if status.Details != nil {
|
||||
status.Details.Kind = kind
|
||||
status.Details.Kind = gvk.Kind
|
||||
}
|
||||
if status.Status != unversioned.StatusSuccess {
|
||||
return nilValue, &errors.StatusError{ErrStatus: *status}
|
||||
|
@@ -22,20 +22,33 @@ import (
|
||||
"net/url"
|
||||
|
||||
"github.com/ugorji/go/codec"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
)
|
||||
|
||||
func (s *Scheme) DecodeToVersionedObject(data []byte) (obj interface{}, version, kind string, err error) {
|
||||
version, kind, err = s.DataVersionAndKind(data)
|
||||
func (s *Scheme) DecodeToVersionedObject(data []byte) (interface{}, string, string, error) {
|
||||
version, kind, err := s.DataVersionAndKind(data)
|
||||
if err != nil {
|
||||
return
|
||||
return nil, "", "", err
|
||||
}
|
||||
if version == "" && s.InternalVersion != "" {
|
||||
|
||||
gv, err := unversioned.ParseGroupVersion(version)
|
||||
if err != nil {
|
||||
return nil, "", "", err
|
||||
}
|
||||
|
||||
internalGV, exists := s.InternalVersions[gv.Group]
|
||||
if !exists {
|
||||
return nil, "", "", fmt.Errorf("no internalVersion specified for %v", gv)
|
||||
}
|
||||
|
||||
if len(gv.Version) == 0 && len(internalGV.Version) != 0 {
|
||||
return nil, "", "", fmt.Errorf("version not set in '%s'", string(data))
|
||||
}
|
||||
if kind == "" {
|
||||
return nil, "", "", fmt.Errorf("kind not set in '%s'", string(data))
|
||||
}
|
||||
obj, err = s.NewObject(version, kind)
|
||||
obj, err := s.NewObject(version, kind)
|
||||
if err != nil {
|
||||
return nil, "", "", err
|
||||
}
|
||||
@@ -43,7 +56,7 @@ func (s *Scheme) DecodeToVersionedObject(data []byte) (obj interface{}, version,
|
||||
if err := codec.NewDecoderBytes(data, new(codec.JsonHandle)).Decode(obj); err != nil {
|
||||
return nil, "", "", err
|
||||
}
|
||||
return
|
||||
return obj, version, kind, nil
|
||||
}
|
||||
|
||||
// Decode converts a JSON string back into a pointer to an api object.
|
||||
@@ -52,7 +65,7 @@ func (s *Scheme) DecodeToVersionedObject(data []byte) (obj interface{}, version,
|
||||
// s.InternalVersion type before being returned. Decode will not decode
|
||||
// objects without version set unless InternalVersion is also "".
|
||||
func (s *Scheme) Decode(data []byte) (interface{}, error) {
|
||||
return s.DecodeToVersion(data, s.InternalVersion)
|
||||
return s.DecodeToVersion(data, unversioned.GroupVersion{})
|
||||
}
|
||||
|
||||
// DecodeToVersion converts a JSON string back into a pointer to an api object.
|
||||
@@ -60,7 +73,9 @@ func (s *Scheme) Decode(data []byte) (interface{}, error) {
|
||||
// technique. The object will be converted, if necessary, into the versioned
|
||||
// type before being returned. Decode will not decode objects without version
|
||||
// set unless version is also "".
|
||||
func (s *Scheme) DecodeToVersion(data []byte, version string) (interface{}, error) {
|
||||
// a GroupVersion with .IsEmpty() == true is means "use the internal version for
|
||||
// the object's group"
|
||||
func (s *Scheme) DecodeToVersion(data []byte, gv unversioned.GroupVersion) (interface{}, error) {
|
||||
obj, sourceVersion, kind, err := s.DecodeToVersionedObject(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -70,13 +85,28 @@ func (s *Scheme) DecodeToVersion(data []byte, version string) (interface{}, erro
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sourceGV, err := unversioned.ParseGroupVersion(sourceVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// if the gv is empty, then we want the internal version, but the internal version varies by
|
||||
// group. We can lookup the group now because we have knowledge of the group
|
||||
if gv.IsEmpty() {
|
||||
exists := false
|
||||
gv, exists = s.InternalVersions[sourceGV.Group]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("no internalVersion specified for %v", gv)
|
||||
}
|
||||
}
|
||||
|
||||
// Convert if needed.
|
||||
if version != sourceVersion {
|
||||
objOut, err := s.NewObject(version, kind)
|
||||
if gv != sourceGV {
|
||||
objOut, err := s.NewObject(gv.String(), kind)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
flags, meta := s.generateConvertMeta(sourceVersion, version, obj)
|
||||
flags, meta := s.generateConvertMeta(sourceVersion, gv.String(), obj)
|
||||
if err := s.converter.Convert(obj, objOut, flags, meta); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -91,17 +121,17 @@ func (s *Scheme) DecodeToVersion(data []byte, version string) (interface{}, erro
|
||||
// If obj's version doesn't match that in data, an attempt will be made to convert
|
||||
// data into obj's version.
|
||||
func (s *Scheme) DecodeInto(data []byte, obj interface{}) error {
|
||||
return s.DecodeIntoWithSpecifiedVersionKind(data, obj, "", "")
|
||||
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{}, specifiedVersion, specifiedKind string) error {
|
||||
func (s *Scheme) DecodeIntoWithSpecifiedVersionKind(data []byte, obj interface{}, requestedGVK unversioned.GroupVersionKind) error {
|
||||
if len(data) == 0 {
|
||||
return errors.New("empty input")
|
||||
}
|
||||
@@ -110,16 +140,16 @@ func (s *Scheme) DecodeIntoWithSpecifiedVersionKind(data []byte, obj interface{}
|
||||
return err
|
||||
}
|
||||
if dataVersion == "" {
|
||||
dataVersion = specifiedVersion
|
||||
dataVersion = requestedGVK.GroupVersion().String()
|
||||
}
|
||||
if dataKind == "" {
|
||||
dataKind = specifiedKind
|
||||
dataKind = requestedGVK.Kind
|
||||
}
|
||||
if len(specifiedVersion) > 0 && (dataVersion != specifiedVersion) {
|
||||
return errors.New(fmt.Sprintf("The apiVersion in the data (%s) does not match the specified apiVersion(%s)", dataVersion, specifiedVersion))
|
||||
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(specifiedKind) > 0 && (dataKind != specifiedKind) {
|
||||
return errors.New(fmt.Sprintf("The kind in the data (%s) does not match the specified kind(%s)", dataKind, specifiedKind))
|
||||
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)
|
||||
|
@@ -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)
|
||||
}
|
||||
|
||||
|
@@ -19,25 +19,27 @@ package conversion
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
)
|
||||
|
||||
type notRegisteredErr struct {
|
||||
kind string
|
||||
version string
|
||||
t reflect.Type
|
||||
gvk unversioned.GroupVersionKind
|
||||
t reflect.Type
|
||||
}
|
||||
|
||||
func (k *notRegisteredErr) Error() string {
|
||||
if k.t != nil {
|
||||
return fmt.Sprintf("no kind is registered for the type %v", k.t)
|
||||
}
|
||||
if len(k.kind) == 0 {
|
||||
return fmt.Sprintf("no version %q has been registered", k.version)
|
||||
if len(k.gvk.Kind) == 0 {
|
||||
return fmt.Sprintf("no version %q has been registered", k.gvk.GroupVersion())
|
||||
}
|
||||
if len(k.version) == 0 {
|
||||
return fmt.Sprintf("no kind %q is registered for the default version", k.kind)
|
||||
if len(k.gvk.Version) == 0 {
|
||||
return fmt.Sprintf("no kind %q is registered for the default version of group %q", k.gvk.Kind, k.gvk.Group)
|
||||
}
|
||||
return fmt.Sprintf("no kind %q is registered for version %q", k.kind, k.version)
|
||||
|
||||
return fmt.Sprintf("no kind %q is registered for version %q", k.gvk.Kind, k.gvk.GroupVersion())
|
||||
}
|
||||
|
||||
// IsNotRegisteredError returns true if the error indicates the provided
|
||||
|
@@ -125,9 +125,13 @@ func TestMetaValues(t *testing.T) {
|
||||
Kind string `json:"kind,omitempty"`
|
||||
TestString string `json:"testString"`
|
||||
}
|
||||
internalGV := unversioned.GroupVersion{Group: "test.group", Version: ""}
|
||||
externalGV := unversioned.GroupVersion{Group: "test.group", Version: "externalVersion"}
|
||||
|
||||
s := NewScheme()
|
||||
s.AddKnownTypeWithName("", "Simple", &InternalSimple{})
|
||||
s.AddKnownTypeWithName("externalVersion", "Simple", &ExternalSimple{})
|
||||
s.InternalVersions[internalGV.Group] = internalGV
|
||||
s.AddKnownTypeWithName(internalGV.WithKind("Simple"), &InternalSimple{})
|
||||
s.AddKnownTypeWithName(externalGV.WithKind("Simple"), &ExternalSimple{})
|
||||
|
||||
internalToExternalCalls := 0
|
||||
externalToInternalCalls := 0
|
||||
@@ -136,10 +140,10 @@ func TestMetaValues(t *testing.T) {
|
||||
err := s.AddConversionFuncs(
|
||||
func(in *InternalSimple, out *ExternalSimple, scope Scope) error {
|
||||
t.Logf("internal -> external")
|
||||
if e, a := "", scope.Meta().SrcVersion; e != a {
|
||||
if e, a := internalGV.String(), scope.Meta().SrcVersion; e != a {
|
||||
t.Fatalf("Expected '%v', got '%v'", e, a)
|
||||
}
|
||||
if e, a := "externalVersion", scope.Meta().DestVersion; e != a {
|
||||
if e, a := externalGV.String(), scope.Meta().DestVersion; e != a {
|
||||
t.Fatalf("Expected '%v', got '%v'", e, a)
|
||||
}
|
||||
scope.Convert(&in.TestString, &out.TestString, 0)
|
||||
@@ -148,10 +152,10 @@ func TestMetaValues(t *testing.T) {
|
||||
},
|
||||
func(in *ExternalSimple, out *InternalSimple, scope Scope) error {
|
||||
t.Logf("external -> internal")
|
||||
if e, a := "externalVersion", scope.Meta().SrcVersion; e != a {
|
||||
if e, a := externalGV.String(), scope.Meta().SrcVersion; e != a {
|
||||
t.Errorf("Expected '%v', got '%v'", e, a)
|
||||
}
|
||||
if e, a := "", scope.Meta().DestVersion; e != a {
|
||||
if e, a := internalGV.String(), scope.Meta().DestVersion; e != a {
|
||||
t.Fatalf("Expected '%v', got '%v'", e, a)
|
||||
}
|
||||
scope.Convert(&in.TestString, &out.TestString, 0)
|
||||
@@ -169,7 +173,7 @@ func TestMetaValues(t *testing.T) {
|
||||
s.Log(t)
|
||||
|
||||
// Test Encode, Decode, and DecodeInto
|
||||
data, err := s.EncodeToVersion(simple, "externalVersion")
|
||||
data, err := s.EncodeToVersion(simple, externalGV.String())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
@@ -226,7 +230,6 @@ func TestMetaValuesUnregisteredConvert(t *testing.T) {
|
||||
TestString string `json:"testString"`
|
||||
}
|
||||
s := NewScheme()
|
||||
s.InternalVersion = ""
|
||||
// We deliberately don't register the types.
|
||||
|
||||
internalToExternalCalls := 0
|
||||
|
@@ -19,22 +19,19 @@ package conversion
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
)
|
||||
|
||||
// Scheme defines an entire encoding and decoding scheme.
|
||||
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.
|
||||
@@ -50,7 +47,9 @@ type Scheme struct {
|
||||
|
||||
// InternalVersion is the default internal version. It is recommended that
|
||||
// you use "" for the internal version.
|
||||
InternalVersion string
|
||||
// TODO logically the InternalVersion is different for every Group, so this structure
|
||||
// must be map
|
||||
InternalVersions map[string]unversioned.GroupVersion
|
||||
|
||||
// MetaInsertionFactory is used to create an object to store and retrieve
|
||||
// the version and kind information for all objects. The default uses the
|
||||
@@ -61,13 +60,18 @@ 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(),
|
||||
InternalVersion: "",
|
||||
MetaFactory: DefaultMetaFactory,
|
||||
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{
|
||||
"": {},
|
||||
"componentconfig": {Group: "componentconfig"},
|
||||
"extensions": {Group: "extensions"},
|
||||
"metrics": {Group: "metrics"},
|
||||
},
|
||||
MetaFactory: DefaultMetaFactory,
|
||||
}
|
||||
s.converter.nameFunc = s.nameFunc
|
||||
return s
|
||||
@@ -82,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 {
|
||||
@@ -115,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.")
|
||||
@@ -138,34 +140,41 @@ 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
|
||||
}
|
||||
|
||||
// NewObject returns a new object of the given version and name,
|
||||
// or an error if it hasn't been registered.
|
||||
func (s *Scheme) NewObject(versionName, kind string) (interface{}, error) {
|
||||
if types, ok := s.versionMap[versionName]; ok {
|
||||
if t, ok := types[kind]; ok {
|
||||
return reflect.New(t).Interface(), nil
|
||||
}
|
||||
return nil, ¬RegisteredErr{kind: kind, version: versionName}
|
||||
func (s *Scheme) NewObject(gvString, kind string) (interface{}, error) {
|
||||
gv, err := unversioned.ParseGroupVersion(gvString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, ¬RegisteredErr{kind: kind, version: versionName}
|
||||
gvk := gv.WithKind(kind)
|
||||
|
||||
if t, exists := s.gvkToType[gvk]; exists {
|
||||
return reflect.New(t).Interface(), nil
|
||||
}
|
||||
|
||||
return nil, ¬RegisteredErr{gvk: gvk}
|
||||
}
|
||||
|
||||
// AddConversionFuncs adds functions to the list of conversion functions. The given
|
||||
@@ -274,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
|
||||
@@ -331,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
|
||||
}
|
||||
@@ -352,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
|
||||
}
|
||||
|
||||
@@ -388,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
|
||||
}
|
||||
|
||||
|
@@ -23,6 +23,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/util"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
@@ -108,17 +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.InternalVersion = ""
|
||||
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)
|
||||
@@ -361,7 +367,7 @@ func TestBadJSONRejection(t *testing.T) {
|
||||
|
||||
func TestBadJSONRejectionForSetInternalVersion(t *testing.T) {
|
||||
s := GetTestScheme()
|
||||
s.InternalVersion = "v1"
|
||||
s.InternalVersions[""] = unversioned.GroupVersion{Version: "v1"}
|
||||
badJSONs := [][]byte{
|
||||
[]byte(`{"myKindKey":"TestType1"}`), // Missing version
|
||||
}
|
||||
|
@@ -84,10 +84,11 @@ var validVersionGV = unversioned.GroupVersion{Group: "apitest", Version: validVe
|
||||
|
||||
func newExternalScheme() (*runtime.Scheme, meta.RESTMapper, runtime.Codec) {
|
||||
scheme := runtime.NewScheme()
|
||||
scheme.AddKnownTypeWithName(internalGV.Version, "Type", &internalType{})
|
||||
scheme.AddKnownTypeWithName(unlikelyGV.String(), "Type", &externalType{})
|
||||
scheme.AddInternalGroupVersion(internalGV)
|
||||
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) {
|
||||
@@ -98,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
|
||||
|
@@ -51,21 +51,12 @@ type OutputVersionMapper struct {
|
||||
|
||||
// RESTMapping implements meta.RESTMapper by prepending the output version to the preferred version list.
|
||||
func (m OutputVersionMapper) RESTMapping(kind string, versions ...string) (*meta.RESTMapping, error) {
|
||||
preferred := []string{m.OutputVersion}
|
||||
for _, version := range versions {
|
||||
if len(version) > 0 {
|
||||
preferred = append(preferred, version)
|
||||
}
|
||||
mapping, err := m.RESTMapper.RESTMapping(kind, m.OutputVersion)
|
||||
if err == nil {
|
||||
return mapping, nil
|
||||
}
|
||||
// if the caller wants to use the default version list, try with the preferred version, and on
|
||||
// error, use the default behavior.
|
||||
if len(preferred) == 1 {
|
||||
if m, err := m.RESTMapper.RESTMapping(kind, preferred...); err == nil {
|
||||
return m, nil
|
||||
}
|
||||
preferred = nil
|
||||
}
|
||||
return m.RESTMapper.RESTMapping(kind, preferred...)
|
||||
|
||||
return m.RESTMapper.RESTMapping(kind, versions...)
|
||||
}
|
||||
|
||||
// ShortcutExpander is a RESTMapper that can be used for Kubernetes
|
||||
|
@@ -217,7 +217,7 @@ func (p *NamePrinter) PrintObj(obj runtime.Object, w io.Writer) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
decodedObj, err := scheme.DecodeToVersion(rawObj, "")
|
||||
decodedObj, err := scheme.DecodeToVersion(rawObj, unversioned.GroupVersion{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@@ -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{
|
||||
|
@@ -154,7 +154,7 @@ func (t *thirdPartyResourceDataCodec) Decode(data []byte) (runtime.Object, error
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (t *thirdPartyResourceDataCodec) DecodeToVersion(data []byte, version string) (runtime.Object, error) {
|
||||
func (t *thirdPartyResourceDataCodec) DecodeToVersion(data []byte, gv unversioned.GroupVersion) (runtime.Object, error) {
|
||||
// TODO: this is hacky, there must be a better way...
|
||||
obj, err := t.Decode(data)
|
||||
if err != nil {
|
||||
@@ -164,7 +164,7 @@ func (t *thirdPartyResourceDataCodec) DecodeToVersion(data []byte, version strin
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return t.delegate.DecodeToVersion(objData, version)
|
||||
return t.delegate.DecodeToVersion(objData, gv)
|
||||
}
|
||||
|
||||
func (t *thirdPartyResourceDataCodec) DecodeInto(data []byte, obj runtime.Object) error {
|
||||
@@ -175,14 +175,14 @@ func (t *thirdPartyResourceDataCodec) DecodeInto(data []byte, obj runtime.Object
|
||||
return t.populate(thirdParty, data)
|
||||
}
|
||||
|
||||
func (t *thirdPartyResourceDataCodec) DecodeIntoWithSpecifiedVersionKind(data []byte, obj runtime.Object, version, kind string) error {
|
||||
func (t *thirdPartyResourceDataCodec) DecodeIntoWithSpecifiedVersionKind(data []byte, obj runtime.Object, gvk unversioned.GroupVersionKind) error {
|
||||
thirdParty, ok := obj.(*extensions.ThirdPartyResourceData)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected object: %#v", obj)
|
||||
}
|
||||
|
||||
if kind != "ThirdPartyResourceData" {
|
||||
return fmt.Errorf("unexpeceted kind: %s", kind)
|
||||
if gvk.Kind != "ThirdPartyResourceData" {
|
||||
return fmt.Errorf("unexpeceted kind: %s", gvk.Kind)
|
||||
}
|
||||
|
||||
var dataObj interface{}
|
||||
@@ -194,25 +194,25 @@ func (t *thirdPartyResourceDataCodec) DecodeIntoWithSpecifiedVersionKind(data []
|
||||
return fmt.Errorf("unexpcted object: %#v", dataObj)
|
||||
}
|
||||
if kindObj, found := mapObj["kind"]; !found {
|
||||
mapObj["kind"] = kind
|
||||
mapObj["kind"] = gvk.Kind
|
||||
} else {
|
||||
kindStr, ok := kindObj.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected object for 'kind': %v", kindObj)
|
||||
}
|
||||
if kindStr != t.kind {
|
||||
return fmt.Errorf("kind doesn't match, expecting: %s, got %s", kind, kindStr)
|
||||
return fmt.Errorf("kind doesn't match, expecting: %s, got %s", gvk.Kind, kindStr)
|
||||
}
|
||||
}
|
||||
if versionObj, found := mapObj["apiVersion"]; !found {
|
||||
mapObj["apiVersion"] = version
|
||||
mapObj["apiVersion"] = gvk.GroupVersion().String()
|
||||
} else {
|
||||
versionStr, ok := versionObj.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected object for 'apiVersion': %v", versionObj)
|
||||
}
|
||||
if versionStr != version {
|
||||
return fmt.Errorf("version doesn't match, expecting: %s, got %s", version, versionStr)
|
||||
if versionStr != gvk.GroupVersion().String() {
|
||||
return fmt.Errorf("version doesn't match, expecting: %v, got %s", gvk.GroupVersion(), versionStr)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -35,6 +35,7 @@ type yamlCodec struct {
|
||||
|
||||
// yamlCodec implements Codec
|
||||
var _ Codec = yamlCodec{}
|
||||
var _ Decoder = yamlCodec{}
|
||||
|
||||
// YAMLDecoder adds YAML decoding support to a codec that supports JSON.
|
||||
func YAMLDecoder(codec Codec) Codec {
|
||||
@@ -75,6 +76,9 @@ type codecWrapper struct {
|
||||
version string
|
||||
}
|
||||
|
||||
// codecWrapper implements Decoder
|
||||
var _ Decoder = &codecWrapper{}
|
||||
|
||||
// Encode implements Codec
|
||||
func (c *codecWrapper) Encode(obj Object) ([]byte, error) {
|
||||
return c.EncodeToVersion(obj, c.version)
|
||||
|
@@ -24,12 +24,13 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/conversion"
|
||||
"k8s.io/kubernetes/pkg/util/sets"
|
||||
)
|
||||
|
||||
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
|
||||
@@ -86,9 +87,15 @@ func (g *conversionGenerator) AddImport(pkg string) string {
|
||||
return g.addImportByPath(pkg)
|
||||
}
|
||||
|
||||
func (g *conversionGenerator) GenerateConversionsForType(version string, reflection reflect.Type) error {
|
||||
func (g *conversionGenerator) GenerateConversionsForType(gv unversioned.GroupVersion, reflection reflect.Type) error {
|
||||
kind := reflection.Name()
|
||||
internalObj, err := g.scheme.NewObject(g.scheme.InternalVersion, kind)
|
||||
// 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]
|
||||
if !exists {
|
||||
return fmt.Errorf("no internal version for %v", gv)
|
||||
}
|
||||
|
||||
internalObj, err := g.scheme.NewObject(internalGV.String(), kind)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot create an object of type %v in internal version", kind)
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -23,6 +23,7 @@ import (
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/meta"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/util"
|
||||
)
|
||||
@@ -61,11 +62,16 @@ func (*EmbeddedTest) IsAnAPIObject() {}
|
||||
func (*EmbeddedTestExternal) IsAnAPIObject() {}
|
||||
|
||||
func TestDecodeEmptyRawExtensionAsObject(t *testing.T) {
|
||||
s := runtime.NewScheme()
|
||||
s.AddKnownTypes("", &ObjectTest{})
|
||||
s.AddKnownTypeWithName("v1test", "ObjectTest", &ObjectTestExternal{})
|
||||
internalGV := unversioned.GroupVersion{Group: "test.group", Version: ""}
|
||||
externalGV := unversioned.GroupVersion{Group: "test.group", Version: "v1test"}
|
||||
externalGVK := externalGV.WithKind("ObjectTest")
|
||||
|
||||
obj, err := s.Decode([]byte(`{"kind":"ObjectTest","apiVersion":"v1test","items":[{}]}`))
|
||||
s := runtime.NewScheme()
|
||||
s.AddInternalGroupVersion(internalGV)
|
||||
s.AddKnownTypes(internalGV, &ObjectTest{})
|
||||
s.AddKnownTypeWithName(externalGVK, &ObjectTestExternal{})
|
||||
|
||||
obj, err := s.Decode([]byte(`{"kind":"` + externalGVK.Kind + `","apiVersion":"` + externalGV.String() + `","items":[{}]}`))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
@@ -74,7 +80,7 @@ func TestDecodeEmptyRawExtensionAsObject(t *testing.T) {
|
||||
t.Fatalf("unexpected object: %#v", test.Items[0])
|
||||
}
|
||||
|
||||
obj, err = s.Decode([]byte(`{"kind":"ObjectTest","apiVersion":"v1test","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)
|
||||
}
|
||||
@@ -85,11 +91,15 @@ func TestDecodeEmptyRawExtensionAsObject(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestArrayOfRuntimeObject(t *testing.T) {
|
||||
internalGV := unversioned.GroupVersion{Group: "test.group", Version: ""}
|
||||
externalGV := unversioned.GroupVersion{Group: "test.group", Version: "v1test"}
|
||||
|
||||
s := runtime.NewScheme()
|
||||
s.AddKnownTypes("", &EmbeddedTest{})
|
||||
s.AddKnownTypeWithName("v1test", "EmbeddedTest", &EmbeddedTestExternal{})
|
||||
s.AddKnownTypes("", &ObjectTest{})
|
||||
s.AddKnownTypeWithName("v1test", "ObjectTest", &ObjectTestExternal{})
|
||||
s.AddInternalGroupVersion(internalGV)
|
||||
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{
|
||||
@@ -104,7 +114,7 @@ func TestArrayOfRuntimeObject(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
wire, err := s.EncodeToVersion(internal, "v1test")
|
||||
wire, err := s.EncodeToVersion(internal, externalGV.String())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
@@ -147,9 +157,14 @@ func TestArrayOfRuntimeObject(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestEmbeddedObject(t *testing.T) {
|
||||
internalGV := unversioned.GroupVersion{Group: "test.group", Version: ""}
|
||||
externalGV := unversioned.GroupVersion{Group: "test.group", Version: "v1test"}
|
||||
embeddedTestExternalGVK := externalGV.WithKind("EmbeddedTest")
|
||||
|
||||
s := runtime.NewScheme()
|
||||
s.AddKnownTypes("", &EmbeddedTest{})
|
||||
s.AddKnownTypeWithName("v1test", "EmbeddedTest", &EmbeddedTestExternal{})
|
||||
s.AddInternalGroupVersion(internalGV)
|
||||
s.AddKnownTypes(internalGV, &EmbeddedTest{})
|
||||
s.AddKnownTypeWithName(embeddedTestExternalGVK, &EmbeddedTestExternal{})
|
||||
|
||||
outer := &EmbeddedTest{
|
||||
ID: "outer",
|
||||
@@ -160,7 +175,7 @@ func TestEmbeddedObject(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
wire, err := s.EncodeToVersion(outer, "v1test")
|
||||
wire, err := s.EncodeToVersion(outer, externalGV.String())
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected encode error '%v'", err)
|
||||
}
|
||||
@@ -206,9 +221,14 @@ func TestEmbeddedObject(t *testing.T) {
|
||||
|
||||
// TestDeepCopyOfEmbeddedObject checks to make sure that EmbeddedObject's can be passed through DeepCopy with fidelity
|
||||
func TestDeepCopyOfEmbeddedObject(t *testing.T) {
|
||||
internalGV := unversioned.GroupVersion{Group: "test.group", Version: ""}
|
||||
externalGV := unversioned.GroupVersion{Group: "test.group", Version: "v1test"}
|
||||
embeddedTestExternalGVK := externalGV.WithKind("EmbeddedTest")
|
||||
|
||||
s := runtime.NewScheme()
|
||||
s.AddKnownTypes("", &EmbeddedTest{})
|
||||
s.AddKnownTypeWithName("v1test", "EmbeddedTest", &EmbeddedTestExternal{})
|
||||
s.AddInternalGroupVersion(internalGV)
|
||||
s.AddKnownTypes(internalGV, &EmbeddedTest{})
|
||||
s.AddKnownTypeWithName(embeddedTestExternalGVK, &EmbeddedTestExternal{})
|
||||
|
||||
original := &EmbeddedTest{
|
||||
ID: "outer",
|
||||
@@ -219,7 +239,7 @@ func TestDeepCopyOfEmbeddedObject(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
originalData, err := s.EncodeToVersion(original, "v1test")
|
||||
originalData, err := s.EncodeToVersion(original, externalGV.String())
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
@@ -230,7 +250,7 @@ func TestDeepCopyOfEmbeddedObject(t *testing.T) {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
copiedData, err := s.EncodeToVersion(copyOfOriginal.(runtime.Object), "v1test")
|
||||
copiedData, err := s.EncodeToVersion(copyOfOriginal.(runtime.Object), externalGV.String())
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
@@ -19,6 +19,8 @@ package runtime
|
||||
import (
|
||||
"io"
|
||||
"net/url"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
)
|
||||
|
||||
// Codec defines methods for serializing and deserializing API objects.
|
||||
@@ -31,10 +33,10 @@ type Codec interface {
|
||||
type Decoder interface {
|
||||
Decode(data []byte) (Object, error)
|
||||
// TODO: Remove this method?
|
||||
DecodeToVersion(data []byte, version string) (Object, error)
|
||||
DecodeToVersion(data []byte, groupVersion unversioned.GroupVersion) (Object, error)
|
||||
DecodeInto(data []byte, obj Object) error
|
||||
// TODO: Remove this method?
|
||||
DecodeIntoWithSpecifiedVersionKind(data []byte, obj Object, kind, version string) error
|
||||
DecodeIntoWithSpecifiedVersionKind(data []byte, obj Object, groupVersionKind unversioned.GroupVersionKind) error
|
||||
|
||||
DecodeParametersInto(parameters url.Values, obj Object) error
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ import (
|
||||
"net/url"
|
||||
"reflect"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/conversion"
|
||||
)
|
||||
|
||||
@@ -35,6 +36,8 @@ type Scheme struct {
|
||||
fieldLabelConversionFuncs map[string]map[string]FieldLabelConversionFunc
|
||||
}
|
||||
|
||||
var _ Decoder = &Scheme{}
|
||||
|
||||
// Function to convert a field selector to internal representation.
|
||||
type FieldLabelConversionFunc func(label, value string) (internalLabel, internalValue string, err error)
|
||||
|
||||
@@ -178,8 +181,16 @@ func (self *Scheme) runtimeObjectToRawExtensionArray(in *[]Object, out *[]RawExt
|
||||
default:
|
||||
version := outVersion
|
||||
// if the object exists
|
||||
if inVersion, _, err := scheme.ObjectVersionAndKind(src[i]); err == nil && len(inVersion) != 0 {
|
||||
version = inVersion
|
||||
// this code is try to set the outputVersion, but only if the object has a non-internal group version
|
||||
if inGVString, _, err := scheme.ObjectVersionAndKind(src[i]); err == nil && len(inGVString) != 0 {
|
||||
inGV, err := unversioned.ParseGroupVersion(inGVString)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if self.raw.InternalVersions[inGV.Group] != inGV {
|
||||
version = inGV.String()
|
||||
}
|
||||
}
|
||||
data, err := scheme.EncodeToVersion(src[i], version)
|
||||
if err != nil {
|
||||
@@ -219,9 +230,13 @@ func (self *Scheme) rawExtensionToRuntimeObjectArray(in *[]RawExtension, out *[]
|
||||
}
|
||||
|
||||
// NewScheme creates a new Scheme. This scheme is pluggable by default.
|
||||
func NewScheme() *Scheme {
|
||||
func NewScheme(internalGroupVersions ...unversioned.GroupVersion) *Scheme {
|
||||
s := &Scheme{conversion.NewScheme(), map[string]map[string]FieldLabelConversionFunc{}}
|
||||
s.raw.InternalVersion = ""
|
||||
|
||||
for _, internalGV := range internalGroupVersions {
|
||||
s.raw.InternalVersions[internalGV.Group] = internalGV
|
||||
}
|
||||
|
||||
s.raw.MetaFactory = conversion.SimpleMetaFactory{BaseFields: []string{"TypeMeta"}, VersionField: "APIVersion", KindField: "Kind"}
|
||||
if err := s.raw.AddConversionFuncs(
|
||||
s.embeddedObjectToRawExtension,
|
||||
@@ -244,27 +259,33 @@ func NewScheme() *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
|
||||
@@ -456,8 +477,8 @@ func (s *Scheme) Decode(data []byte) (Object, error) {
|
||||
// are set by Encode. Only versioned objects (APIVersion != "") are
|
||||
// accepted. The object will be converted into the in-memory versioned type
|
||||
// requested before being returned.
|
||||
func (s *Scheme) DecodeToVersion(data []byte, version string) (Object, error) {
|
||||
obj, err := s.raw.DecodeToVersion(data, version)
|
||||
func (s *Scheme) DecodeToVersion(data []byte, gv unversioned.GroupVersion) (Object, error) {
|
||||
obj, err := s.raw.DecodeToVersion(data, gv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -476,8 +497,10 @@ func (s *Scheme) DecodeInto(data []byte, obj Object) error {
|
||||
return s.raw.DecodeInto(data, obj)
|
||||
}
|
||||
|
||||
func (s *Scheme) DecodeIntoWithSpecifiedVersionKind(data []byte, obj Object, version, kind string) error {
|
||||
return s.raw.DecodeIntoWithSpecifiedVersionKind(data, obj, version, kind)
|
||||
// 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)
|
||||
}
|
||||
|
||||
func (s *Scheme) DecodeParametersInto(parameters url.Values, obj Object) error {
|
||||
|
@@ -20,6 +20,7 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/conversion"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
@@ -43,9 +44,13 @@ func (*InternalSimple) IsAnAPIObject() {}
|
||||
func (*ExternalSimple) IsAnAPIObject() {}
|
||||
|
||||
func TestScheme(t *testing.T) {
|
||||
internalGV := unversioned.GroupVersion{Group: "test.group", Version: ""}
|
||||
externalGV := unversioned.GroupVersion{Group: "test.group", Version: "testExternal"}
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
scheme.AddKnownTypeWithName("", "Simple", &InternalSimple{})
|
||||
scheme.AddKnownTypeWithName("externalVersion", "Simple", &ExternalSimple{})
|
||||
scheme.AddInternalGroupVersion(internalGV)
|
||||
scheme.AddKnownTypeWithName(internalGV.WithKind("Simple"), &InternalSimple{})
|
||||
scheme.AddKnownTypeWithName(externalGV.WithKind("Simple"), &ExternalSimple{})
|
||||
|
||||
// test that scheme is an ObjectTyper
|
||||
var _ runtime.ObjectTyper = scheme
|
||||
@@ -56,10 +61,10 @@ func TestScheme(t *testing.T) {
|
||||
// Register functions to verify that scope.Meta() gets set correctly.
|
||||
err := scheme.AddConversionFuncs(
|
||||
func(in *InternalSimple, out *ExternalSimple, scope conversion.Scope) error {
|
||||
if e, a := "", scope.Meta().SrcVersion; e != a {
|
||||
if e, a := internalGV.String(), scope.Meta().SrcVersion; e != a {
|
||||
t.Errorf("Expected '%v', got '%v'", e, a)
|
||||
}
|
||||
if e, a := "externalVersion", scope.Meta().DestVersion; e != a {
|
||||
if e, a := externalGV.String(), scope.Meta().DestVersion; e != a {
|
||||
t.Errorf("Expected '%v', got '%v'", e, a)
|
||||
}
|
||||
scope.Convert(&in.TypeMeta, &out.TypeMeta, 0)
|
||||
@@ -68,10 +73,10 @@ func TestScheme(t *testing.T) {
|
||||
return nil
|
||||
},
|
||||
func(in *ExternalSimple, out *InternalSimple, scope conversion.Scope) error {
|
||||
if e, a := "externalVersion", scope.Meta().SrcVersion; e != a {
|
||||
if e, a := externalGV.String(), scope.Meta().SrcVersion; e != a {
|
||||
t.Errorf("Expected '%v', got '%v'", e, a)
|
||||
}
|
||||
if e, a := "", scope.Meta().DestVersion; e != a {
|
||||
if e, a := internalGV.String(), scope.Meta().DestVersion; e != a {
|
||||
t.Errorf("Expected '%v', got '%v'", e, a)
|
||||
}
|
||||
scope.Convert(&in.TypeMeta, &out.TypeMeta, 0)
|
||||
@@ -89,11 +94,11 @@ func TestScheme(t *testing.T) {
|
||||
|
||||
// Test Encode, Decode, DecodeInto, and DecodeToVersion
|
||||
obj := runtime.Object(simple)
|
||||
data, err := scheme.EncodeToVersion(obj, "externalVersion")
|
||||
data, err := scheme.EncodeToVersion(obj, externalGV.String())
|
||||
obj2, err2 := scheme.Decode(data)
|
||||
obj3 := &InternalSimple{}
|
||||
err3 := scheme.DecodeInto(data, obj3)
|
||||
obj4, err4 := scheme.DecodeToVersion(data, "externalVersion")
|
||||
obj4, err4 := scheme.DecodeToVersion(data, externalGV)
|
||||
if err != nil || err2 != nil || err3 != nil || err4 != nil {
|
||||
t.Fatalf("Failure: '%v' '%v' '%v' '%v'", err, err2, err3, err4)
|
||||
}
|
||||
@@ -131,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) {
|
||||
@@ -198,9 +205,13 @@ func (*ExternalOptionalExtensionType) IsAnAPIObject() {}
|
||||
func (*InternalOptionalExtensionType) IsAnAPIObject() {}
|
||||
|
||||
func TestExternalToInternalMapping(t *testing.T) {
|
||||
internalGV := unversioned.GroupVersion{Group: "test.group", Version: ""}
|
||||
externalGV := unversioned.GroupVersion{Group: "test.group", Version: "testExternal"}
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
scheme.AddKnownTypeWithName("", "OptionalExtensionType", &InternalOptionalExtensionType{})
|
||||
scheme.AddKnownTypeWithName("testExternal", "OptionalExtensionType", &ExternalOptionalExtensionType{})
|
||||
scheme.AddInternalGroupVersion(internalGV)
|
||||
scheme.AddKnownTypeWithName(internalGV.WithKind("OptionalExtensionType"), &InternalOptionalExtensionType{})
|
||||
scheme.AddKnownTypeWithName(externalGV.WithKind("OptionalExtensionType"), &ExternalOptionalExtensionType{})
|
||||
|
||||
table := []struct {
|
||||
obj runtime.Object
|
||||
@@ -208,7 +219,7 @@ func TestExternalToInternalMapping(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
&InternalOptionalExtensionType{Extension: runtime.EmbeddedObject{Object: nil}},
|
||||
`{"kind":"OptionalExtensionType","apiVersion":"testExternal"}`,
|
||||
`{"kind":"OptionalExtensionType","apiVersion":"` + externalGV.String() + `"}`,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -230,15 +241,19 @@ func TestExternalToInternalMapping(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestExtensionMapping(t *testing.T) {
|
||||
internalGV := unversioned.GroupVersion{Group: "test.group", Version: ""}
|
||||
externalGV := unversioned.GroupVersion{Group: "test.group", Version: "testExternal"}
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
scheme.AddKnownTypeWithName("", "ExtensionType", &InternalExtensionType{})
|
||||
scheme.AddKnownTypeWithName("", "OptionalExtensionType", &InternalOptionalExtensionType{})
|
||||
scheme.AddKnownTypeWithName("", "A", &ExtensionA{})
|
||||
scheme.AddKnownTypeWithName("", "B", &ExtensionB{})
|
||||
scheme.AddKnownTypeWithName("testExternal", "ExtensionType", &ExternalExtensionType{})
|
||||
scheme.AddKnownTypeWithName("testExternal", "OptionalExtensionType", &ExternalOptionalExtensionType{})
|
||||
scheme.AddKnownTypeWithName("testExternal", "A", &ExtensionA{})
|
||||
scheme.AddKnownTypeWithName("testExternal", "B", &ExtensionB{})
|
||||
scheme.AddInternalGroupVersion(internalGV)
|
||||
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
|
||||
@@ -246,21 +261,21 @@ func TestExtensionMapping(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
&InternalExtensionType{Extension: runtime.EmbeddedObject{Object: &ExtensionA{TestString: "foo"}}},
|
||||
`{"kind":"ExtensionType","apiVersion":"testExternal","extension":{"kind":"A","testString":"foo"}}
|
||||
`{"kind":"ExtensionType","apiVersion":"` + externalGV.String() + `","extension":{"kind":"A","testString":"foo"}}
|
||||
`,
|
||||
}, {
|
||||
&InternalExtensionType{Extension: runtime.EmbeddedObject{Object: &ExtensionB{TestString: "bar"}}},
|
||||
`{"kind":"ExtensionType","apiVersion":"testExternal","extension":{"kind":"B","testString":"bar"}}
|
||||
`{"kind":"ExtensionType","apiVersion":"` + externalGV.String() + `","extension":{"kind":"B","testString":"bar"}}
|
||||
`,
|
||||
}, {
|
||||
&InternalExtensionType{Extension: runtime.EmbeddedObject{Object: nil}},
|
||||
`{"kind":"ExtensionType","apiVersion":"testExternal","extension":null}
|
||||
`{"kind":"ExtensionType","apiVersion":"` + externalGV.String() + `","extension":null}
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, item := range table {
|
||||
gotEncoded, err := scheme.EncodeToVersion(item.obj, "testExternal")
|
||||
gotEncoded, err := scheme.EncodeToVersion(item.obj, externalGV.String())
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error '%v' (%#v)", err, item.obj)
|
||||
} else if e, a := item.encoded, string(gotEncoded); e != a {
|
||||
@@ -284,10 +299,14 @@ func TestExtensionMapping(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestEncode(t *testing.T) {
|
||||
internalGV := unversioned.GroupVersion{Group: "test.group", Version: ""}
|
||||
externalGV := unversioned.GroupVersion{Group: "test.group", Version: "testExternal"}
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
scheme.AddKnownTypeWithName("", "Simple", &InternalSimple{})
|
||||
scheme.AddKnownTypeWithName("externalVersion", "Simple", &ExternalSimple{})
|
||||
codec := runtime.CodecFor(scheme, "externalVersion")
|
||||
scheme.AddInternalGroupVersion(internalGV)
|
||||
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",
|
||||
}
|
||||
|
@@ -22,6 +22,7 @@ import (
|
||||
"net/url"
|
||||
"reflect"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/conversion"
|
||||
)
|
||||
|
||||
@@ -31,6 +32,8 @@ var UnstructuredJSONScheme ObjectDecoder = unstructuredJSONScheme{}
|
||||
|
||||
type unstructuredJSONScheme struct{}
|
||||
|
||||
var _ Decoder = unstructuredJSONScheme{}
|
||||
|
||||
// Recognizes returns true for any version or kind that is specified (internal
|
||||
// versions are specifically excluded).
|
||||
func (unstructuredJSONScheme) Recognizes(version, kind string) bool {
|
||||
@@ -75,11 +78,11 @@ func (unstructuredJSONScheme) DecodeInto(data []byte, obj Object) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (unstructuredJSONScheme) DecodeIntoWithSpecifiedVersionKind(data []byte, obj Object, kind, version string) error {
|
||||
func (unstructuredJSONScheme) DecodeIntoWithSpecifiedVersionKind(data []byte, obj Object, gvk unversioned.GroupVersionKind) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (unstructuredJSONScheme) DecodeToVersion(data []byte, version string) (Object, error) {
|
||||
func (unstructuredJSONScheme) DecodeToVersion(data []byte, gv unversioned.GroupVersion) (Object, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
@@ -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 {
|
||||
|
@@ -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{},
|
||||
)
|
||||
}
|
||||
|
@@ -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{},
|
||||
)
|
||||
}
|
||||
|
Reference in New Issue
Block a user