mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-03 17:30:00 +00:00
Move GroupVersion* to pkg/runtime/schema
This commit is contained in:
parent
1dfd64f437
commit
a43960da3b
@ -107,7 +107,7 @@ func (g *genFakeForType) GenerateType(c *generator.Context, t *types.Type, w io.
|
|||||||
"groupName": groupName,
|
"groupName": groupName,
|
||||||
"version": g.version,
|
"version": g.version,
|
||||||
"watchInterface": c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/watch", Name: "Interface"}),
|
"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"}),
|
"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"}),
|
"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 pkgAPI = "k8s.io/kubernetes/pkg/api"
|
||||||
const pkgSerializer = "k8s.io/kubernetes/pkg/runtime/serializer"
|
const pkgSerializer = "k8s.io/kubernetes/pkg/runtime/serializer"
|
||||||
const pkgUnversioned = "k8s.io/kubernetes/pkg/api/unversioned"
|
const pkgUnversioned = "k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
|
const pkgSchema = "k8s.io/kubernetes/pkg/runtime/schema"
|
||||||
|
|
||||||
apiPath := func(group string) string {
|
apiPath := func(group string) string {
|
||||||
if len(g.apiPath) > 0 {
|
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"}),
|
"Group": c.Universe.Variable(types.Name{Package: pkgRegistered, Name: "Group"}),
|
||||||
"GroupOrDie": c.Universe.Variable(types.Name{Package: pkgRegistered, Name: "GroupOrDie"}),
|
"GroupOrDie": c.Universe.Variable(types.Name{Package: pkgRegistered, Name: "GroupOrDie"}),
|
||||||
"IsEnabledVersion": c.Universe.Variable(types.Name{Package: pkgRegistered, Name: "IsEnabledVersion"}),
|
"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),
|
"apiPath": apiPath(g.group),
|
||||||
"codecs": c.Universe.Variable(types.Name{Package: pkgAPI, Name: "Codecs"}),
|
"codecs": c.Universe.Variable(types.Name{Package: pkgAPI, Name: "Codecs"}),
|
||||||
"directCodecFactory": c.Universe.Variable(types.Name{Package: pkgSerializer, Name: "DirectCodecFactory"}),
|
"directCodecFactory": c.Universe.Variable(types.Name{Package: pkgSerializer, Name: "DirectCodecFactory"}),
|
||||||
|
@ -62,6 +62,7 @@ func New() *Generator {
|
|||||||
Packages: strings.Join([]string{
|
Packages: strings.Join([]string{
|
||||||
`+k8s.io/kubernetes/pkg/util/intstr`,
|
`+k8s.io/kubernetes/pkg/util/intstr`,
|
||||||
`+k8s.io/kubernetes/pkg/api/resource`,
|
`+k8s.io/kubernetes/pkg/api/resource`,
|
||||||
|
`+k8s.io/kubernetes/pkg/runtime/schema`,
|
||||||
`+k8s.io/kubernetes/pkg/runtime`,
|
`+k8s.io/kubernetes/pkg/runtime`,
|
||||||
`+k8s.io/kubernetes/pkg/watch/versioned`,
|
`+k8s.io/kubernetes/pkg/watch/versioned`,
|
||||||
`k8s.io/kubernetes/pkg/api/unversioned`,
|
`k8s.io/kubernetes/pkg/api/unversioned`,
|
||||||
|
@ -24,13 +24,13 @@ import (
|
|||||||
testgroupetcd "k8s.io/kubernetes/examples/apiserver/rest"
|
testgroupetcd "k8s.io/kubernetes/examples/apiserver/rest"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/rest"
|
"k8s.io/kubernetes/pkg/api/rest"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
|
||||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||||
"k8s.io/kubernetes/pkg/genericapiserver"
|
"k8s.io/kubernetes/pkg/genericapiserver"
|
||||||
"k8s.io/kubernetes/pkg/genericapiserver/authorizer"
|
"k8s.io/kubernetes/pkg/genericapiserver/authorizer"
|
||||||
genericoptions "k8s.io/kubernetes/pkg/genericapiserver/options"
|
genericoptions "k8s.io/kubernetes/pkg/genericapiserver/options"
|
||||||
genericvalidation "k8s.io/kubernetes/pkg/genericapiserver/validation"
|
genericvalidation "k8s.io/kubernetes/pkg/genericapiserver/validation"
|
||||||
"k8s.io/kubernetes/pkg/registry/generic"
|
"k8s.io/kubernetes/pkg/registry/generic"
|
||||||
|
"k8s.io/kubernetes/pkg/runtime/schema"
|
||||||
"k8s.io/kubernetes/pkg/storage/storagebackend"
|
"k8s.io/kubernetes/pkg/storage/storagebackend"
|
||||||
|
|
||||||
// Install the testgroup API
|
// Install the testgroup API
|
||||||
@ -86,7 +86,7 @@ func Run(serverOptions *genericoptions.ServerRunOptions, stopCh <-chan struct{})
|
|||||||
return fmt.Errorf("%v", err)
|
return fmt.Errorf("%v", err)
|
||||||
}
|
}
|
||||||
storageFactory := newStorageFactory()
|
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 {
|
if err != nil {
|
||||||
return fmt.Errorf("Unable to get storage config: %v", err)
|
return fmt.Errorf("Unable to get storage config: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -20,23 +20,10 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"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
|
// 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
|
// concepts during lookup stages without having partially valid types
|
||||||
//
|
//
|
||||||
@ -46,14 +33,6 @@ type GroupResource struct {
|
|||||||
Resource string `protobuf:"bytes,2,opt,name=resource"`
|
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 {
|
func (gr *GroupResource) String() string {
|
||||||
if len(gr.Group) == 0 {
|
if len(gr.Group) == 0 {
|
||||||
return gr.Resource
|
return gr.Resource
|
||||||
@ -61,16 +40,6 @@ func (gr *GroupResource) String() string {
|
|||||||
return gr.Resource + "." + gr.Group
|
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
|
// 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
|
// 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"`
|
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 {
|
func (gvr *GroupVersionResource) String() string {
|
||||||
return strings.Join([]string{gvr.Group, "/", gvr.Version, ", Resource=", gvr.Resource}, "")
|
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"`
|
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 {
|
func (gk *GroupKind) String() string {
|
||||||
if len(gk.Group) == 0 {
|
if len(gk.Group) == 0 {
|
||||||
return gk.Kind
|
return gk.Kind
|
||||||
@ -131,19 +80,6 @@ type GroupVersionKind struct {
|
|||||||
Kind string `protobuf:"bytes,3,opt,name=kind"`
|
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 {
|
func (gvk GroupVersionKind) String() string {
|
||||||
return gvk.Group + "/" + gvk.Version + ", Kind=" + gvk.Kind
|
return gvk.Group + "/" + gvk.Version + ", Kind=" + gvk.Kind
|
||||||
}
|
}
|
||||||
@ -179,55 +115,6 @@ func (gv GroupVersion) String() string {
|
|||||||
return 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}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalJSON implements the json.Marshaller interface.
|
// MarshalJSON implements the json.Marshaller interface.
|
||||||
func (gv GroupVersion) MarshalJSON() ([]byte, error) {
|
func (gv GroupVersion) MarshalJSON() ([]byte, error) {
|
||||||
s := gv.String()
|
s := gv.String()
|
||||||
@ -242,11 +129,11 @@ func (gv *GroupVersion) unmarshal(value []byte) error {
|
|||||||
if err := json.Unmarshal(value, &s); err != nil {
|
if err := json.Unmarshal(value, &s); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
parsed, err := ParseGroupVersion(s)
|
parsed, err := schema.ParseGroupVersion(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*gv = parsed
|
gv.Group, gv.Version = parsed.Group, parsed.Version
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,87 +146,3 @@ func (gv *GroupVersion) UnmarshalJSON(value []byte) error {
|
|||||||
func (gv *GroupVersion) UnmarshalText(value []byte) error {
|
func (gv *GroupVersion) UnmarshalText(value []byte) error {
|
||||||
return gv.unmarshal(value)
|
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"
|
"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 {
|
type GroupVersionHolder struct {
|
||||||
GV GroupVersion `json:"val"`
|
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
|
package unversioned
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/kubernetes/pkg/runtime/schema"
|
||||||
|
)
|
||||||
|
|
||||||
// ListMetaAccessor retrieves the list interface from an object
|
// ListMetaAccessor retrieves the list interface from an object
|
||||||
// TODO: move this, and TypeMeta and ListMeta, to a different package
|
// TODO: move this, and TypeMeta and ListMeta, to a different package
|
||||||
type ListMetaAccessor interface {
|
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) GetSelfLink() string { return meta.SelfLink }
|
||||||
func (meta *ListMeta) SetSelfLink(selfLink string) { meta.SelfLink = 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
|
// 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()
|
obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GroupVersionKind satisfies the ObjectKind interface for all objects that embed TypeMeta
|
// GroupVersionKind satisfies the ObjectKind interface for all objects that embed TypeMeta
|
||||||
func (obj *TypeMeta) GroupVersionKind() GroupVersionKind {
|
func (obj *TypeMeta) GroupVersionKind() schema.GroupVersionKind {
|
||||||
return FromAPIVersionAndKind(obj.APIVersion, obj.Kind)
|
return schema.FromAPIVersionAndKind(obj.APIVersion, obj.Kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (obj *ListMeta) GetListMeta() List { return obj }
|
func (obj *ListMeta) GetListMeta() List { return obj }
|
||||||
|
@ -16,10 +16,14 @@ limitations under the License.
|
|||||||
|
|
||||||
package unversioned
|
package unversioned
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/kubernetes/pkg/runtime/schema"
|
||||||
|
)
|
||||||
|
|
||||||
// SchemeGroupVersion is group version used to register these objects
|
// 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
|
// 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()
|
return SchemeGroupVersion.WithKind(kind).GroupKind()
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,9 @@ limitations under the License.
|
|||||||
package unversioned
|
package unversioned
|
||||||
|
|
||||||
import (
|
import (
|
||||||
conversion "k8s.io/kubernetes/pkg/conversion"
|
|
||||||
time "time"
|
time "time"
|
||||||
|
|
||||||
|
conversion "k8s.io/kubernetes/pkg/conversion"
|
||||||
)
|
)
|
||||||
|
|
||||||
func DeepCopy_unversioned_APIGroup(in interface{}, out interface{}, c *conversion.Cloner) error {
|
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"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"k8s.io/client-go/pkg/api/errors"
|
"k8s.io/kubernetes/pkg/api/errors"
|
||||||
"k8s.io/client-go/pkg/api/unversioned"
|
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
|
"k8s.io/kubernetes/pkg/runtime/schema"
|
||||||
"k8s.io/kubernetes/pkg/security/apparmor"
|
"k8s.io/kubernetes/pkg/security/apparmor"
|
||||||
"k8s.io/kubernetes/pkg/watch"
|
"k8s.io/kubernetes/pkg/watch"
|
||||||
"k8s.io/kubernetes/test/e2e/framework"
|
"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) {
|
_, err = watch.Until(framework.PodStartTimeout, w, func(e watch.Event) (bool, error) {
|
||||||
switch e.Type {
|
switch e.Type {
|
||||||
case watch.Deleted:
|
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) {
|
switch t := e.Object.(type) {
|
||||||
case *v1.Pod:
|
case *v1.Pod:
|
||||||
|
Loading…
Reference in New Issue
Block a user