Fresh dep ensure

This commit is contained in:
Mike Cronce
2018-11-26 13:23:56 -05:00
parent 93cb8a04d7
commit 407478ab9a
9016 changed files with 551394 additions and 279685 deletions

View File

@ -1,72 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = [
"meta_test.go",
"multirestmapper_test.go",
"priority_test.go",
"restmapper_test.go",
],
embed = [":go_default_library"],
deps = [
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"errors.go",
"firsthit_restmapper.go",
"help.go",
"interfaces.go",
"lazy.go",
"meta.go",
"multirestmapper.go",
"priority.go",
"restmapper.go",
"unstructured.go",
],
importpath = "k8s.io/apimachinery/pkg/api/meta",
deps = [
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//staging/src/k8s.io/apimachinery/pkg/api/meta/table:all-srcs",
],
tags = ["automanaged"],
)

View File

@ -23,12 +23,6 @@ import (
"k8s.io/apimachinery/pkg/types"
)
// VersionInterfaces contains the interfaces one should use for dealing with types of a particular version.
type VersionInterfaces struct {
runtime.ObjectConvertor
MetadataAccessor
}
type ListMetaAccessor interface {
GetListMeta() List
}
@ -92,28 +86,19 @@ const (
type RESTScope interface {
// Name of the scope
Name() RESTScopeName
// ParamName is the optional name of the parameter that should be inserted in the resource url
// If empty, no param will be inserted
ParamName() string
// ArgumentName is the optional name that should be used for the variable holding the value.
ArgumentName() string
// ParamDescription is the optional description to use to document the parameter in api documentation
ParamDescription() string
}
// RESTMapping contains the information needed to deal with objects of a specific
// resource and kind in a RESTful manner.
type RESTMapping struct {
// Resource is a string representing the name of this resource as a REST client would see it
Resource string
// Resource is the GroupVersionResource (location) for this endpoint
Resource schema.GroupVersionResource
// GroupVersionKind is the GroupVersionKind (data format) to submit to this endpoint
GroupVersionKind schema.GroupVersionKind
// Scope contains the information needed to deal with REST Resources that are in a resource hierarchy
Scope RESTScope
runtime.ObjectConvertor
MetadataAccessor
}
// RESTMapper allows clients to map resources to kind, and map kind and version

View File

@ -19,27 +19,25 @@ package meta
import (
"sync"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// lazyObject defers loading the mapper and typer until necessary.
type lazyObject struct {
loader func() (RESTMapper, runtime.ObjectTyper, error)
loader func() (RESTMapper, error)
lock sync.Mutex
loaded bool
err error
mapper RESTMapper
typer runtime.ObjectTyper
}
// NewLazyObjectLoader handles unrecoverable errors when creating a RESTMapper / ObjectTyper by
// returning those initialization errors when the interface methods are invoked. This defers the
// initialization and any server calls until a client actually needs to perform the action.
func NewLazyObjectLoader(fn func() (RESTMapper, runtime.ObjectTyper, error)) (RESTMapper, runtime.ObjectTyper) {
func NewLazyRESTMapperLoader(fn func() (RESTMapper, error)) RESTMapper {
obj := &lazyObject{loader: fn}
return obj, obj
return obj
}
// init lazily loads the mapper and typer, returning an error if initialization has failed.
@ -49,13 +47,12 @@ func (o *lazyObject) init() error {
if o.loaded {
return o.err
}
o.mapper, o.typer, o.err = o.loader()
o.mapper, o.err = o.loader()
o.loaded = true
return o.err
}
var _ RESTMapper = &lazyObject{}
var _ runtime.ObjectTyper = &lazyObject{}
func (o *lazyObject) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) {
if err := o.init(); err != nil {
@ -105,17 +102,3 @@ func (o *lazyObject) ResourceSingularizer(resource string) (singular string, err
}
return o.mapper.ResourceSingularizer(resource)
}
func (o *lazyObject) ObjectKinds(obj runtime.Object) ([]schema.GroupVersionKind, bool, error) {
if err := o.init(); err != nil {
return nil, false, err
}
return o.typer.ObjectKinds(obj)
}
func (o *lazyObject) Recognizes(gvk schema.GroupVersionKind) bool {
if err := o.init(); err != nil {
return false
}
return o.typer.Recognizes(gvk)
}

View File

@ -20,7 +20,7 @@ import (
"fmt"
"reflect"
"github.com/golang/glog"
"k8s.io/klog"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
@ -38,7 +38,6 @@ var errNotCommon = fmt.Errorf("object does not implement the common interface fo
// CommonAccessor returns a Common interface for the provided object or an error if the object does
// not provide List.
// TODO: return bool instead of error
func CommonAccessor(obj interface{}) (metav1.Common, error) {
switch t := obj.(type) {
case List:
@ -71,7 +70,6 @@ func CommonAccessor(obj interface{}) (metav1.Common, error) {
// not provide List.
// IMPORTANT: Objects are NOT a superset of lists. Do not use this check to determine whether an
// object *is* a List.
// TODO: return bool instead of error
func ListAccessor(obj interface{}) (List, error) {
switch t := obj.(type) {
case List:
@ -101,7 +99,6 @@ var errNotObject = fmt.Errorf("object does not implement the Object interfaces")
// obj must be a pointer to an API type. An error is returned if the minimum
// required fields are missing. Fields that are not required return the default
// value and are a no-op if set.
// TODO: return bool instead of error
func Accessor(obj interface{}) (metav1.Object, error) {
switch t := obj.(type) {
case metav1.Object:
@ -135,12 +132,12 @@ func AsPartialObjectMetadata(m metav1.Object) *metav1beta1.PartialObjectMetadata
CreationTimestamp: m.GetCreationTimestamp(),
DeletionTimestamp: m.GetDeletionTimestamp(),
DeletionGracePeriodSeconds: m.GetDeletionGracePeriodSeconds(),
Labels: m.GetLabels(),
Annotations: m.GetAnnotations(),
OwnerReferences: m.GetOwnerReferences(),
Finalizers: m.GetFinalizers(),
ClusterName: m.GetClusterName(),
Initializers: m.GetInitializers(),
Labels: m.GetLabels(),
Annotations: m.GetAnnotations(),
OwnerReferences: m.GetOwnerReferences(),
Finalizers: m.GetFinalizers(),
ClusterName: m.GetClusterName(),
Initializers: m.GetInitializers(),
},
}
}
@ -610,7 +607,7 @@ func (a genericAccessor) GetOwnerReferences() []metav1.OwnerReference {
var ret []metav1.OwnerReference
s := a.ownerReferences
if s.Kind() != reflect.Ptr || s.Elem().Kind() != reflect.Slice {
glog.Errorf("expect %v to be a pointer to slice", s)
klog.Errorf("expect %v to be a pointer to slice", s)
return ret
}
s = s.Elem()
@ -618,7 +615,7 @@ func (a genericAccessor) GetOwnerReferences() []metav1.OwnerReference {
ret = make([]metav1.OwnerReference, s.Len(), s.Len()+1)
for i := 0; i < s.Len(); i++ {
if err := extractFromOwnerReference(s.Index(i), &ret[i]); err != nil {
glog.Errorf("extractFromOwnerReference failed: %v", err)
klog.Errorf("extractFromOwnerReference failed: %v", err)
return ret
}
}
@ -628,13 +625,13 @@ func (a genericAccessor) GetOwnerReferences() []metav1.OwnerReference {
func (a genericAccessor) SetOwnerReferences(references []metav1.OwnerReference) {
s := a.ownerReferences
if s.Kind() != reflect.Ptr || s.Elem().Kind() != reflect.Slice {
glog.Errorf("expect %v to be a pointer to slice", s)
klog.Errorf("expect %v to be a pointer to slice", s)
}
s = s.Elem()
newReferences := reflect.MakeSlice(s.Type(), len(references), len(references))
for i := 0; i < len(references); i++ {
if err := setOwnerReference(newReferences.Index(i), &references[i]); err != nil {
glog.Errorf("setOwnerReference failed: %v", err)
klog.Errorf("setOwnerReference failed: %v", err)
return
}
}

View File

@ -54,12 +54,12 @@ func (m PriorityRESTMapper) String() string {
// ResourceFor finds all resources, then passes them through the ResourcePriority patterns to find a single matching hit.
func (m PriorityRESTMapper) ResourceFor(partiallySpecifiedResource schema.GroupVersionResource) (schema.GroupVersionResource, error) {
originalGVRs, err := m.Delegate.ResourcesFor(partiallySpecifiedResource)
if err != nil {
return schema.GroupVersionResource{}, err
originalGVRs, originalErr := m.Delegate.ResourcesFor(partiallySpecifiedResource)
if originalErr != nil && len(originalGVRs) == 0 {
return schema.GroupVersionResource{}, originalErr
}
if len(originalGVRs) == 1 {
return originalGVRs[0], nil
return originalGVRs[0], originalErr
}
remainingGVRs := append([]schema.GroupVersionResource{}, originalGVRs...)
@ -77,7 +77,7 @@ func (m PriorityRESTMapper) ResourceFor(partiallySpecifiedResource schema.GroupV
continue
case 1:
// one match, return
return matchedGVRs[0], nil
return matchedGVRs[0], originalErr
default:
// more than one match, use the matched hits as the list moving to the next pattern.
// this way you can have a series of selection criteria
@ -90,12 +90,12 @@ func (m PriorityRESTMapper) ResourceFor(partiallySpecifiedResource schema.GroupV
// KindFor finds all kinds, then passes them through the KindPriority patterns to find a single matching hit.
func (m PriorityRESTMapper) KindFor(partiallySpecifiedResource schema.GroupVersionResource) (schema.GroupVersionKind, error) {
originalGVKs, err := m.Delegate.KindsFor(partiallySpecifiedResource)
if err != nil {
return schema.GroupVersionKind{}, err
originalGVKs, originalErr := m.Delegate.KindsFor(partiallySpecifiedResource)
if originalErr != nil && len(originalGVKs) == 0 {
return schema.GroupVersionKind{}, originalErr
}
if len(originalGVKs) == 1 {
return originalGVKs[0], nil
return originalGVKs[0], originalErr
}
remainingGVKs := append([]schema.GroupVersionKind{}, originalGVKs...)
@ -113,7 +113,7 @@ func (m PriorityRESTMapper) KindFor(partiallySpecifiedResource schema.GroupVersi
continue
case 1:
// one match, return
return matchedGVKs[0], nil
return matchedGVKs[0], originalErr
default:
// more than one match, use the matched hits as the list moving to the next pattern.
// this way you can have a series of selection criteria
@ -153,9 +153,9 @@ func kindMatches(pattern schema.GroupVersionKind, kind schema.GroupVersionKind)
}
func (m PriorityRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (mapping *RESTMapping, err error) {
mappings, err := m.Delegate.RESTMappings(gk, versions...)
if err != nil {
return nil, err
mappings, originalErr := m.Delegate.RESTMappings(gk, versions...)
if originalErr != nil && len(mappings) == 0 {
return nil, originalErr
}
// any versions the user provides take priority
@ -187,7 +187,7 @@ func (m PriorityRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string)
continue
case 1:
// one match, return
return matching[0], nil
return matching[0], originalErr
default:
// more than one match, use the matched hits as the list moving to the next pattern.
// this way you can have a series of selection criteria
@ -195,7 +195,7 @@ func (m PriorityRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string)
}
}
if len(remaining) == 1 {
return remaining[0], nil
return remaining[0], originalErr
}
var kinds []schema.GroupVersionKind

View File

@ -34,6 +34,30 @@ func TestPriorityRESTMapperResourceForErrorHandling(t *testing.T) {
result schema.GroupVersionResource
err string
}{
{
name: "error",
delegate: fixedRESTMapper{err: errors.New("delegateError")},
err: "delegateError",
},
{
name: "single hit + error",
delegate: fixedRESTMapper{resourcesFor: []schema.GroupVersionResource{{Resource: "single-hit"}}, err: errors.New("delegateError")},
result: schema.GroupVersionResource{Resource: "single-hit"},
err: "delegateError",
},
{
name: "group selection + error",
delegate: fixedRESTMapper{resourcesFor: []schema.GroupVersionResource{
{Group: "one", Version: "a", Resource: "first"},
{Group: "two", Version: "b", Resource: "second"},
}, err: errors.New("delegateError")},
resourcePatterns: []schema.GroupVersionResource{
{Group: "one", Version: AnyVersion, Resource: AnyResource},
},
result: schema.GroupVersionResource{Group: "one", Version: "a", Resource: "first"},
err: "delegateError",
},
{
name: "single hit",
delegate: fixedRESTMapper{resourcesFor: []schema.GroupVersionResource{{Resource: "single-hit"}}},
@ -106,6 +130,10 @@ func TestPriorityRESTMapperResourceForErrorHandling(t *testing.T) {
if len(tc.err) == 0 && actualErr == nil {
continue
}
if len(tc.err) == 0 && actualErr != nil {
t.Errorf("%s: unexpected err: %v", tc.name, actualErr)
continue
}
if len(tc.err) > 0 && actualErr == nil {
t.Errorf("%s: missing expected err: %v", tc.name, tc.err)
continue
@ -125,6 +153,30 @@ func TestPriorityRESTMapperKindForErrorHandling(t *testing.T) {
result schema.GroupVersionKind
err string
}{
{
name: "error",
delegate: fixedRESTMapper{err: errors.New("delegateErr")},
err: "delegateErr",
},
{
name: "single hit + error",
delegate: fixedRESTMapper{kindsFor: []schema.GroupVersionKind{{Kind: "single-hit"}}, err: errors.New("delegateErr")},
result: schema.GroupVersionKind{Kind: "single-hit"},
err: "delegateErr",
},
{
name: "group selection + error",
delegate: fixedRESTMapper{kindsFor: []schema.GroupVersionKind{
{Group: "one", Version: "a", Kind: "first"},
{Group: "two", Version: "b", Kind: "second"},
}, err: errors.New("delegateErr")},
kindPatterns: []schema.GroupVersionKind{
{Group: "one", Version: AnyVersion, Kind: AnyKind},
},
result: schema.GroupVersionKind{Group: "one", Version: "a", Kind: "first"},
err: "delegateErr",
},
{
name: "single hit",
delegate: fixedRESTMapper{kindsFor: []schema.GroupVersionKind{{Kind: "single-hit"}}},
@ -197,6 +249,10 @@ func TestPriorityRESTMapperKindForErrorHandling(t *testing.T) {
if len(tc.err) == 0 && actualErr == nil {
continue
}
if len(tc.err) == 0 && actualErr != nil {
t.Errorf("%s: unexpected err: %v", tc.name, actualErr)
continue
}
if len(tc.err) > 0 && actualErr == nil {
t.Errorf("%s: missing expected err: %v", tc.name, tc.err)
continue
@ -248,6 +304,13 @@ func TestPriorityRESTMapperRESTMapping(t *testing.T) {
input: schema.GroupKind{Kind: "Foo"},
err: errors.New("fail on this"),
},
{
name: "result + error",
mapper: PriorityRESTMapper{Delegate: fixedRESTMapper{mappings: []*RESTMapping{mapping1}, err: errors.New("fail on this")}},
input: schema.GroupKind{Kind: "Foo"},
result: mapping1,
err: errors.New("fail on this"),
},
{
name: "return error for ambiguous",
mapper: PriorityRESTMapper{

View File

@ -28,30 +28,15 @@ import (
// Implements RESTScope interface
type restScope struct {
name RESTScopeName
paramName string
argumentName string
paramDescription string
name RESTScopeName
}
func (r *restScope) Name() RESTScopeName {
return r.name
}
func (r *restScope) ParamName() string {
return r.paramName
}
func (r *restScope) ArgumentName() string {
return r.argumentName
}
func (r *restScope) ParamDescription() string {
return r.paramDescription
}
var RESTScopeNamespace = &restScope{
name: RESTScopeNameNamespace,
paramName: "namespaces",
argumentName: "namespace",
paramDescription: "object name and auth scope, such as for teams and projects",
name: RESTScopeNameNamespace,
}
var RESTScopeRoot = &restScope{
@ -77,8 +62,6 @@ type DefaultRESTMapper struct {
kindToScope map[schema.GroupVersionKind]RESTScope
singularToPlural map[schema.GroupVersionResource]schema.GroupVersionResource
pluralToSingular map[schema.GroupVersionResource]schema.GroupVersionResource
interfacesFunc VersionInterfacesFunc
}
func (m *DefaultRESTMapper) String() string {
@ -87,16 +70,12 @@ func (m *DefaultRESTMapper) String() string {
var _ RESTMapper = &DefaultRESTMapper{}
// VersionInterfacesFunc returns the appropriate typer, and metadata accessor for a
// given api version, or an error if no such api version exists.
type VersionInterfacesFunc func(version schema.GroupVersion) (*VersionInterfaces, error)
// NewDefaultRESTMapper initializes a mapping between Kind and APIVersion
// to a resource name and back based on the objects in a runtime.Scheme
// and the Kubernetes API conventions. Takes a group name, a priority list of the versions
// to search when an object has no default version (set empty to return an error),
// and a function that retrieves the correct metadata for a given version.
func NewDefaultRESTMapper(defaultGroupVersions []schema.GroupVersion, f VersionInterfacesFunc) *DefaultRESTMapper {
func NewDefaultRESTMapper(defaultGroupVersions []schema.GroupVersion) *DefaultRESTMapper {
resourceToKind := make(map[schema.GroupVersionResource]schema.GroupVersionKind)
kindToPluralResource := make(map[schema.GroupVersionKind]schema.GroupVersionResource)
kindToScope := make(map[schema.GroupVersionKind]RESTScope)
@ -111,7 +90,6 @@ func NewDefaultRESTMapper(defaultGroupVersions []schema.GroupVersion, f VersionI
defaultGroupVersions: defaultGroupVersions,
singularToPlural: singularToPlural,
pluralToSingular: pluralToSingular,
interfacesFunc: f,
}
}
@ -526,18 +504,10 @@ func (m *DefaultRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string
return nil, fmt.Errorf("the provided version %q and kind %q cannot be mapped to a supported scope", gvk.GroupVersion(), gvk.Kind)
}
interfaces, err := m.interfacesFunc(gvk.GroupVersion())
if err != nil {
return nil, fmt.Errorf("the provided version %q has no relevant versions: %v", gvk.GroupVersion().String(), err)
}
mappings = append(mappings, &RESTMapping{
Resource: res.Resource,
Resource: res,
GroupVersionKind: gvk,
Scope: scope,
ObjectConvertor: interfaces.ObjectConvertor,
MetadataAccessor: interfaces.MetadataAccessor,
})
}

View File

@ -17,42 +17,13 @@ limitations under the License.
package meta
import (
"errors"
"reflect"
"strings"
"testing"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
type fakeConvertor struct{}
func (fakeConvertor) Convert(in, out, context interface{}) error {
return nil
}
func (fakeConvertor) ConvertToVersion(in runtime.Object, _ runtime.GroupVersioner) (runtime.Object, error) {
return in, nil
}
func (fakeConvertor) ConvertFieldLabel(version, kind, label, value string) (string, string, error) {
return label, value, nil
}
var validAccessor = resourceAccessor{}
var validConvertor = fakeConvertor{}
func fakeInterfaces(version schema.GroupVersion) (*VersionInterfaces, error) {
return &VersionInterfaces{ObjectConvertor: validConvertor, MetadataAccessor: validAccessor}, nil
}
var unmatchedErr = errors.New("no version")
func unmatchedVersionInterfaces(version schema.GroupVersion) (*VersionInterfaces, error) {
return nil, unmatchedErr
}
func TestRESTMapperVersionAndKindForResource(t *testing.T) {
testGroup := "test.group"
testVersion := "test"
@ -71,7 +42,7 @@ func TestRESTMapperVersionAndKindForResource(t *testing.T) {
{Resource: schema.GroupVersionResource{Resource: "internalobjects"}, ExpectedGVK: testGroupVersion.WithKind("InternalObject")},
}
for i, testCase := range testCases {
mapper := NewDefaultRESTMapper([]schema.GroupVersion{testGroupVersion}, fakeInterfaces)
mapper := NewDefaultRESTMapper([]schema.GroupVersion{testGroupVersion})
if len(testCase.ExpectedGVK.Kind) != 0 {
mapper.Add(testCase.ExpectedGVK, RESTScopeNamespace)
}
@ -104,7 +75,7 @@ func TestRESTMapperGroupForResource(t *testing.T) {
{Resource: schema.GroupVersionResource{Resource: "myobje"}, Err: true, GroupVersionKind: schema.GroupVersionKind{Group: "testapi", Version: "test", Kind: "MyObject"}},
}
for i, testCase := range testCases {
mapper := NewDefaultRESTMapper([]schema.GroupVersion{testCase.GroupVersionKind.GroupVersion()}, fakeInterfaces)
mapper := NewDefaultRESTMapper([]schema.GroupVersion{testCase.GroupVersionKind.GroupVersion()})
mapper.Add(testCase.GroupVersionKind, RESTScopeNamespace)
actualGVK, err := mapper.KindFor(testCase.Resource)
@ -249,7 +220,7 @@ func TestRESTMapperKindsFor(t *testing.T) {
}
for _, testCase := range testCases {
tcName := testCase.Name
mapper := NewDefaultRESTMapper(testCase.PreferredOrder, fakeInterfaces)
mapper := NewDefaultRESTMapper(testCase.PreferredOrder)
for _, kind := range testCase.KindsToRegister {
mapper.Add(kind, RESTScopeNamespace)
}
@ -426,7 +397,7 @@ func TestRESTMapperResourcesFor(t *testing.T) {
tcName := testCase.Name
for _, partialResource := range []schema.GroupVersionResource{testCase.PluralPartialResourceToRequest, testCase.SingularPartialResourceToRequest} {
mapper := NewDefaultRESTMapper(testCase.PreferredOrder, fakeInterfaces)
mapper := NewDefaultRESTMapper(testCase.PreferredOrder)
for _, kind := range testCase.KindsToRegister {
mapper.Add(kind, RESTScopeNamespace)
}
@ -511,7 +482,7 @@ func TestRESTMapperResourceSingularizer(t *testing.T) {
{Kind: "lowercases", Plural: "lowercaseses", Singular: "lowercases"},
}
for i, testCase := range testCases {
mapper := NewDefaultRESTMapper([]schema.GroupVersion{testGroupVersion}, fakeInterfaces)
mapper := NewDefaultRESTMapper([]schema.GroupVersion{testGroupVersion})
// create singular/plural mapping
mapper.Add(testGroupVersion.WithKind(testCase.Kind), RESTScopeNamespace)
@ -535,7 +506,7 @@ func TestRESTMapperRESTMapping(t *testing.T) {
APIGroupVersions []schema.GroupVersion
DefaultVersions []schema.GroupVersion
Resource string
Resource schema.GroupVersionResource
ExpectedGroupVersion *schema.GroupVersion
Err bool
}{
@ -544,19 +515,19 @@ func TestRESTMapperRESTMapping(t *testing.T) {
{DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "Unknown", Err: true},
{DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"},
{DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"},
{DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: testGroupVersion.WithResource("internalobjects")},
{DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: testGroupVersion.WithResource("internalobjects")},
{DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"},
{DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: testGroupVersion.WithResource("internalobjects")},
{DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{}, Resource: "internalobjects", ExpectedGroupVersion: &schema.GroupVersion{Group: testGroup, Version: "test"}},
{DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{}, Resource: internalGroupVersion.WithResource("internalobjects"), ExpectedGroupVersion: &schema.GroupVersion{Group: testGroup, Version: "test"}},
{DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"},
{DefaultVersions: []schema.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: testGroupVersion.WithResource("internalobjects")},
// TODO: add test for a resource that exists in one version but not another
}
for i, testCase := range testCases {
mapper := NewDefaultRESTMapper(testCase.DefaultVersions, fakeInterfaces)
mapper := NewDefaultRESTMapper(testCase.DefaultVersions)
mapper.Add(internalGroupVersion.WithKind("InternalObject"), RESTScopeNamespace)
preferredVersions := []string{}
@ -577,10 +548,6 @@ func TestRESTMapperRESTMapping(t *testing.T) {
t.Errorf("%d: unexpected resource: %#v", i, mapping)
}
if mapping.MetadataAccessor == nil || mapping.ObjectConvertor == nil {
t.Errorf("%d: missing codec and accessor: %#v", i, mapping)
}
groupVersion := testCase.ExpectedGroupVersion
if groupVersion == nil {
groupVersion = &testCase.APIGroupVersions[0]
@ -599,7 +566,7 @@ func TestRESTMapperRESTMappingSelectsVersion(t *testing.T) {
internalObjectGK := schema.GroupKind{Group: "tgroup", Kind: "InternalObject"}
otherObjectGK := schema.GroupKind{Group: "tgroup", Kind: "OtherObject"}
mapper := NewDefaultRESTMapper([]schema.GroupVersion{expectedGroupVersion1, expectedGroupVersion2}, fakeInterfaces)
mapper := NewDefaultRESTMapper([]schema.GroupVersion{expectedGroupVersion1, expectedGroupVersion2})
mapper.Add(expectedGroupVersion1.WithKind("InternalObject"), RESTScopeNamespace)
mapper.Add(expectedGroupVersion2.WithKind("OtherObject"), RESTScopeNamespace)
@ -608,7 +575,7 @@ func TestRESTMapperRESTMappingSelectsVersion(t *testing.T) {
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if mapping.Resource != "otherobjects" || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion2 {
if mapping.Resource != expectedGroupVersion2.WithResource("otherobjects") || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion2 {
t.Errorf("unexpected mapping: %#v", mapping)
}
@ -616,7 +583,7 @@ func TestRESTMapperRESTMappingSelectsVersion(t *testing.T) {
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if mapping.Resource != "internalobjects" || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion1 {
if mapping.Resource != expectedGroupVersion1.WithResource("internalobjects") || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion1 {
t.Errorf("unexpected mapping: %#v", mapping)
}
@ -646,7 +613,7 @@ func TestRESTMapperRESTMappingSelectsVersion(t *testing.T) {
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if mapping.Resource != "otherobjects" || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion2 {
if mapping.Resource != expectedGroupVersion2.WithResource("otherobjects") || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion2 {
t.Errorf("unexpected mapping: %#v", mapping)
}
}
@ -678,7 +645,7 @@ func TestRESTMapperRESTMappings(t *testing.T) {
Kind: "InternalObject",
APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "v2"}},
AddGroupVersionKind: []schema.GroupVersionKind{schema.GroupVersion{Group: testGroup, Version: "v2"}.WithKind("InternalObject")},
ExpectedRESTMappings: []*RESTMapping{{Resource: "internalobjects", GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v2", Kind: "InternalObject"}}},
ExpectedRESTMappings: []*RESTMapping{{Resource: schema.GroupVersionResource{Group: testGroup, Version: "v2", Resource: "internalobjects"}, GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v2", Kind: "InternalObject"}}},
},
// ask for specific versions - only one available - check ExpectedRESTMappings
@ -687,20 +654,29 @@ func TestRESTMapperRESTMappings(t *testing.T) {
Kind: "InternalObject",
APIGroupVersions: []schema.GroupVersion{{Group: testGroup, Version: "v3"}, {Group: testGroup, Version: "v2"}},
AddGroupVersionKind: []schema.GroupVersionKind{schema.GroupVersion{Group: testGroup, Version: "v2"}.WithKind("InternalObject")},
ExpectedRESTMappings: []*RESTMapping{{Resource: "internalobjects", GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v2", Kind: "InternalObject"}}},
ExpectedRESTMappings: []*RESTMapping{{Resource: schema.GroupVersionResource{Group: testGroup, Version: "v2", Resource: "internalobjects"}, GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v2", Kind: "InternalObject"}}},
},
// do not ask for specific version - search through default versions - check ExpectedRESTMappings
{
DefaultVersions: []schema.GroupVersion{testGroupVersion, {Group: testGroup, Version: "v2"}},
Kind: "InternalObject",
AddGroupVersionKind: []schema.GroupVersionKind{schema.GroupVersion{Group: testGroup, Version: "v1"}.WithKind("InternalObject"), schema.GroupVersion{Group: testGroup, Version: "v2"}.WithKind("InternalObject")},
ExpectedRESTMappings: []*RESTMapping{{Resource: "internalobjects", GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v1", Kind: "InternalObject"}}, {Resource: "internalobjects", GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v2", Kind: "InternalObject"}}},
DefaultVersions: []schema.GroupVersion{testGroupVersion, {Group: testGroup, Version: "v2"}},
Kind: "InternalObject",
AddGroupVersionKind: []schema.GroupVersionKind{schema.GroupVersion{Group: testGroup, Version: "v1"}.WithKind("InternalObject"), schema.GroupVersion{Group: testGroup, Version: "v2"}.WithKind("InternalObject")},
ExpectedRESTMappings: []*RESTMapping{
{
Resource: schema.GroupVersionResource{Group: testGroup, Version: "v1", Resource: "internalobjects"},
GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v1", Kind: "InternalObject"},
},
{
Resource: schema.GroupVersionResource{Group: testGroup, Version: "v2", Resource: "internalobjects"},
GroupVersionKind: schema.GroupVersionKind{Group: testGroup, Version: "v2", Kind: "InternalObject"},
},
},
},
}
for i, testCase := range testCases {
mapper := NewDefaultRESTMapper(testCase.DefaultVersions, fakeInterfaces)
mapper := NewDefaultRESTMapper(testCase.DefaultVersions)
for _, gvk := range testCase.AddGroupVersionKind {
mapper.Add(gvk, RESTScopeNamespace)
}
@ -727,9 +703,6 @@ func TestRESTMapperRESTMappings(t *testing.T) {
if mapping.Resource != exp.Resource {
t.Errorf("%d - %d: unexpected resource: %#v", i, j, mapping)
}
if mapping.MetadataAccessor == nil || mapping.ObjectConvertor == nil {
t.Errorf("%d - %d: missing codec and accessor: %#v", i, j, mapping)
}
if mapping.GroupVersionKind != exp.GroupVersionKind {
t.Errorf("%d - %d: unexpected GroupVersionKind: %#v", i, j, mapping)
}
@ -742,9 +715,9 @@ func TestRESTMapperReportsErrorOnBadVersion(t *testing.T) {
expectedGroupVersion2 := schema.GroupVersion{Group: "tgroup", Version: "test2"}
internalObjectGK := schema.GroupKind{Group: "tgroup", Kind: "InternalObject"}
mapper := NewDefaultRESTMapper([]schema.GroupVersion{expectedGroupVersion1, expectedGroupVersion2}, unmatchedVersionInterfaces)
mapper := NewDefaultRESTMapper([]schema.GroupVersion{expectedGroupVersion1, expectedGroupVersion2})
mapper.Add(expectedGroupVersion1.WithKind("InternalObject"), RESTScopeNamespace)
_, err := mapper.RESTMapping(internalObjectGK, expectedGroupVersion1.Version)
_, err := mapper.RESTMapping(internalObjectGK, "test3")
if err == nil {
t.Errorf("unexpected non-error")
}

View File

@ -1,29 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["table.go"],
importpath = "k8s.io/apimachinery/pkg/api/meta/table",
visibility = ["//visibility:public"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/duration:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -53,7 +53,7 @@ func MetaToTableRow(obj runtime.Object, rowFn func(obj runtime.Object, m metav1.
row := metav1beta1.TableRow{
Object: runtime.RawExtension{Object: obj},
}
row.Cells, err = rowFn(obj, m, m.GetName(), translateTimestamp(m.GetCreationTimestamp()))
row.Cells, err = rowFn(obj, m, m.GetName(), ConvertToHumanReadableDateType(m.GetCreationTimestamp()))
if err != nil {
return nil, err
}
@ -61,9 +61,9 @@ func MetaToTableRow(obj runtime.Object, rowFn func(obj runtime.Object, m metav1.
return rows, nil
}
// translateTimestamp returns the elapsed time since timestamp in
// ConvertToHumanReadableDateType returns the elapsed time since timestamp in
// human-readable approximation.
func translateTimestamp(timestamp metav1.Time) string {
func ConvertToHumanReadableDateType(timestamp metav1.Time) string {
if timestamp.IsZero() {
return "<unknown>"
}

View File

@ -0,0 +1,171 @@
/*
Copyright 2018 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 testrestmapper
import (
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets"
)
// TestOnlyStaticRESTMapper returns a union RESTMapper of all known types with priorities chosen in the following order:
// 1. legacy kube group preferred version, extensions preferred version, metrics preferred version, legacy
// kube any version, extensions any version, metrics any version, all other groups alphabetical preferred version,
// all other groups alphabetical.
// TODO callers of this method should be updated to build their own specific restmapper based on their scheme for their tests
// TODO the things being tested are related to whether various cases are handled, not tied to the particular types being checked.
func TestOnlyStaticRESTMapper(scheme *runtime.Scheme, versionPatterns ...schema.GroupVersion) meta.RESTMapper {
unionMapper := meta.MultiRESTMapper{}
unionedGroups := sets.NewString()
for _, enabledVersion := range scheme.PrioritizedVersionsAllGroups() {
if !unionedGroups.Has(enabledVersion.Group) {
unionedGroups.Insert(enabledVersion.Group)
unionMapper = append(unionMapper, newRESTMapper(enabledVersion.Group, scheme))
}
}
if len(versionPatterns) != 0 {
resourcePriority := []schema.GroupVersionResource{}
kindPriority := []schema.GroupVersionKind{}
for _, versionPriority := range versionPatterns {
resourcePriority = append(resourcePriority, versionPriority.WithResource(meta.AnyResource))
kindPriority = append(kindPriority, versionPriority.WithKind(meta.AnyKind))
}
return meta.PriorityRESTMapper{Delegate: unionMapper, ResourcePriority: resourcePriority, KindPriority: kindPriority}
}
prioritizedGroups := []string{"", "extensions", "metrics"}
resourcePriority, kindPriority := prioritiesForGroups(scheme, prioritizedGroups...)
prioritizedGroupsSet := sets.NewString(prioritizedGroups...)
remainingGroups := sets.String{}
for _, enabledVersion := range scheme.PrioritizedVersionsAllGroups() {
if !prioritizedGroupsSet.Has(enabledVersion.Group) {
remainingGroups.Insert(enabledVersion.Group)
}
}
remainingResourcePriority, remainingKindPriority := prioritiesForGroups(scheme, remainingGroups.List()...)
resourcePriority = append(resourcePriority, remainingResourcePriority...)
kindPriority = append(kindPriority, remainingKindPriority...)
return meta.PriorityRESTMapper{Delegate: unionMapper, ResourcePriority: resourcePriority, KindPriority: kindPriority}
}
// prioritiesForGroups returns the resource and kind priorities for a PriorityRESTMapper, preferring the preferred version of each group first,
// then any non-preferred version of the group second.
func prioritiesForGroups(scheme *runtime.Scheme, groups ...string) ([]schema.GroupVersionResource, []schema.GroupVersionKind) {
resourcePriority := []schema.GroupVersionResource{}
kindPriority := []schema.GroupVersionKind{}
for _, group := range groups {
availableVersions := scheme.PrioritizedVersionsForGroup(group)
if len(availableVersions) > 0 {
resourcePriority = append(resourcePriority, availableVersions[0].WithResource(meta.AnyResource))
kindPriority = append(kindPriority, availableVersions[0].WithKind(meta.AnyKind))
}
}
for _, group := range groups {
resourcePriority = append(resourcePriority, schema.GroupVersionResource{Group: group, Version: meta.AnyVersion, Resource: meta.AnyResource})
kindPriority = append(kindPriority, schema.GroupVersionKind{Group: group, Version: meta.AnyVersion, Kind: meta.AnyKind})
}
return resourcePriority, kindPriority
}
func newRESTMapper(group string, scheme *runtime.Scheme) meta.RESTMapper {
mapper := meta.NewDefaultRESTMapper(scheme.PrioritizedVersionsForGroup(group))
for _, gv := range scheme.PrioritizedVersionsForGroup(group) {
for kind := range scheme.KnownTypes(gv) {
if ignoredKinds.Has(kind) {
continue
}
scope := meta.RESTScopeNamespace
if rootScopedKinds[gv.WithKind(kind).GroupKind()] {
scope = meta.RESTScopeRoot
}
mapper.Add(gv.WithKind(kind), scope)
}
}
return mapper
}
// hardcoded is good enough for the test we're running
var rootScopedKinds = map[schema.GroupKind]bool{
{Group: "admission.k8s.io", Kind: "AdmissionReview"}: true,
{Group: "admissionregistration.k8s.io", Kind: "InitializerConfiguration"}: true,
{Group: "admissionregistration.k8s.io", Kind: "ValidatingWebhookConfiguration"}: true,
{Group: "admissionregistration.k8s.io", Kind: "MutatingWebhookConfiguration"}: true,
{Group: "authentication.k8s.io", Kind: "TokenReview"}: true,
{Group: "authorization.k8s.io", Kind: "SubjectAccessReview"}: true,
{Group: "authorization.k8s.io", Kind: "SelfSubjectAccessReview"}: true,
{Group: "authorization.k8s.io", Kind: "SelfSubjectRulesReview"}: true,
{Group: "certificates.k8s.io", Kind: "CertificateSigningRequest"}: true,
{Group: "", Kind: "Node"}: true,
{Group: "", Kind: "Namespace"}: true,
{Group: "", Kind: "PersistentVolume"}: true,
{Group: "", Kind: "ComponentStatus"}: true,
{Group: "extensions", Kind: "PodSecurityPolicy"}: true,
{Group: "policy", Kind: "PodSecurityPolicy"}: true,
{Group: "extensions", Kind: "PodSecurityPolicy"}: true,
{Group: "rbac.authorization.k8s.io", Kind: "ClusterRole"}: true,
{Group: "rbac.authorization.k8s.io", Kind: "ClusterRoleBinding"}: true,
{Group: "scheduling.k8s.io", Kind: "PriorityClass"}: true,
{Group: "storage.k8s.io", Kind: "StorageClass"}: true,
{Group: "storage.k8s.io", Kind: "VolumeAttachment"}: true,
{Group: "apiextensions.k8s.io", Kind: "CustomResourceDefinition"}: true,
{Group: "apiserver.k8s.io", Kind: "AdmissionConfiguration"}: true,
{Group: "audit.k8s.io", Kind: "Event"}: true,
{Group: "audit.k8s.io", Kind: "Policy"}: true,
{Group: "apiregistration.k8s.io", Kind: "APIService"}: true,
{Group: "metrics.k8s.io", Kind: "NodeMetrics"}: true,
{Group: "wardle.k8s.io", Kind: "Fischer"}: true,
}
// hardcoded is good enough for the test we're running
var ignoredKinds = sets.NewString(
"ListOptions",
"DeleteOptions",
"Status",
"PodLogOptions",
"PodExecOptions",
"PodAttachOptions",
"PodPortForwardOptions",
"PodProxyOptions",
"NodeProxyOptions",
"ServiceProxyOptions",
)

View File

@ -1,47 +0,0 @@
/*
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 meta
import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// InterfacesForUnstructuredConversion returns VersionInterfaces suitable for
// dealing with unstructured.Unstructured objects and supports conversion
// from typed objects (provided by parent) to untyped objects.
func InterfacesForUnstructuredConversion(parent VersionInterfacesFunc) VersionInterfacesFunc {
return func(version schema.GroupVersion) (*VersionInterfaces, error) {
if i, err := parent(version); err == nil {
return &VersionInterfaces{
ObjectConvertor: i.ObjectConvertor,
MetadataAccessor: NewAccessor(),
}, nil
}
return InterfacesForUnstructured(version)
}
}
// InterfacesForUnstructured returns VersionInterfaces suitable for
// dealing with unstructured.Unstructured objects. It will return errors for
// other conversions.
func InterfacesForUnstructured(schema.GroupVersion) (*VersionInterfaces, error) {
return &VersionInterfaces{
ObjectConvertor: &unstructured.UnstructuredObjectConverter{},
MetadataAccessor: NewAccessor(),
}, nil
}