mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-10-31 18:28:13 +00:00 
			
		
		
		
	Move GroupVersion* to pkg/runtime/schema
This commit is contained in:
		| @@ -107,7 +107,7 @@ func (g *genFakeForType) GenerateType(c *generator.Context, t *types.Type, w io. | ||||
| 		"groupName":            groupName, | ||||
| 		"version":              g.version, | ||||
| 		"watchInterface":       c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/watch", Name: "Interface"}), | ||||
| 		"GroupVersionResource": c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/api/unversioned", Name: "GroupVersionResource"}), | ||||
| 		"GroupVersionResource": c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/runtime/schema", Name: "GroupVersionResource"}), | ||||
| 		"PatchType":            c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/api", Name: "PatchType"}), | ||||
| 		"Everything":           c.Universe.Function(types.Name{Package: "k8s.io/kubernetes/pkg/labels", Name: "Everything"}), | ||||
|  | ||||
|   | ||||
| @@ -62,6 +62,7 @@ func (g *genGroup) GenerateType(c *generator.Context, t *types.Type, w io.Writer | ||||
| 	const pkgAPI = "k8s.io/kubernetes/pkg/api" | ||||
| 	const pkgSerializer = "k8s.io/kubernetes/pkg/runtime/serializer" | ||||
| 	const pkgUnversioned = "k8s.io/kubernetes/pkg/api/unversioned" | ||||
| 	const pkgSchema = "k8s.io/kubernetes/pkg/runtime/schema" | ||||
|  | ||||
| 	apiPath := func(group string) string { | ||||
| 		if len(g.apiPath) > 0 { | ||||
| @@ -96,7 +97,7 @@ func (g *genGroup) GenerateType(c *generator.Context, t *types.Type, w io.Writer | ||||
| 		"Group":                      c.Universe.Variable(types.Name{Package: pkgRegistered, Name: "Group"}), | ||||
| 		"GroupOrDie":                 c.Universe.Variable(types.Name{Package: pkgRegistered, Name: "GroupOrDie"}), | ||||
| 		"IsEnabledVersion":           c.Universe.Variable(types.Name{Package: pkgRegistered, Name: "IsEnabledVersion"}), | ||||
| 		"ParseGroupVersion":          c.Universe.Function(types.Name{Package: pkgUnversioned, Name: "ParseGroupVersion"}), | ||||
| 		"ParseGroupVersion":          c.Universe.Function(types.Name{Package: pkgSchema, Name: "ParseGroupVersion"}), | ||||
| 		"apiPath":                    apiPath(g.group), | ||||
| 		"codecs":                     c.Universe.Variable(types.Name{Package: pkgAPI, Name: "Codecs"}), | ||||
| 		"directCodecFactory":         c.Universe.Variable(types.Name{Package: pkgSerializer, Name: "DirectCodecFactory"}), | ||||
|   | ||||
| @@ -62,6 +62,7 @@ func New() *Generator { | ||||
| 		Packages: strings.Join([]string{ | ||||
| 			`+k8s.io/kubernetes/pkg/util/intstr`, | ||||
| 			`+k8s.io/kubernetes/pkg/api/resource`, | ||||
| 			`+k8s.io/kubernetes/pkg/runtime/schema`, | ||||
| 			`+k8s.io/kubernetes/pkg/runtime`, | ||||
| 			`+k8s.io/kubernetes/pkg/watch/versioned`, | ||||
| 			`k8s.io/kubernetes/pkg/api/unversioned`, | ||||
|   | ||||
| @@ -24,13 +24,13 @@ import ( | ||||
| 	testgroupetcd "k8s.io/kubernetes/examples/apiserver/rest" | ||||
| 	"k8s.io/kubernetes/pkg/api" | ||||
| 	"k8s.io/kubernetes/pkg/api/rest" | ||||
| 	"k8s.io/kubernetes/pkg/api/unversioned" | ||||
| 	"k8s.io/kubernetes/pkg/apimachinery/registered" | ||||
| 	"k8s.io/kubernetes/pkg/genericapiserver" | ||||
| 	"k8s.io/kubernetes/pkg/genericapiserver/authorizer" | ||||
| 	genericoptions "k8s.io/kubernetes/pkg/genericapiserver/options" | ||||
| 	genericvalidation "k8s.io/kubernetes/pkg/genericapiserver/validation" | ||||
| 	"k8s.io/kubernetes/pkg/registry/generic" | ||||
| 	"k8s.io/kubernetes/pkg/runtime/schema" | ||||
| 	"k8s.io/kubernetes/pkg/storage/storagebackend" | ||||
|  | ||||
| 	// Install the testgroup API | ||||
| @@ -86,7 +86,7 @@ func Run(serverOptions *genericoptions.ServerRunOptions, stopCh <-chan struct{}) | ||||
| 		return fmt.Errorf("%v", err) | ||||
| 	} | ||||
| 	storageFactory := newStorageFactory() | ||||
| 	storageConfig, err := storageFactory.NewConfig(unversioned.GroupResource{Group: groupName, Resource: "testtype"}) | ||||
| 	storageConfig, err := storageFactory.NewConfig(schema.GroupResource{Group: groupName, Resource: "testtype"}) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("Unable to get storage config: %v", err) | ||||
| 	} | ||||
|   | ||||
| @@ -20,23 +20,10 @@ import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
|  | ||||
| 	"k8s.io/kubernetes/pkg/runtime/schema" | ||||
| ) | ||||
|  | ||||
| // ParseResourceArg takes the common style of string which may be either `resource.group.com` or `resource.version.group.com` | ||||
| // and parses it out into both possibilities.  This code takes no responsibility for knowing which representation was intended | ||||
| // but with a knowledge of all GroupVersions, calling code can take a very good guess.  If there are only two segments, then | ||||
| // `*GroupVersionResource` is nil. | ||||
| // `resource.group.com` -> `group=com, version=group, resource=resource` and `group=group.com, resource=resource` | ||||
| func ParseResourceArg(arg string) (*GroupVersionResource, GroupResource) { | ||||
| 	var gvr *GroupVersionResource | ||||
| 	if strings.Count(arg, ".") >= 2 { | ||||
| 		s := strings.SplitN(arg, ".", 3) | ||||
| 		gvr = &GroupVersionResource{Group: s[2], Version: s[1], Resource: s[0]} | ||||
| 	} | ||||
|  | ||||
| 	return gvr, ParseGroupResource(arg) | ||||
| } | ||||
|  | ||||
| // GroupResource specifies a Group and a Resource, but does not force a version.  This is useful for identifying | ||||
| // concepts during lookup stages without having partially valid types | ||||
| // | ||||
| @@ -46,14 +33,6 @@ type GroupResource struct { | ||||
| 	Resource string `protobuf:"bytes,2,opt,name=resource"` | ||||
| } | ||||
|  | ||||
| func (gr GroupResource) WithVersion(version string) GroupVersionResource { | ||||
| 	return GroupVersionResource{Group: gr.Group, Version: version, Resource: gr.Resource} | ||||
| } | ||||
|  | ||||
| func (gr GroupResource) Empty() bool { | ||||
| 	return len(gr.Group) == 0 && len(gr.Resource) == 0 | ||||
| } | ||||
|  | ||||
| func (gr *GroupResource) String() string { | ||||
| 	if len(gr.Group) == 0 { | ||||
| 		return gr.Resource | ||||
| @@ -61,16 +40,6 @@ func (gr *GroupResource) String() string { | ||||
| 	return gr.Resource + "." + gr.Group | ||||
| } | ||||
|  | ||||
| // ParseGroupResource turns "resource.group" string into a GroupResource struct.  Empty strings are allowed | ||||
| // for each field. | ||||
| func ParseGroupResource(gr string) GroupResource { | ||||
| 	if i := strings.Index(gr, "."); i == -1 { | ||||
| 		return GroupResource{Resource: gr} | ||||
| 	} else { | ||||
| 		return GroupResource{Group: gr[i+1:], Resource: gr[:i]} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // GroupVersionResource unambiguously identifies a resource.  It doesn't anonymously include GroupVersion | ||||
| // to avoid automatic coersion.  It doesn't use a GroupVersion to avoid custom marshalling | ||||
| // | ||||
| @@ -81,18 +50,6 @@ type GroupVersionResource struct { | ||||
| 	Resource string `protobuf:"bytes,3,opt,name=resource"` | ||||
| } | ||||
|  | ||||
| func (gvr GroupVersionResource) Empty() bool { | ||||
| 	return len(gvr.Group) == 0 && len(gvr.Version) == 0 && len(gvr.Resource) == 0 | ||||
| } | ||||
|  | ||||
| func (gvr GroupVersionResource) GroupResource() GroupResource { | ||||
| 	return GroupResource{Group: gvr.Group, Resource: gvr.Resource} | ||||
| } | ||||
|  | ||||
| func (gvr GroupVersionResource) GroupVersion() GroupVersion { | ||||
| 	return GroupVersion{Group: gvr.Group, Version: gvr.Version} | ||||
| } | ||||
|  | ||||
| func (gvr *GroupVersionResource) String() string { | ||||
| 	return strings.Join([]string{gvr.Group, "/", gvr.Version, ", Resource=", gvr.Resource}, "") | ||||
| } | ||||
| @@ -106,14 +63,6 @@ type GroupKind struct { | ||||
| 	Kind  string `protobuf:"bytes,2,opt,name=kind"` | ||||
| } | ||||
|  | ||||
| func (gk GroupKind) Empty() bool { | ||||
| 	return len(gk.Group) == 0 && len(gk.Kind) == 0 | ||||
| } | ||||
|  | ||||
| func (gk GroupKind) WithVersion(version string) GroupVersionKind { | ||||
| 	return GroupVersionKind{Group: gk.Group, Version: version, Kind: gk.Kind} | ||||
| } | ||||
|  | ||||
| func (gk *GroupKind) String() string { | ||||
| 	if len(gk.Group) == 0 { | ||||
| 		return gk.Kind | ||||
| @@ -131,19 +80,6 @@ type GroupVersionKind struct { | ||||
| 	Kind    string `protobuf:"bytes,3,opt,name=kind"` | ||||
| } | ||||
|  | ||||
| // Empty returns true if group, version, and kind are empty | ||||
| func (gvk GroupVersionKind) Empty() bool { | ||||
| 	return len(gvk.Group) == 0 && len(gvk.Version) == 0 && len(gvk.Kind) == 0 | ||||
| } | ||||
|  | ||||
| func (gvk GroupVersionKind) GroupKind() GroupKind { | ||||
| 	return GroupKind{Group: gvk.Group, Kind: gvk.Kind} | ||||
| } | ||||
|  | ||||
| func (gvk GroupVersionKind) GroupVersion() GroupVersion { | ||||
| 	return GroupVersion{Group: gvk.Group, Version: gvk.Version} | ||||
| } | ||||
|  | ||||
| func (gvk GroupVersionKind) String() string { | ||||
| 	return gvk.Group + "/" + gvk.Version + ", Kind=" + gvk.Kind | ||||
| } | ||||
| @@ -179,55 +115,6 @@ func (gv GroupVersion) String() string { | ||||
| 	return gv.Version | ||||
| } | ||||
|  | ||||
| // KindForGroupVersionKinds identifies the preferred GroupVersionKind out of a list. It returns ok false | ||||
| // if none of the options match the group. It prefers a match to group and version over just group. | ||||
| // TODO: Move GroupVersion to a package under pkg/runtime, since it's used by scheme. | ||||
| // TODO: Introduce an adapter type between GroupVersion and runtime.GroupVersioner, and use LegacyCodec(GroupVersion) | ||||
| //   in fewer places. | ||||
| func (gv GroupVersion) KindForGroupVersionKinds(kinds []GroupVersionKind) (target GroupVersionKind, ok bool) { | ||||
| 	for _, gvk := range kinds { | ||||
| 		if gvk.Group == gv.Group && gvk.Version == gv.Version { | ||||
| 			return gvk, true | ||||
| 		} | ||||
| 	} | ||||
| 	for _, gvk := range kinds { | ||||
| 		if gvk.Group == gv.Group { | ||||
| 			return gv.WithKind(gvk.Kind), true | ||||
| 		} | ||||
| 	} | ||||
| 	return GroupVersionKind{}, false | ||||
| } | ||||
|  | ||||
| // 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 | ||||
| 	} | ||||
|  | ||||
| 	switch strings.Count(gv, "/") { | ||||
| 	case 0: | ||||
| 		return GroupVersion{"", gv}, nil | ||||
| 	case 1: | ||||
| 		i := strings.Index(gv, "/") | ||||
| 		return GroupVersion{gv[:i], gv[i+1:]}, nil | ||||
| 	default: | ||||
| 		return GroupVersion{}, fmt.Errorf("unexpected GroupVersion string: %v", gv) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // 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} | ||||
| } | ||||
|  | ||||
| // WithResource creates a GroupVersionResource based on the method receiver's GroupVersion and the passed Resource. | ||||
| func (gv GroupVersion) WithResource(resource string) GroupVersionResource { | ||||
| 	return GroupVersionResource{Group: gv.Group, Version: gv.Version, Resource: resource} | ||||
| } | ||||
|  | ||||
| // MarshalJSON implements the json.Marshaller interface. | ||||
| func (gv GroupVersion) MarshalJSON() ([]byte, error) { | ||||
| 	s := gv.String() | ||||
| @@ -242,11 +129,11 @@ func (gv *GroupVersion) unmarshal(value []byte) error { | ||||
| 	if err := json.Unmarshal(value, &s); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	parsed, err := ParseGroupVersion(s) | ||||
| 	parsed, err := schema.ParseGroupVersion(s) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	*gv = parsed | ||||
| 	gv.Group, gv.Version = parsed.Group, parsed.Version | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| @@ -259,87 +146,3 @@ func (gv *GroupVersion) UnmarshalJSON(value []byte) error { | ||||
| func (gv *GroupVersion) UnmarshalText(value []byte) error { | ||||
| 	return gv.unmarshal(value) | ||||
| } | ||||
|  | ||||
| // GroupVersions can be used to represent a set of desired group versions. | ||||
| // TODO: Move GroupVersions to a package under pkg/runtime, since it's used by scheme. | ||||
| // TODO: Introduce an adapter type between GroupVersions and runtime.GroupVersioner, and use LegacyCodec(GroupVersion) | ||||
| //   in fewer places. | ||||
| type GroupVersions []GroupVersion | ||||
|  | ||||
| // KindForGroupVersionKinds identifies the preferred GroupVersionKind out of a list. It returns ok false | ||||
| // if none of the options match the group. | ||||
| func (gvs GroupVersions) KindForGroupVersionKinds(kinds []GroupVersionKind) (GroupVersionKind, bool) { | ||||
| 	var targets []GroupVersionKind | ||||
| 	for _, gv := range gvs { | ||||
| 		target, ok := gv.KindForGroupVersionKinds(kinds) | ||||
| 		if !ok { | ||||
| 			continue | ||||
| 		} | ||||
| 		targets = append(targets, target) | ||||
| 	} | ||||
| 	if len(targets) == 1 { | ||||
| 		return targets[0], true | ||||
| 	} | ||||
| 	if len(targets) > 1 { | ||||
| 		return bestMatch(kinds, targets), true | ||||
| 	} | ||||
| 	return GroupVersionKind{}, false | ||||
| } | ||||
|  | ||||
| // bestMatch tries to pick best matching GroupVersionKind and falls back to the first | ||||
| // found if no exact match exists. | ||||
| func bestMatch(kinds []GroupVersionKind, targets []GroupVersionKind) GroupVersionKind { | ||||
| 	for _, gvk := range targets { | ||||
| 		for _, k := range kinds { | ||||
| 			if k == gvk { | ||||
| 				return k | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return targets[0] | ||||
| } | ||||
|  | ||||
| // ToAPIVersionAndKind is a convenience method for satisfying runtime.Object on types that | ||||
| // do not use TypeMeta. | ||||
| func (gvk *GroupVersionKind) ToAPIVersionAndKind() (string, string) { | ||||
| 	if gvk == nil { | ||||
| 		return "", "" | ||||
| 	} | ||||
| 	return gvk.GroupVersion().String(), gvk.Kind | ||||
| } | ||||
|  | ||||
| // FromAPIVersionAndKind returns a GVK representing the provided fields for types that | ||||
| // do not use TypeMeta. This method exists to support test types and legacy serializations | ||||
| // that have a distinct group and kind. | ||||
| // TODO: further reduce usage of this method. | ||||
| func FromAPIVersionAndKind(apiVersion, kind string) GroupVersionKind { | ||||
| 	if gv, err := ParseGroupVersion(apiVersion); err == nil { | ||||
| 		return GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: kind} | ||||
| 	} | ||||
| 	return GroupVersionKind{Kind: kind} | ||||
| } | ||||
|  | ||||
| // All objects that are serialized from a Scheme encode their type information. This interface is used | ||||
| // by serialization to set type information from the Scheme onto the serialized version of an object. | ||||
| // For objects that cannot be serialized or have unique requirements, this interface may be a no-op. | ||||
| // TODO: this belongs in pkg/runtime, move unversioned.GVK into runtime. | ||||
| type ObjectKind interface { | ||||
| 	// SetGroupVersionKind sets or clears the intended serialized kind of an object. Passing kind nil | ||||
| 	// should clear the current setting. | ||||
| 	SetGroupVersionKind(kind GroupVersionKind) | ||||
| 	// GroupVersionKind returns the stored group, version, and kind of an object, or nil if the object does | ||||
| 	// not expose or provide these fields. | ||||
| 	GroupVersionKind() GroupVersionKind | ||||
| } | ||||
|  | ||||
| // EmptyObjectKind implements the ObjectKind interface as a noop | ||||
| // TODO: this belongs in pkg/runtime, move unversioned.GVK into runtime. | ||||
| var EmptyObjectKind = emptyObjectKind{} | ||||
|  | ||||
| type emptyObjectKind struct{} | ||||
|  | ||||
| // SetGroupVersionKind implements the ObjectKind interface | ||||
| func (emptyObjectKind) SetGroupVersionKind(gvk GroupVersionKind) {} | ||||
|  | ||||
| // GroupVersionKind implements the ObjectKind interface | ||||
| func (emptyObjectKind) GroupVersionKind() GroupVersionKind { return GroupVersionKind{} } | ||||
|   | ||||
| @@ -24,77 +24,6 @@ import ( | ||||
| 	"github.com/ugorji/go/codec" | ||||
| ) | ||||
|  | ||||
| func TestGroupVersionParse(t *testing.T) { | ||||
| 	tests := []struct { | ||||
| 		input string | ||||
| 		out   GroupVersion | ||||
| 		err   func(error) bool | ||||
| 	}{ | ||||
| 		{input: "v1", out: GroupVersion{Version: "v1"}}, | ||||
| 		{input: "v2", out: GroupVersion{Version: "v2"}}, | ||||
| 		{input: "/v1", out: GroupVersion{Version: "v1"}}, | ||||
| 		{input: "v1/", out: GroupVersion{Group: "v1"}}, | ||||
| 		{input: "/v1/", err: func(err error) bool { return err.Error() == "unexpected GroupVersion string: /v1/" }}, | ||||
| 		{input: "v1/a", out: GroupVersion{Group: "v1", Version: "a"}}, | ||||
| 	} | ||||
| 	for i, test := range tests { | ||||
| 		out, err := ParseGroupVersion(test.input) | ||||
| 		if test.err == nil && err != nil || err == nil && test.err != nil { | ||||
| 			t.Errorf("%d: unexpected error: %v", i, err) | ||||
| 			continue | ||||
| 		} | ||||
| 		if test.err != nil && !test.err(err) { | ||||
| 			t.Errorf("%d: unexpected error: %v", i, err) | ||||
| 			continue | ||||
| 		} | ||||
| 		if out != test.out { | ||||
| 			t.Errorf("%d: unexpected output: %#v", i, out) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestGroupResourceParse(t *testing.T) { | ||||
| 	tests := []struct { | ||||
| 		input string | ||||
| 		out   GroupResource | ||||
| 	}{ | ||||
| 		{input: "v1", out: GroupResource{Resource: "v1"}}, | ||||
| 		{input: ".v1", out: GroupResource{Group: "v1"}}, | ||||
| 		{input: "v1.", out: GroupResource{Resource: "v1"}}, | ||||
| 		{input: "v1.a", out: GroupResource{Group: "a", Resource: "v1"}}, | ||||
| 		{input: "b.v1.a", out: GroupResource{Group: "v1.a", Resource: "b"}}, | ||||
| 	} | ||||
| 	for i, test := range tests { | ||||
| 		out := ParseGroupResource(test.input) | ||||
| 		if out != test.out { | ||||
| 			t.Errorf("%d: unexpected output: %#v", i, out) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestParseResourceArg(t *testing.T) { | ||||
| 	tests := []struct { | ||||
| 		input string | ||||
| 		gvr   *GroupVersionResource | ||||
| 		gr    GroupResource | ||||
| 	}{ | ||||
| 		{input: "v1", gr: GroupResource{Resource: "v1"}}, | ||||
| 		{input: ".v1", gr: GroupResource{Group: "v1"}}, | ||||
| 		{input: "v1.", gr: GroupResource{Resource: "v1"}}, | ||||
| 		{input: "v1.a", gr: GroupResource{Group: "a", Resource: "v1"}}, | ||||
| 		{input: "b.v1.a", gvr: &GroupVersionResource{Group: "a", Version: "v1", Resource: "b"}, gr: GroupResource{Group: "v1.a", Resource: "b"}}, | ||||
| 	} | ||||
| 	for i, test := range tests { | ||||
| 		gvr, gr := ParseResourceArg(test.input) | ||||
| 		if (gvr != nil && test.gvr == nil) || (gvr == nil && test.gvr != nil) || (test.gvr != nil && *gvr != *test.gvr) { | ||||
| 			t.Errorf("%d: unexpected output: %#v", i, gvr) | ||||
| 		} | ||||
| 		if gr != test.gr { | ||||
| 			t.Errorf("%d: unexpected output: %#v", i, gr) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type GroupVersionHolder struct { | ||||
| 	GV GroupVersion `json:"val"` | ||||
| } | ||||
| @@ -147,47 +76,3 @@ func TestGroupVersionMarshalJSON(t *testing.T) { | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestKindForGroupVersionKinds(t *testing.T) { | ||||
| 	gvks := GroupVersions{ | ||||
| 		GroupVersion{Group: "batch", Version: "v1"}, | ||||
| 		GroupVersion{Group: "batch", Version: "v2alpha1"}, | ||||
| 		GroupVersion{Group: "policy", Version: "v1beta1"}, | ||||
| 	} | ||||
| 	cases := []struct { | ||||
| 		input  []GroupVersionKind | ||||
| 		target GroupVersionKind | ||||
| 		ok     bool | ||||
| 	}{ | ||||
| 		{ | ||||
| 			input:  []GroupVersionKind{{Group: "batch", Version: "v2alpha1", Kind: "ScheduledJob"}}, | ||||
| 			target: GroupVersionKind{Group: "batch", Version: "v2alpha1", Kind: "ScheduledJob"}, | ||||
| 			ok:     true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			input:  []GroupVersionKind{{Group: "batch", Version: "v3alpha1", Kind: "CronJob"}}, | ||||
| 			target: GroupVersionKind{Group: "batch", Version: "v1", Kind: "CronJob"}, | ||||
| 			ok:     true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			input:  []GroupVersionKind{{Group: "policy", Version: "v1beta1", Kind: "PodDisruptionBudget"}}, | ||||
| 			target: GroupVersionKind{Group: "policy", Version: "v1beta1", Kind: "PodDisruptionBudget"}, | ||||
| 			ok:     true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			input:  []GroupVersionKind{{Group: "apps", Version: "v1alpha1", Kind: "StatefulSet"}}, | ||||
| 			target: GroupVersionKind{}, | ||||
| 			ok:     false, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for i, c := range cases { | ||||
| 		target, ok := gvks.KindForGroupVersionKinds(c.input) | ||||
| 		if c.target != target { | ||||
| 			t.Errorf("%d: unexpected target: %v, expected %v", i, target, c.target) | ||||
| 		} | ||||
| 		if c.ok != ok { | ||||
| 			t.Errorf("%d: unexpected ok: %v, expected %v", i, ok, c.ok) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -16,6 +16,10 @@ limitations under the License. | ||||
|  | ||||
| package unversioned | ||||
|  | ||||
| import ( | ||||
| 	"k8s.io/kubernetes/pkg/runtime/schema" | ||||
| ) | ||||
|  | ||||
| // ListMetaAccessor retrieves the list interface from an object | ||||
| // TODO: move this, and TypeMeta and ListMeta, to a different package | ||||
| type ListMetaAccessor interface { | ||||
| @@ -47,16 +51,16 @@ func (meta *ListMeta) SetResourceVersion(version string) { meta.ResourceVersion | ||||
| func (meta *ListMeta) GetSelfLink() string               { return meta.SelfLink } | ||||
| func (meta *ListMeta) SetSelfLink(selfLink string)       { meta.SelfLink = selfLink } | ||||
|  | ||||
| func (obj *TypeMeta) GetObjectKind() ObjectKind { return obj } | ||||
| func (obj *TypeMeta) GetObjectKind() schema.ObjectKind { return obj } | ||||
|  | ||||
| // SetGroupVersionKind satisfies the ObjectKind interface for all objects that embed TypeMeta | ||||
| func (obj *TypeMeta) SetGroupVersionKind(gvk GroupVersionKind) { | ||||
| func (obj *TypeMeta) SetGroupVersionKind(gvk schema.GroupVersionKind) { | ||||
| 	obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind() | ||||
| } | ||||
|  | ||||
| // GroupVersionKind satisfies the ObjectKind interface for all objects that embed TypeMeta | ||||
| func (obj *TypeMeta) GroupVersionKind() GroupVersionKind { | ||||
| 	return FromAPIVersionAndKind(obj.APIVersion, obj.Kind) | ||||
| func (obj *TypeMeta) GroupVersionKind() schema.GroupVersionKind { | ||||
| 	return schema.FromAPIVersionAndKind(obj.APIVersion, obj.Kind) | ||||
| } | ||||
|  | ||||
| func (obj *ListMeta) GetListMeta() List { return obj } | ||||
|   | ||||
| @@ -16,10 +16,14 @@ limitations under the License. | ||||
|  | ||||
| package unversioned | ||||
|  | ||||
| import ( | ||||
| 	"k8s.io/kubernetes/pkg/runtime/schema" | ||||
| ) | ||||
|  | ||||
| // SchemeGroupVersion is group version used to register these objects | ||||
| var SchemeGroupVersion = GroupVersion{Group: "", Version: ""} | ||||
| var SchemeGroupVersion = schema.GroupVersion{Group: "", Version: ""} | ||||
|  | ||||
| // Kind takes an unqualified kind and returns a Group qualified GroupKind | ||||
| func Kind(kind string) GroupKind { | ||||
| func Kind(kind string) schema.GroupKind { | ||||
| 	return SchemeGroupVersion.WithKind(kind).GroupKind() | ||||
| } | ||||
|   | ||||
| @@ -21,8 +21,9 @@ limitations under the License. | ||||
| package unversioned | ||||
|  | ||||
| import ( | ||||
| 	conversion "k8s.io/kubernetes/pkg/conversion" | ||||
| 	time "time" | ||||
|  | ||||
| 	conversion "k8s.io/kubernetes/pkg/conversion" | ||||
| ) | ||||
|  | ||||
| func DeepCopy_unversioned_APIGroup(in interface{}, out interface{}, c *conversion.Cloner) error { | ||||
|   | ||||
							
								
								
									
										58
									
								
								pkg/runtime/schema/generated.pb.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								pkg/runtime/schema/generated.pb.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| /* | ||||
| Copyright 2016 The Kubernetes Authors. | ||||
|  | ||||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | ||||
| You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
| Unless required by applicable law or agreed to in writing, software | ||||
| distributed under the License is distributed on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| See the License for the specific language governing permissions and | ||||
| limitations under the License. | ||||
| */ | ||||
|  | ||||
| // Code generated by protoc-gen-gogo. | ||||
| // source: k8s.io/kubernetes/pkg/runtime/schema/generated.proto | ||||
| // DO NOT EDIT! | ||||
|  | ||||
| /* | ||||
| 	Package schema is a generated protocol buffer package. | ||||
|  | ||||
| 	It is generated from these files: | ||||
| 		k8s.io/kubernetes/pkg/runtime/schema/generated.proto | ||||
|  | ||||
| 	It has these top-level messages: | ||||
| */ | ||||
| package schema | ||||
|  | ||||
| import proto "github.com/gogo/protobuf/proto" | ||||
| import fmt "fmt" | ||||
| import math "math" | ||||
|  | ||||
| // Reference imports to suppress errors if they are not otherwise used. | ||||
| var _ = proto.Marshal | ||||
| var _ = fmt.Errorf | ||||
| var _ = math.Inf | ||||
|  | ||||
| // This is a compile-time assertion to ensure that this generated file | ||||
| // is compatible with the proto package it is being compiled against. | ||||
| const _ = proto.GoGoProtoPackageIsVersion1 | ||||
|  | ||||
| var fileDescriptorGenerated = []byte{ | ||||
| 	// 183 bytes of a gzipped FileDescriptorProto | ||||
| 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x32, 0xc9, 0xb6, 0x28, 0xd6, | ||||
| 	0xcb, 0xcc, 0xd7, 0xcf, 0x2e, 0x4d, 0x4a, 0x2d, 0xca, 0x4b, 0x2d, 0x49, 0x2d, 0xd6, 0x2f, 0xc8, | ||||
| 	0x4e, 0xd7, 0x2f, 0x2a, 0xcd, 0x2b, 0xc9, 0xcc, 0x4d, 0xd5, 0x2f, 0x4e, 0xce, 0x48, 0xcd, 0x4d, | ||||
| 	0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0x4a, 0x2c, 0x49, 0x4d, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, | ||||
| 	0x17, 0x52, 0x81, 0xe8, 0xd2, 0x43, 0xe8, 0xd2, 0x2b, 0xc8, 0x4e, 0xd7, 0x83, 0xea, 0xd2, 0x83, | ||||
| 	0xe8, 0x92, 0xd2, 0x4d, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, | ||||
| 	0x4f, 0xcf, 0xd7, 0x07, 0x6b, 0x4e, 0x2a, 0x4d, 0x03, 0xf3, 0xc0, 0x1c, 0x30, 0x0b, 0x62, 0xa8, | ||||
| 	0x94, 0x21, 0x76, 0xa7, 0x94, 0x96, 0x64, 0xe6, 0xe8, 0x67, 0xe6, 0x95, 0x14, 0x97, 0x14, 0xa1, | ||||
| 	0xbb, 0xc3, 0x49, 0xe3, 0xc4, 0x43, 0x39, 0x86, 0x0b, 0x0f, 0xe5, 0x18, 0x6e, 0x3c, 0x94, 0x63, | ||||
| 	0x68, 0x78, 0x24, 0xc7, 0x78, 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, | ||||
| 	0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x10, 0xc5, 0x06, 0x71, 0x0b, 0x20, 0x00, 0x00, 0xff, 0xff, 0x8d, | ||||
| 	0x74, 0x75, 0xa7, 0xe8, 0x00, 0x00, 0x00, | ||||
| } | ||||
							
								
								
									
										28
									
								
								pkg/runtime/schema/generated.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								pkg/runtime/schema/generated.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| /* | ||||
| Copyright 2016 The Kubernetes Authors. | ||||
|  | ||||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | ||||
| You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
| Unless required by applicable law or agreed to in writing, software | ||||
| distributed under the License is distributed on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| See the License for the specific language governing permissions and | ||||
| limitations under the License. | ||||
| */ | ||||
|  | ||||
|  | ||||
| // This file was autogenerated by go-to-protobuf. Do not edit it manually! | ||||
|  | ||||
| syntax = 'proto2'; | ||||
|  | ||||
| package k8s.io.kubernetes.pkg.runtime.schema; | ||||
|  | ||||
| import "k8s.io/kubernetes/pkg/util/intstr/generated.proto"; | ||||
|  | ||||
| // Package-wide variables from generator "generated". | ||||
| option go_package = "schema"; | ||||
|  | ||||
							
								
								
									
										277
									
								
								pkg/runtime/schema/group_version.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										277
									
								
								pkg/runtime/schema/group_version.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,277 @@ | ||||
| /* | ||||
| Copyright 2015 The Kubernetes Authors. | ||||
|  | ||||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | ||||
| You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
| Unless required by applicable law or agreed to in writing, software | ||||
| distributed under the License is distributed on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| See the License for the specific language governing permissions and | ||||
| limitations under the License. | ||||
| */ | ||||
|  | ||||
| package schema | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| // ParseResourceArg takes the common style of string which may be either `resource.group.com` or `resource.version.group.com` | ||||
| // and parses it out into both possibilities.  This code takes no responsibility for knowing which representation was intended | ||||
| // but with a knowledge of all GroupVersions, calling code can take a very good guess.  If there are only two segments, then | ||||
| // `*GroupVersionResource` is nil. | ||||
| // `resource.group.com` -> `group=com, version=group, resource=resource` and `group=group.com, resource=resource` | ||||
| func ParseResourceArg(arg string) (*GroupVersionResource, GroupResource) { | ||||
| 	var gvr *GroupVersionResource | ||||
| 	if strings.Count(arg, ".") >= 2 { | ||||
| 		s := strings.SplitN(arg, ".", 3) | ||||
| 		gvr = &GroupVersionResource{Group: s[2], Version: s[1], Resource: s[0]} | ||||
| 	} | ||||
|  | ||||
| 	return gvr, ParseGroupResource(arg) | ||||
| } | ||||
|  | ||||
| // GroupResource specifies a Group and a Resource, but does not force a version.  This is useful for identifying | ||||
| // concepts during lookup stages without having partially valid types | ||||
| type GroupResource struct { | ||||
| 	Group    string | ||||
| 	Resource string | ||||
| } | ||||
|  | ||||
| func (gr GroupResource) WithVersion(version string) GroupVersionResource { | ||||
| 	return GroupVersionResource{Group: gr.Group, Version: version, Resource: gr.Resource} | ||||
| } | ||||
|  | ||||
| func (gr GroupResource) Empty() bool { | ||||
| 	return len(gr.Group) == 0 && len(gr.Resource) == 0 | ||||
| } | ||||
|  | ||||
| func (gr *GroupResource) String() string { | ||||
| 	if len(gr.Group) == 0 { | ||||
| 		return gr.Resource | ||||
| 	} | ||||
| 	return gr.Resource + "." + gr.Group | ||||
| } | ||||
|  | ||||
| // ParseGroupResource turns "resource.group" string into a GroupResource struct.  Empty strings are allowed | ||||
| // for each field. | ||||
| func ParseGroupResource(gr string) GroupResource { | ||||
| 	if i := strings.Index(gr, "."); i == -1 { | ||||
| 		return GroupResource{Resource: gr} | ||||
| 	} else { | ||||
| 		return GroupResource{Group: gr[i+1:], Resource: gr[:i]} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // GroupVersionResource unambiguously identifies a resource.  It doesn't anonymously include GroupVersion | ||||
| // to avoid automatic coercion.  It doesn't use a GroupVersion to avoid custom marshalling | ||||
| type GroupVersionResource struct { | ||||
| 	Group    string | ||||
| 	Version  string | ||||
| 	Resource string | ||||
| } | ||||
|  | ||||
| func (gvr GroupVersionResource) Empty() bool { | ||||
| 	return len(gvr.Group) == 0 && len(gvr.Version) == 0 && len(gvr.Resource) == 0 | ||||
| } | ||||
|  | ||||
| func (gvr GroupVersionResource) GroupResource() GroupResource { | ||||
| 	return GroupResource{Group: gvr.Group, Resource: gvr.Resource} | ||||
| } | ||||
|  | ||||
| func (gvr GroupVersionResource) GroupVersion() GroupVersion { | ||||
| 	return GroupVersion{Group: gvr.Group, Version: gvr.Version} | ||||
| } | ||||
|  | ||||
| func (gvr *GroupVersionResource) String() string { | ||||
| 	return strings.Join([]string{gvr.Group, "/", gvr.Version, ", Resource=", gvr.Resource}, "") | ||||
| } | ||||
|  | ||||
| // GroupKind specifies a Group and a Kind, but does not force a version.  This is useful for identifying | ||||
| // concepts during lookup stages without having partially valid types | ||||
| type GroupKind struct { | ||||
| 	Group string | ||||
| 	Kind  string | ||||
| } | ||||
|  | ||||
| func (gk GroupKind) Empty() bool { | ||||
| 	return len(gk.Group) == 0 && len(gk.Kind) == 0 | ||||
| } | ||||
|  | ||||
| func (gk GroupKind) WithVersion(version string) GroupVersionKind { | ||||
| 	return GroupVersionKind{Group: gk.Group, Version: version, Kind: gk.Kind} | ||||
| } | ||||
|  | ||||
| func (gk *GroupKind) String() string { | ||||
| 	if len(gk.Group) == 0 { | ||||
| 		return gk.Kind | ||||
| 	} | ||||
| 	return gk.Kind + "." + gk.Group | ||||
| } | ||||
|  | ||||
| // GroupVersionKind unambiguously identifies a kind.  It doesn't anonymously include GroupVersion | ||||
| // to avoid automatic coercion.  It doesn't use a GroupVersion to avoid custom marshalling | ||||
| type GroupVersionKind struct { | ||||
| 	Group   string | ||||
| 	Version string | ||||
| 	Kind    string | ||||
| } | ||||
|  | ||||
| // Empty returns true if group, version, and kind are empty | ||||
| func (gvk GroupVersionKind) Empty() bool { | ||||
| 	return len(gvk.Group) == 0 && len(gvk.Version) == 0 && len(gvk.Kind) == 0 | ||||
| } | ||||
|  | ||||
| func (gvk GroupVersionKind) GroupKind() GroupKind { | ||||
| 	return GroupKind{Group: gvk.Group, Kind: gvk.Kind} | ||||
| } | ||||
|  | ||||
| func (gvk GroupVersionKind) GroupVersion() GroupVersion { | ||||
| 	return GroupVersion{Group: gvk.Group, Version: gvk.Version} | ||||
| } | ||||
|  | ||||
| func (gvk GroupVersionKind) String() string { | ||||
| 	return gvk.Group + "/" + gvk.Version + ", Kind=" + gvk.Kind | ||||
| } | ||||
|  | ||||
| // GroupVersion contains the "group" and the "version", which uniquely identifies the API. | ||||
| type GroupVersion struct { | ||||
| 	Group   string | ||||
| 	Version string | ||||
| } | ||||
|  | ||||
| // Empty returns true if group and version are empty | ||||
| func (gv GroupVersion) Empty() 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.Empty() { | ||||
| 		return "" | ||||
| 	} | ||||
|  | ||||
| 	// special case of "v1" for backward compatibility | ||||
| 	if len(gv.Group) == 0 && gv.Version == "v1" { | ||||
| 		return gv.Version | ||||
| 	} | ||||
| 	if len(gv.Group) > 0 { | ||||
| 		return gv.Group + "/" + gv.Version | ||||
| 	} | ||||
| 	return gv.Version | ||||
| } | ||||
|  | ||||
| // KindForGroupVersionKinds identifies the preferred GroupVersionKind out of a list. It returns ok false | ||||
| // if none of the options match the group. It prefers a match to group and version over just group. | ||||
| // TODO: Move GroupVersion to a package under pkg/runtime, since it's used by scheme. | ||||
| // TODO: Introduce an adapter type between GroupVersion and runtime.GroupVersioner, and use LegacyCodec(GroupVersion) | ||||
| //   in fewer places. | ||||
| func (gv GroupVersion) KindForGroupVersionKinds(kinds []GroupVersionKind) (target GroupVersionKind, ok bool) { | ||||
| 	for _, gvk := range kinds { | ||||
| 		if gvk.Group == gv.Group && gvk.Version == gv.Version { | ||||
| 			return gvk, true | ||||
| 		} | ||||
| 	} | ||||
| 	for _, gvk := range kinds { | ||||
| 		if gvk.Group == gv.Group { | ||||
| 			return gv.WithKind(gvk.Kind), true | ||||
| 		} | ||||
| 	} | ||||
| 	return GroupVersionKind{}, false | ||||
| } | ||||
|  | ||||
| // 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 | ||||
| 	} | ||||
|  | ||||
| 	switch strings.Count(gv, "/") { | ||||
| 	case 0: | ||||
| 		return GroupVersion{"", gv}, nil | ||||
| 	case 1: | ||||
| 		i := strings.Index(gv, "/") | ||||
| 		return GroupVersion{gv[:i], gv[i+1:]}, nil | ||||
| 	default: | ||||
| 		return GroupVersion{}, fmt.Errorf("unexpected GroupVersion string: %v", gv) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // 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} | ||||
| } | ||||
|  | ||||
| // WithResource creates a GroupVersionResource based on the method receiver's GroupVersion and the passed Resource. | ||||
| func (gv GroupVersion) WithResource(resource string) GroupVersionResource { | ||||
| 	return GroupVersionResource{Group: gv.Group, Version: gv.Version, Resource: resource} | ||||
| } | ||||
|  | ||||
| // GroupVersions can be used to represent a set of desired group versions. | ||||
| // TODO: Move GroupVersions to a package under pkg/runtime, since it's used by scheme. | ||||
| // TODO: Introduce an adapter type between GroupVersions and runtime.GroupVersioner, and use LegacyCodec(GroupVersion) | ||||
| //   in fewer places. | ||||
| type GroupVersions []GroupVersion | ||||
|  | ||||
| // KindForGroupVersionKinds identifies the preferred GroupVersionKind out of a list. It returns ok false | ||||
| // if none of the options match the group. | ||||
| func (gvs GroupVersions) KindForGroupVersionKinds(kinds []GroupVersionKind) (GroupVersionKind, bool) { | ||||
| 	var targets []GroupVersionKind | ||||
| 	for _, gv := range gvs { | ||||
| 		target, ok := gv.KindForGroupVersionKinds(kinds) | ||||
| 		if !ok { | ||||
| 			continue | ||||
| 		} | ||||
| 		targets = append(targets, target) | ||||
| 	} | ||||
| 	if len(targets) == 1 { | ||||
| 		return targets[0], true | ||||
| 	} | ||||
| 	if len(targets) > 1 { | ||||
| 		return bestMatch(kinds, targets), true | ||||
| 	} | ||||
| 	return GroupVersionKind{}, false | ||||
| } | ||||
|  | ||||
| // bestMatch tries to pick best matching GroupVersionKind and falls back to the first | ||||
| // found if no exact match exists. | ||||
| func bestMatch(kinds []GroupVersionKind, targets []GroupVersionKind) GroupVersionKind { | ||||
| 	for _, gvk := range targets { | ||||
| 		for _, k := range kinds { | ||||
| 			if k == gvk { | ||||
| 				return k | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return targets[0] | ||||
| } | ||||
|  | ||||
| // ToAPIVersionAndKind is a convenience method for satisfying runtime.Object on types that | ||||
| // do not use TypeMeta. | ||||
| func (gvk *GroupVersionKind) ToAPIVersionAndKind() (string, string) { | ||||
| 	if gvk == nil { | ||||
| 		return "", "" | ||||
| 	} | ||||
| 	return gvk.GroupVersion().String(), gvk.Kind | ||||
| } | ||||
|  | ||||
| // FromAPIVersionAndKind returns a GVK representing the provided fields for types that | ||||
| // do not use TypeMeta. This method exists to support test types and legacy serializations | ||||
| // that have a distinct group and kind. | ||||
| // TODO: further reduce usage of this method. | ||||
| func FromAPIVersionAndKind(apiVersion, kind string) GroupVersionKind { | ||||
| 	if gv, err := ParseGroupVersion(apiVersion); err == nil { | ||||
| 		return GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: kind} | ||||
| 	} | ||||
| 	return GroupVersionKind{Kind: kind} | ||||
| } | ||||
							
								
								
									
										136
									
								
								pkg/runtime/schema/group_version_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								pkg/runtime/schema/group_version_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,136 @@ | ||||
| /* | ||||
| Copyright 2015 The Kubernetes Authors. | ||||
|  | ||||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | ||||
| You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
| Unless required by applicable law or agreed to in writing, software | ||||
| distributed under the License is distributed on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| See the License for the specific language governing permissions and | ||||
| limitations under the License. | ||||
| */ | ||||
|  | ||||
| package schema | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func TestGroupVersionParse(t *testing.T) { | ||||
| 	tests := []struct { | ||||
| 		input string | ||||
| 		out   GroupVersion | ||||
| 		err   func(error) bool | ||||
| 	}{ | ||||
| 		{input: "v1", out: GroupVersion{Version: "v1"}}, | ||||
| 		{input: "v2", out: GroupVersion{Version: "v2"}}, | ||||
| 		{input: "/v1", out: GroupVersion{Version: "v1"}}, | ||||
| 		{input: "v1/", out: GroupVersion{Group: "v1"}}, | ||||
| 		{input: "/v1/", err: func(err error) bool { return err.Error() == "unexpected GroupVersion string: /v1/" }}, | ||||
| 		{input: "v1/a", out: GroupVersion{Group: "v1", Version: "a"}}, | ||||
| 	} | ||||
| 	for i, test := range tests { | ||||
| 		out, err := ParseGroupVersion(test.input) | ||||
| 		if test.err == nil && err != nil || err == nil && test.err != nil { | ||||
| 			t.Errorf("%d: unexpected error: %v", i, err) | ||||
| 			continue | ||||
| 		} | ||||
| 		if test.err != nil && !test.err(err) { | ||||
| 			t.Errorf("%d: unexpected error: %v", i, err) | ||||
| 			continue | ||||
| 		} | ||||
| 		if out != test.out { | ||||
| 			t.Errorf("%d: unexpected output: %#v", i, out) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestGroupResourceParse(t *testing.T) { | ||||
| 	tests := []struct { | ||||
| 		input string | ||||
| 		out   GroupResource | ||||
| 	}{ | ||||
| 		{input: "v1", out: GroupResource{Resource: "v1"}}, | ||||
| 		{input: ".v1", out: GroupResource{Group: "v1"}}, | ||||
| 		{input: "v1.", out: GroupResource{Resource: "v1"}}, | ||||
| 		{input: "v1.a", out: GroupResource{Group: "a", Resource: "v1"}}, | ||||
| 		{input: "b.v1.a", out: GroupResource{Group: "v1.a", Resource: "b"}}, | ||||
| 	} | ||||
| 	for i, test := range tests { | ||||
| 		out := ParseGroupResource(test.input) | ||||
| 		if out != test.out { | ||||
| 			t.Errorf("%d: unexpected output: %#v", i, out) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestParseResourceArg(t *testing.T) { | ||||
| 	tests := []struct { | ||||
| 		input string | ||||
| 		gvr   *GroupVersionResource | ||||
| 		gr    GroupResource | ||||
| 	}{ | ||||
| 		{input: "v1", gr: GroupResource{Resource: "v1"}}, | ||||
| 		{input: ".v1", gr: GroupResource{Group: "v1"}}, | ||||
| 		{input: "v1.", gr: GroupResource{Resource: "v1"}}, | ||||
| 		{input: "v1.a", gr: GroupResource{Group: "a", Resource: "v1"}}, | ||||
| 		{input: "b.v1.a", gvr: &GroupVersionResource{Group: "a", Version: "v1", Resource: "b"}, gr: GroupResource{Group: "v1.a", Resource: "b"}}, | ||||
| 	} | ||||
| 	for i, test := range tests { | ||||
| 		gvr, gr := ParseResourceArg(test.input) | ||||
| 		if (gvr != nil && test.gvr == nil) || (gvr == nil && test.gvr != nil) || (test.gvr != nil && *gvr != *test.gvr) { | ||||
| 			t.Errorf("%d: unexpected output: %#v", i, gvr) | ||||
| 		} | ||||
| 		if gr != test.gr { | ||||
| 			t.Errorf("%d: unexpected output: %#v", i, gr) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestKindForGroupVersionKinds(t *testing.T) { | ||||
| 	gvks := GroupVersions{ | ||||
| 		GroupVersion{Group: "batch", Version: "v1"}, | ||||
| 		GroupVersion{Group: "batch", Version: "v2alpha1"}, | ||||
| 		GroupVersion{Group: "policy", Version: "v1beta1"}, | ||||
| 	} | ||||
| 	cases := []struct { | ||||
| 		input  []GroupVersionKind | ||||
| 		target GroupVersionKind | ||||
| 		ok     bool | ||||
| 	}{ | ||||
| 		{ | ||||
| 			input:  []GroupVersionKind{{Group: "batch", Version: "v2alpha1", Kind: "ScheduledJob"}}, | ||||
| 			target: GroupVersionKind{Group: "batch", Version: "v2alpha1", Kind: "ScheduledJob"}, | ||||
| 			ok:     true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			input:  []GroupVersionKind{{Group: "batch", Version: "v3alpha1", Kind: "CronJob"}}, | ||||
| 			target: GroupVersionKind{Group: "batch", Version: "v1", Kind: "CronJob"}, | ||||
| 			ok:     true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			input:  []GroupVersionKind{{Group: "policy", Version: "v1beta1", Kind: "PodDisruptionBudget"}}, | ||||
| 			target: GroupVersionKind{Group: "policy", Version: "v1beta1", Kind: "PodDisruptionBudget"}, | ||||
| 			ok:     true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			input:  []GroupVersionKind{{Group: "apps", Version: "v1alpha1", Kind: "StatefulSet"}}, | ||||
| 			target: GroupVersionKind{}, | ||||
| 			ok:     false, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for i, c := range cases { | ||||
| 		target, ok := gvks.KindForGroupVersionKinds(c.input) | ||||
| 		if c.target != target { | ||||
| 			t.Errorf("%d: unexpected target: %v, expected %v", i, target, c.target) | ||||
| 		} | ||||
| 		if c.ok != ok { | ||||
| 			t.Errorf("%d: unexpected ok: %v, expected %v", i, ok, c.ok) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										40
									
								
								pkg/runtime/schema/interfaces.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								pkg/runtime/schema/interfaces.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| /* | ||||
| Copyright 2016 The Kubernetes Authors. | ||||
|  | ||||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | ||||
| You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
| Unless required by applicable law or agreed to in writing, software | ||||
| distributed under the License is distributed on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| See the License for the specific language governing permissions and | ||||
| limitations under the License. | ||||
| */ | ||||
|  | ||||
| package schema | ||||
|  | ||||
| // All objects that are serialized from a Scheme encode their type information. This interface is used | ||||
| // by serialization to set type information from the Scheme onto the serialized version of an object. | ||||
| // For objects that cannot be serialized or have unique requirements, this interface may be a no-op. | ||||
| type ObjectKind interface { | ||||
| 	// SetGroupVersionKind sets or clears the intended serialized kind of an object. Passing kind nil | ||||
| 	// should clear the current setting. | ||||
| 	SetGroupVersionKind(kind GroupVersionKind) | ||||
| 	// GroupVersionKind returns the stored group, version, and kind of an object, or nil if the object does | ||||
| 	// not expose or provide these fields. | ||||
| 	GroupVersionKind() GroupVersionKind | ||||
| } | ||||
|  | ||||
| // EmptyObjectKind implements the ObjectKind interface as a noop | ||||
| var EmptyObjectKind = emptyObjectKind{} | ||||
|  | ||||
| type emptyObjectKind struct{} | ||||
|  | ||||
| // SetGroupVersionKind implements the ObjectKind interface | ||||
| func (emptyObjectKind) SetGroupVersionKind(gvk GroupVersionKind) {} | ||||
|  | ||||
| // GroupVersionKind implements the ObjectKind interface | ||||
| func (emptyObjectKind) GroupVersionKind() GroupVersionKind { return GroupVersionKind{} } | ||||
| @@ -26,9 +26,9 @@ import ( | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
|  | ||||
| 	"k8s.io/client-go/pkg/api/errors" | ||||
| 	"k8s.io/client-go/pkg/api/unversioned" | ||||
| 	"k8s.io/kubernetes/pkg/api/errors" | ||||
| 	"k8s.io/kubernetes/pkg/api/v1" | ||||
| 	"k8s.io/kubernetes/pkg/runtime/schema" | ||||
| 	"k8s.io/kubernetes/pkg/security/apparmor" | ||||
| 	"k8s.io/kubernetes/pkg/watch" | ||||
| 	"k8s.io/kubernetes/test/e2e/framework" | ||||
| @@ -151,7 +151,7 @@ func runAppArmorTest(f *framework.Framework, shouldRun bool, profile string) v1. | ||||
| 		_, err = watch.Until(framework.PodStartTimeout, w, func(e watch.Event) (bool, error) { | ||||
| 			switch e.Type { | ||||
| 			case watch.Deleted: | ||||
| 				return false, errors.NewNotFound(unversioned.GroupResource{Resource: "pods"}, pod.Name) | ||||
| 				return false, errors.NewNotFound(schema.GroupResource{Resource: "pods"}, pod.Name) | ||||
| 			} | ||||
| 			switch t := e.Object.(type) { | ||||
| 			case *v1.Pod: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Clayton Coleman
					Clayton Coleman