Merge pull request #63206 from deads2k/api-11-restmapper

Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

remove incorrect static restmapper from type registry

A RESTMapping can only be determined by inspecting a server since discovery is the authoritative source of mapping decisions.  This removes a deceptive method from the type registry and makes the old logic available for existing tests in a separate, clearly labeled package.

@kubernetes/sig-api-machinery-pr-reviews @kubernetes/sig-cli-maintainers 

```release-note
NONE
```
This commit is contained in:
Kubernetes Submit Queue 2018-05-01 08:10:37 -07:00 committed by GitHub
commit f03f83a20a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
71 changed files with 457 additions and 483 deletions

View File

@ -48,7 +48,6 @@ go_library(
"//pkg/apis/settings/install:go_default_library", "//pkg/apis/settings/install:go_default_library",
"//pkg/apis/storage:go_default_library", "//pkg/apis/storage:go_default_library",
"//pkg/apis/storage/install:go_default_library", "//pkg/apis/storage/install:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime: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/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/recognizer:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/recognizer:go_default_library",

View File

@ -30,7 +30,6 @@ import (
"reflect" "reflect"
"strings" "strings"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer/recognizer" "k8s.io/apimachinery/pkg/runtime/serializer/recognizer"
@ -473,51 +472,3 @@ func (g TestGroup) SubResourcePath(resource, namespace, name, sub string) string
return path return path
} }
// RESTMapper returns RESTMapper in legacyscheme.Registry.
func (g TestGroup) RESTMapper() meta.RESTMapper {
return legacyscheme.Registry.RESTMapper()
}
// ExternalGroupVersions returns all external group versions allowed for the server.
func ExternalGroupVersions() schema.GroupVersions {
versions := []schema.GroupVersion{}
for _, g := range Groups {
gv := g.GroupVersion()
versions = append(versions, *gv)
}
return versions
}
// GetCodecForObject gets codec based on runtime.Object
func GetCodecForObject(obj runtime.Object) (runtime.Codec, error) {
kinds, _, err := legacyscheme.Scheme.ObjectKinds(obj)
if err != nil {
return nil, fmt.Errorf("unexpected encoding error: %v", err)
}
kind := kinds[0]
for _, group := range Groups {
if group.GroupVersion().Group != kind.Group {
continue
}
if legacyscheme.Scheme.Recognizes(kind) {
return group.Codec(), nil
}
}
// Codec used for unversioned types
if legacyscheme.Scheme.Recognizes(kind) {
serializer, ok := runtime.SerializerInfoForMediaType(legacyscheme.Codecs.SupportedMediaTypes(), runtime.ContentTypeJSON)
if !ok {
return nil, fmt.Errorf("no serializer registered for json")
}
return serializer.Serializer, nil
}
return nil, fmt.Errorf("unexpected kind: %v", kind)
}
// NewTestGroup creates a new TestGroup.
func NewTestGroup(external, internal schema.GroupVersion, internalTypes map[string]reflect.Type, externalTypes map[string]reflect.Type) TestGroup {
return TestGroup{external, internal, internalTypes, externalTypes}
}

View File

@ -31,7 +31,6 @@ go_test(
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//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/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
], ],
) )

View File

@ -45,18 +45,6 @@ func Install(registry *registered.APIRegistrationManager, scheme *runtime.Scheme
"PersistentVolume", "PersistentVolume",
"ComponentStatus", "ComponentStatus",
), ),
IgnoredKinds: sets.NewString(
"ListOptions",
"DeleteOptions",
"Status",
"PodLogOptions",
"PodExecOptions",
"PodAttachOptions",
"PodPortForwardOptions",
"PodProxyOptions",
"NodeProxyOptions",
"ServiceProxyOptions",
),
}, },
announced.VersionToSchemeFunc{ announced.VersionToSchemeFunc{
v1.SchemeGroupVersion.Version: v1.AddToScheme, v1.SchemeGroupVersion.Version: v1.AddToScheme,

View File

@ -24,7 +24,6 @@ import (
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/legacyscheme"
internal "k8s.io/kubernetes/pkg/apis/core" internal "k8s.io/kubernetes/pkg/apis/core"
) )
@ -66,43 +65,6 @@ func TestCodec(t *testing.T) {
} }
} }
func TestRESTMapper(t *testing.T) {
gv := schema.GroupVersion{Group: "", Version: "v1"}
rcGVK := gv.WithKind("ReplicationController")
podTemplateGVK := gv.WithKind("PodTemplate")
if gvk, err := legacyscheme.Registry.RESTMapper().KindFor(internal.SchemeGroupVersion.WithResource("replicationcontrollers")); err != nil || gvk != rcGVK {
t.Errorf("unexpected version mapping: %v %v", gvk, err)
}
if m, err := legacyscheme.Registry.GroupOrDie(internal.GroupName).RESTMapper.RESTMapping(podTemplateGVK.GroupKind(), ""); err != nil || m.GroupVersionKind != podTemplateGVK || m.Resource != "podtemplates" {
t.Errorf("unexpected version mapping: %#v %v", m, err)
}
for _, version := range legacyscheme.Registry.GroupOrDie(internal.GroupName).GroupVersions {
mapping, err := legacyscheme.Registry.GroupOrDie(internal.GroupName).RESTMapper.RESTMapping(rcGVK.GroupKind(), version.Version)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if mapping.Resource != "replicationControllers" && mapping.Resource != "replicationcontrollers" {
t.Errorf("incorrect resource name: %#v", mapping)
}
if mapping.GroupVersionKind.GroupVersion() != version {
t.Errorf("incorrect version: %v", mapping)
}
rc := &internal.ReplicationController{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}
name, err := meta.NewAccessor().Name(rc)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if name != "foo" {
t.Errorf("bad name: %q", name)
}
}
}
func TestUnversioned(t *testing.T) { func TestUnversioned(t *testing.T) {
for _, obj := range []runtime.Object{ for _, obj := range []runtime.Object{
&metav1.Status{}, &metav1.Status{},

View File

@ -14,7 +14,6 @@ go_library(
importpath = "k8s.io/kubernetes/pkg/apis/core/validation", importpath = "k8s.io/kubernetes/pkg/apis/core/validation",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
"//pkg/api/legacyscheme:go_default_library",
"//pkg/api/service:go_default_library", "//pkg/api/service:go_default_library",
"//pkg/apis/core:go_default_library", "//pkg/apis/core:go_default_library",
"//pkg/apis/core/helper:go_default_library", "//pkg/apis/core/helper:go_default_library",
@ -29,13 +28,11 @@ go_library(
"//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",

View File

@ -20,12 +20,9 @@ import (
"fmt" "fmt"
"time" "time"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/core"
) )
@ -90,40 +87,8 @@ func ValidateEvent(event *core.Event) field.ErrorList {
} }
} }
// For kinds we recognize, make sure InvolvedObject.Namespace is set for namespaced kinds
if namespaced, err := isNamespacedKind(event.InvolvedObject.Kind, event.InvolvedObject.APIVersion); err == nil {
if namespaced && len(event.InvolvedObject.Namespace) == 0 {
allErrs = append(allErrs, field.Required(field.NewPath("involvedObject", "namespace"), fmt.Sprintf("required for kind %s", event.InvolvedObject.Kind)))
}
if !namespaced && len(event.InvolvedObject.Namespace) > 0 {
allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "namespace"), event.InvolvedObject.Namespace, fmt.Sprintf("not allowed for kind %s", event.InvolvedObject.Kind)))
}
}
for _, msg := range validation.IsDNS1123Subdomain(event.Namespace) { for _, msg := range validation.IsDNS1123Subdomain(event.Namespace) {
allErrs = append(allErrs, field.Invalid(field.NewPath("namespace"), event.Namespace, msg)) allErrs = append(allErrs, field.Invalid(field.NewPath("namespace"), event.Namespace, msg))
} }
return allErrs return allErrs
} }
// Check whether the kind in groupVersion is scoped at the root of the api hierarchy
func isNamespacedKind(kind, groupVersion string) (bool, error) {
gv, err := schema.ParseGroupVersion(groupVersion)
if err != nil {
return false, err
}
g, err := legacyscheme.Registry.Group(gv.Group)
if err != nil {
return false, err
}
restMapping, err := g.RESTMapper.RESTMapping(schema.GroupKind{Group: gv.Group, Kind: kind}, gv.Version)
if err != nil {
return false, err
}
scopeName := restMapping.Scope.Name()
if scopeName == meta.RESTScopeNameNamespace {
return true, nil
}
return false, nil
}

View File

@ -58,6 +58,7 @@ go_test(
"//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",

View File

@ -32,6 +32,7 @@ import (
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/api/meta/testrestmapper"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apimachinery/pkg/runtime/serializer"
@ -60,7 +61,7 @@ func TestGarbageCollectorConstruction(t *testing.T) {
config := &restclient.Config{} config := &restclient.Config{}
config.ContentConfig.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: metaonly.NewMetadataCodecFactory()} config.ContentConfig.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: metaonly.NewMetadataCodecFactory()}
tweakableRM := meta.NewDefaultRESTMapper(nil) tweakableRM := meta.NewDefaultRESTMapper(nil)
rm := &testRESTMapper{meta.MultiRESTMapper{tweakableRM, legacyscheme.Registry.RESTMapper()}} rm := &testRESTMapper{meta.MultiRESTMapper{tweakableRM, testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme)}}
metaOnlyClientPool := dynamic.NewClientPool(config, rm, dynamic.LegacyAPIPathResolverFunc) metaOnlyClientPool := dynamic.NewClientPool(config, rm, dynamic.LegacyAPIPathResolverFunc)
config.ContentConfig.NegotiatedSerializer = nil config.ContentConfig.NegotiatedSerializer = nil
clientPool := dynamic.NewClientPool(config, rm, dynamic.LegacyAPIPathResolverFunc) clientPool := dynamic.NewClientPool(config, rm, dynamic.LegacyAPIPathResolverFunc)
@ -190,15 +191,15 @@ type garbageCollector struct {
func setupGC(t *testing.T, config *restclient.Config) garbageCollector { func setupGC(t *testing.T, config *restclient.Config) garbageCollector {
config.ContentConfig.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: metaonly.NewMetadataCodecFactory()} config.ContentConfig.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: metaonly.NewMetadataCodecFactory()}
metaOnlyClientPool := dynamic.NewClientPool(config, legacyscheme.Registry.RESTMapper(), dynamic.LegacyAPIPathResolverFunc) metaOnlyClientPool := dynamic.NewClientPool(config, testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme), dynamic.LegacyAPIPathResolverFunc)
config.ContentConfig.NegotiatedSerializer = nil config.ContentConfig.NegotiatedSerializer = nil
clientPool := dynamic.NewClientPool(config, legacyscheme.Registry.RESTMapper(), dynamic.LegacyAPIPathResolverFunc) clientPool := dynamic.NewClientPool(config, testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme), dynamic.LegacyAPIPathResolverFunc)
podResource := map[schema.GroupVersionResource]struct{}{{Version: "v1", Resource: "pods"}: {}} podResource := map[schema.GroupVersionResource]struct{}{{Version: "v1", Resource: "pods"}: {}}
client := fake.NewSimpleClientset() client := fake.NewSimpleClientset()
sharedInformers := informers.NewSharedInformerFactory(client, 0) sharedInformers := informers.NewSharedInformerFactory(client, 0)
alwaysStarted := make(chan struct{}) alwaysStarted := make(chan struct{})
close(alwaysStarted) close(alwaysStarted)
gc, err := NewGarbageCollector(metaOnlyClientPool, clientPool, &testRESTMapper{legacyscheme.Registry.RESTMapper()}, podResource, ignoredResources, sharedInformers, alwaysStarted) gc, err := NewGarbageCollector(metaOnlyClientPool, clientPool, &testRESTMapper{testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme)}, podResource, ignoredResources, sharedInformers, alwaysStarted)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -433,7 +434,7 @@ func TestGCListWatcher(t *testing.T) {
testHandler := &fakeActionHandler{} testHandler := &fakeActionHandler{}
srv, clientConfig := testServerAndClientConfig(testHandler.ServeHTTP) srv, clientConfig := testServerAndClientConfig(testHandler.ServeHTTP)
defer srv.Close() defer srv.Close()
clientPool := dynamic.NewClientPool(clientConfig, legacyscheme.Registry.RESTMapper(), dynamic.LegacyAPIPathResolverFunc) clientPool := dynamic.NewClientPool(clientConfig, testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme), dynamic.LegacyAPIPathResolverFunc)
podResource := schema.GroupVersionResource{Version: "v1", Resource: "pods"} podResource := schema.GroupVersionResource{Version: "v1", Resource: "pods"}
client, err := clientPool.ClientForGroupVersionResource(podResource) client, err := clientPool.ClientForGroupVersionResource(podResource)
if err != nil { if err != nil {
@ -822,7 +823,7 @@ func TestGarbageCollectorSync(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
rm := &testRESTMapper{legacyscheme.Registry.RESTMapper()} rm := &testRESTMapper{testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme)}
metaOnlyClientPool := dynamic.NewClientPool(clientConfig, rm, dynamic.LegacyAPIPathResolverFunc) metaOnlyClientPool := dynamic.NewClientPool(clientConfig, rm, dynamic.LegacyAPIPathResolverFunc)
clientPool := dynamic.NewClientPool(clientConfig, rm, dynamic.LegacyAPIPathResolverFunc) clientPool := dynamic.NewClientPool(clientConfig, rm, dynamic.LegacyAPIPathResolverFunc)
podResource := map[schema.GroupVersionResource]struct{}{ podResource := map[schema.GroupVersionResource]struct{}{

View File

@ -69,6 +69,7 @@ go_test(
"//vendor/k8s.io/api/autoscaling/v1:go_default_library", "//vendor/k8s.io/api/autoscaling/v1:go_default_library",
"//vendor/k8s.io/api/autoscaling/v2beta1:go_default_library", "//vendor/k8s.io/api/autoscaling/v2beta1:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",

View File

@ -27,6 +27,7 @@ import (
autoscalingv1 "k8s.io/api/autoscaling/v1" autoscalingv1 "k8s.io/api/autoscaling/v1"
autoscalingv2 "k8s.io/api/autoscaling/v2beta1" autoscalingv2 "k8s.io/api/autoscaling/v2beta1"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta/testrestmapper"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
@ -511,7 +512,7 @@ func (tc *testCase) prepareTestClient(t *testing.T) (*fake.Clientset, *metricsfa
} }
name := getForAction.GetName() name := getForAction.GetName()
mapper := legacyscheme.Registry.RESTMapper() mapper := testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme)
metrics := &cmapi.MetricValueList{} metrics := &cmapi.MetricValueList{}
var matchedTarget *autoscalingv2.MetricSpec var matchedTarget *autoscalingv2.MetricSpec
for i, target := range tc.metricsTarget { for i, target := range tc.metricsTarget {
@ -649,7 +650,7 @@ func (tc *testCase) setupController(t *testing.T) (*HorizontalController, inform
eventClient.Core(), eventClient.Core(),
testScaleClient, testScaleClient,
testClient.Autoscaling(), testClient.Autoscaling(),
legacyscheme.Registry.RESTMapper(), testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme),
replicaCalc, replicaCalc,
informerFactory.Autoscaling().V1().HorizontalPodAutoscalers(), informerFactory.Autoscaling().V1().HorizontalPodAutoscalers(),
controller.NoResyncPeriodFunc(), controller.NoResyncPeriodFunc(),

View File

@ -30,6 +30,7 @@ import (
autoscalingv1 "k8s.io/api/autoscaling/v1" autoscalingv1 "k8s.io/api/autoscaling/v1"
autoscalingv2 "k8s.io/api/autoscaling/v2beta1" autoscalingv2 "k8s.io/api/autoscaling/v2beta1"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta/testrestmapper"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
@ -497,7 +498,7 @@ func (tc *legacyTestCase) runTest(t *testing.T) {
eventClient.Core(), eventClient.Core(),
testScaleClient, testScaleClient,
testClient.Autoscaling(), testClient.Autoscaling(),
legacyscheme.Registry.RESTMapper(), testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme),
replicaCalc, replicaCalc,
informerFactory.Autoscaling().V1().HorizontalPodAutoscalers(), informerFactory.Autoscaling().V1().HorizontalPodAutoscalers(),
controller.NoResyncPeriodFunc(), controller.NoResyncPeriodFunc(),

View File

@ -47,6 +47,7 @@ go_test(
"//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/k8s.io/api/autoscaling/v2beta1:go_default_library", "//vendor/k8s.io/api/autoscaling/v2beta1:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",

View File

@ -23,6 +23,7 @@ import (
autoscalingapi "k8s.io/api/autoscaling/v2beta1" autoscalingapi "k8s.io/api/autoscaling/v2beta1"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta/testrestmapper"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
@ -153,7 +154,7 @@ func (tc *restClientTestCase) prepareTestClient(t *testing.T) (*metricsfake.Clie
return true, &metrics, nil return true, &metrics, nil
} else { } else {
name := getForAction.GetName() name := getForAction.GetName()
mapper := legacyscheme.Registry.RESTMapper() mapper := testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme)
assert.NotNil(t, tc.singleObject, "should have only requested a single-object metric when we asked for metrics for a single object") assert.NotNil(t, tc.singleObject, "should have only requested a single-object metric when we asked for metrics for a single object")
gk := schema.FromAPIVersionAndKind(tc.singleObject.APIVersion, tc.singleObject.Kind).GroupKind() gk := schema.FromAPIVersionAndKind(tc.singleObject.APIVersion, tc.singleObject.Kind).GroupKind()
mapping, err := mapper.RESTMapping(gk) mapping, err := mapper.RESTMapping(gk)

View File

@ -24,6 +24,7 @@ import (
autoscalingv2 "k8s.io/api/autoscaling/v2beta1" autoscalingv2 "k8s.io/api/autoscaling/v2beta1"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta/testrestmapper"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
@ -221,7 +222,7 @@ func (tc *replicaCalcTestCase) prepareTestClient(t *testing.T) (*fake.Clientset,
return true, &metrics, nil return true, &metrics, nil
} }
name := getForAction.GetName() name := getForAction.GetName()
mapper := legacyscheme.Registry.RESTMapper() mapper := testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme)
metrics := &cmapi.MetricValueList{} metrics := &cmapi.MetricValueList{}
assert.NotNil(t, tc.metric.singleObject, "should have only requested a single-object metric when calling GetObjectMetricReplicas") assert.NotNil(t, tc.metric.singleObject, "should have only requested a single-object metric when calling GetObjectMetricReplicas")
gk := schema.FromAPIVersionAndKind(tc.metric.singleObject.APIVersion, tc.metric.singleObject.Kind).GroupKind() gk := schema.FromAPIVersionAndKind(tc.metric.singleObject.APIVersion, tc.metric.singleObject.Kind).GroupKind()

View File

@ -25,7 +25,6 @@ import (
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates" "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
@ -46,7 +45,6 @@ type SetLastAppliedOptions struct {
FilenameOptions resource.FilenameOptions FilenameOptions resource.FilenameOptions
infoList []*resource.Info infoList []*resource.Info
mapper meta.RESTMapper
namespace string namespace string
enforceNamespace bool enforceNamespace bool
dryRun bool dryRun bool
@ -117,7 +115,6 @@ func (o *SetLastAppliedOptions) Complete(f cmdutil.Factory, cmd *cobra.Command)
o.output = cmdutil.GetFlagString(cmd, "output") o.output = cmdutil.GetFlagString(cmd, "output")
o.shortOutput = o.output == "name" o.shortOutput = o.output == "name"
o.mapper = f.RESTMapper()
var err error var err error
o.namespace, o.enforceNamespace, err = f.DefaultNamespace() o.namespace, o.enforceNamespace, err = f.DefaultNamespace()
if err != nil { if err != nil {
@ -205,7 +202,7 @@ func (o *SetLastAppliedOptions) RunSetLastApplied() error {
} }
info.Refresh(patchedObj, false) info.Refresh(patchedObj, false)
} }
if err := o.PrintObj(info.AsVersioned(legacyscheme.Scheme), o.Out); err != nil { if err := o.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), o.Out); err != nil {
return err return err
} }
} }

View File

@ -127,7 +127,10 @@ func (o *CanIOptions) Complete(f cmdutil.Factory, args []string) error {
break break
} }
resourceTokens := strings.SplitN(args[1], "/", 2) resourceTokens := strings.SplitN(args[1], "/", 2)
restMapper := f.RESTMapper() restMapper, err := f.RESTMapper()
if err != nil {
return err
}
o.Resource = o.resourceFor(restMapper, resourceTokens[0]) o.Resource = o.resourceFor(restMapper, resourceTokens[0])
if len(resourceTokens) > 1 { if len(resourceTokens) > 1 {
o.ResourceName = resourceTokens[1] o.ResourceName = resourceTokens[1]

View File

@ -127,16 +127,20 @@ func NewCmdAutoscale(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *
} }
func (o *AutoscaleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { func (o *AutoscaleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
var err error
o.dryRun = cmdutil.GetFlagBool(cmd, "dry-run") o.dryRun = cmdutil.GetFlagBool(cmd, "dry-run")
o.createAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag) o.createAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag)
o.builder = f.NewBuilder() o.builder = f.NewBuilder()
o.canBeAutoscaled = f.CanBeAutoscaled o.canBeAutoscaled = f.CanBeAutoscaled
o.mapper = f.RESTMapper() o.mapper, err = f.RESTMapper()
if err != nil {
return err
}
o.clientForMapping = f.ClientForMapping o.clientForMapping = f.ClientForMapping
o.args = args o.args = args
o.RecordFlags.Complete(f.Command(cmd, false)) o.RecordFlags.Complete(f.Command(cmd, false))
var err error
o.Recorder, err = o.RecordFlags.ToRecorder() o.Recorder, err = o.RecordFlags.ToRecorder()
if err != nil { if err != nil {
return err return err
@ -249,7 +253,7 @@ func (o *AutoscaleOptions) Run() error {
if err != nil { if err != nil {
return err return err
} }
return printer.PrintObj(hpa.AsVersioned(legacyscheme.Scheme), o.Out) return printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(hpa.Object, hpa.Mapping), o.Out)
} }
if err := kubectl.CreateOrUpdateAnnotation(o.createAnnotation, hpa.Object, cmdutil.InternalVersionJSONEncoder()); err != nil { if err := kubectl.CreateOrUpdateAnnotation(o.createAnnotation, hpa.Object, cmdutil.InternalVersionJSONEncoder()); err != nil {
@ -266,7 +270,7 @@ func (o *AutoscaleOptions) Run() error {
if err != nil { if err != nil {
return err return err
} }
return printer.PrintObj(info.AsVersioned(legacyscheme.Scheme), o.Out) return printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, hpa.Mapping), o.Out)
}) })
if err != nil { if err != nil {
return err return err

View File

@ -228,7 +228,7 @@ func (options *CertificateOptions) modifyCertificateCondition(builder *resource.
} }
found++ found++
return options.PrintObj(info.AsVersioned(legacyscheme.Scheme), options.Out) return options.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), options.Out)
}) })
if found == 0 { if found == 0 {
fmt.Fprintf(options.Out, "No resources found\n") fmt.Fprintf(options.Out, "No resources found\n")

View File

@ -389,7 +389,10 @@ func RunCreateSubcommand(f cmdutil.Factory, options *CreateSubcommandOptions) er
if err != nil { if err != nil {
return err return err
} }
mapper := f.RESTMapper() mapper, err := f.RESTMapper()
if err != nil {
return err
}
if !options.DryRun { if !options.DryRun {
// create subcommands have compiled knowledge of things they create, so type them directly // create subcommands have compiled knowledge of things they create, so type them directly
gvks, _, err := legacyscheme.Scheme.ObjectKinds(obj) gvks, _, err := legacyscheme.Scheme.ObjectKinds(obj)
@ -423,7 +426,7 @@ func RunCreateSubcommand(f cmdutil.Factory, options *CreateSubcommandOptions) er
} }
// ensure we pass a versioned object to the printer // ensure we pass a versioned object to the printer
obj = info.AsVersioned(legacyscheme.Scheme) obj = cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping)
} else { } else {
if meta, err := meta.Accessor(obj); err == nil && nsOverriden { if meta, err := meta.Accessor(obj); err == nil && nsOverriden {
meta.SetNamespace(namespace) meta.SetNamespace(namespace)

View File

@ -437,8 +437,12 @@ func TestClusterRoleValidate(t *testing.T) {
for name, test := range tests { for name, test := range tests {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
test.clusterRoleOptions.Mapper = tf.RESTMapper() var err error
err := test.clusterRoleOptions.Validate() test.clusterRoleOptions.Mapper, err = tf.RESTMapper()
if err != nil {
t.Fatal(err)
}
err = test.clusterRoleOptions.Validate()
if test.expectErr && err == nil { if test.expectErr && err == nil {
t.Errorf("%s: expect error happens, but validate passes.", name) t.Errorf("%s: expect error happens, but validate passes.", name)
} }

View File

@ -205,7 +205,10 @@ func (o *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
o.ResourceNames = resourceNames o.ResourceNames = resourceNames
// Complete other options for Run. // Complete other options for Run.
o.Mapper = f.RESTMapper() o.Mapper, err = f.RESTMapper()
if err != nil {
return err
}
o.DryRun = cmdutil.GetDryRunFlag(cmd) o.DryRun = cmdutil.GetDryRunFlag(cmd)
o.OutputFormat = cmdutil.GetFlagString(cmd, "output") o.OutputFormat = cmdutil.GetFlagString(cmd, "output")

View File

@ -339,8 +339,12 @@ func TestValidate(t *testing.T) {
} }
for name, test := range tests { for name, test := range tests {
test.roleOptions.Mapper = tf.RESTMapper() var err error
err := test.roleOptions.Validate() test.roleOptions.Mapper, err = tf.RESTMapper()
if err != nil {
t.Fatal(err)
}
err = test.roleOptions.Validate()
if test.expectErr && err == nil { if test.expectErr && err == nil {
t.Errorf("%s: expect error happens but validate passes.", name) t.Errorf("%s: expect error happens but validate passes.", name)
} }

View File

@ -29,7 +29,6 @@ import (
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
policyv1beta1 "k8s.io/api/policy/v1beta1" policyv1beta1 "k8s.io/api/policy/v1beta1"
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
@ -68,7 +67,6 @@ type DrainOptions struct {
DeleteLocalData bool DeleteLocalData bool
Selector string Selector string
PodSelector string PodSelector string
mapper meta.RESTMapper
nodeInfos []*resource.Info nodeInfos []*resource.Info
typer runtime.ObjectTyper typer runtime.ObjectTyper
@ -741,7 +739,7 @@ func (o *DrainOptions) RunCordonOrUncordon(desired bool) error {
fmt.Printf("error: %v", err) fmt.Printf("error: %v", err)
continue continue
} }
printer.PrintObj(nodeInfo.AsVersioned(legacyscheme.Scheme), o.Out) printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(nodeInfo.Object, nodeInfo.Mapping), o.Out)
} else { } else {
if !o.DryRun { if !o.DryRun {
helper := resource.NewHelper(o.restClient, nodeInfo.Mapping) helper := resource.NewHelper(o.restClient, nodeInfo.Mapping)
@ -767,7 +765,7 @@ func (o *DrainOptions) RunCordonOrUncordon(desired bool) error {
fmt.Fprintf(o.ErrOut, "%v", err) fmt.Fprintf(o.ErrOut, "%v", err)
continue continue
} }
printer.PrintObj(nodeInfo.AsVersioned(legacyscheme.Scheme), o.Out) printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(nodeInfo.Object, nodeInfo.Mapping), o.Out)
} }
} else { } else {
printer, err := o.ToPrinter("skipped") printer, err := o.ToPrinter("skipped")
@ -775,7 +773,7 @@ func (o *DrainOptions) RunCordonOrUncordon(desired bool) error {
fmt.Fprintf(o.ErrOut, "%v", err) fmt.Fprintf(o.ErrOut, "%v", err)
continue continue
} }
printer.PrintObj(nodeInfo.AsVersioned(legacyscheme.Scheme), o.Out) printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(nodeInfo.Object, nodeInfo.Mapping), o.Out)
} }
} }

View File

@ -836,7 +836,6 @@ func TestDeletePods(t *testing.T) {
o := DrainOptions{ o := DrainOptions{
PrintFlags: printers.NewPrintFlags("drained"), PrintFlags: printers.NewPrintFlags("drained"),
} }
o.mapper = tf.RESTMapper()
o.Out = os.Stdout o.Out = os.Stdout
o.ToPrinter = func(operation string) (printers.ResourcePrinterFunc, error) { o.ToPrinter = func(operation string) (printers.ResourcePrinterFunc, error) {

View File

@ -91,12 +91,16 @@ func NewCmdExplain(parent string, f cmdutil.Factory, streams genericclioptions.I
} }
func (o *ExplainOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { func (o *ExplainOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
var err error
o.Recursive = cmdutil.GetFlagBool(cmd, "recursive") o.Recursive = cmdutil.GetFlagBool(cmd, "recursive")
o.ApiVersion = cmdutil.GetFlagString(cmd, "api-version") o.ApiVersion = cmdutil.GetFlagString(cmd, "api-version")
o.Mapper = f.RESTMapper() o.Mapper, err = f.RESTMapper()
if err != nil {
return err
}
var err error
o.Schema, err = f.OpenAPISchema() o.Schema, err = f.OpenAPISchema()
if err != nil { if err != nil {
return err return err

View File

@ -187,7 +187,10 @@ func (o *ExposeServiceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) e
o.MapBasedSelectorForObject = f.MapBasedSelectorForObject o.MapBasedSelectorForObject = f.MapBasedSelectorForObject
o.PortsForObject = f.PortsForObject o.PortsForObject = f.PortsForObject
o.ProtocolsForObject = f.ProtocolsForObject o.ProtocolsForObject = f.ProtocolsForObject
o.Mapper = f.RESTMapper() o.Mapper, err = f.RESTMapper()
if err != nil {
return err
}
o.LabelsForObject = f.LabelsForObject o.LabelsForObject = f.LabelsForObject
o.Namespace, o.EnforceNamespace, err = f.DefaultNamespace() o.Namespace, o.EnforceNamespace, err = f.DefaultNamespace()
@ -336,7 +339,7 @@ func (o *ExposeServiceOptions) RunExpose(cmd *cobra.Command, args []string) erro
return err return err
} }
return o.PrintObj(info.AsVersioned(legacyscheme.Scheme), o.Out) return o.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), o.Out)
}) })
if err != nil { if err != nil {
return err return err

View File

@ -21,7 +21,6 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
utilerrors "k8s.io/apimachinery/pkg/util/errors" utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/legacyscheme"
@ -43,7 +42,6 @@ type PauseConfig struct {
ToPrinter func(string) (printers.ResourcePrinterFunc, error) ToPrinter func(string) (printers.ResourcePrinterFunc, error)
Pauser func(info *resource.Info) ([]byte, error) Pauser func(info *resource.Info) ([]byte, error)
Mapper meta.RESTMapper
Infos []*resource.Info Infos []*resource.Info
genericclioptions.IOStreams genericclioptions.IOStreams
@ -105,8 +103,6 @@ func (o *PauseConfig) CompletePause(f cmdutil.Factory, cmd *cobra.Command, args
return cmdutil.UsageErrorf(cmd, "%s", cmd.Use) return cmdutil.UsageErrorf(cmd, "%s", cmd.Use)
} }
o.Mapper = f.RESTMapper()
o.Pauser = f.Pauser o.Pauser = f.Pauser
cmdNamespace, enforceNamespace, err := f.DefaultNamespace() cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
@ -160,7 +156,7 @@ func (o PauseConfig) RunPause() error {
allErrs = append(allErrs, err) allErrs = append(allErrs, err)
continue continue
} }
printer.PrintObj(info.AsVersioned(legacyscheme.Scheme), o.Out) printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), o.Out)
continue continue
} }
@ -176,7 +172,7 @@ func (o PauseConfig) RunPause() error {
allErrs = append(allErrs, err) allErrs = append(allErrs, err)
continue continue
} }
printer.PrintObj(info.AsVersioned(legacyscheme.Scheme), o.Out) printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), o.Out)
} }
return utilerrors.NewAggregate(allErrs) return utilerrors.NewAggregate(allErrs)

View File

@ -21,7 +21,6 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
utilerrors "k8s.io/apimachinery/pkg/util/errors" utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/legacyscheme"
@ -43,7 +42,6 @@ type ResumeConfig struct {
ToPrinter func(string) (printers.ResourcePrinterFunc, error) ToPrinter func(string) (printers.ResourcePrinterFunc, error)
Resumer func(object *resource.Info) ([]byte, error) Resumer func(object *resource.Info) ([]byte, error)
Mapper meta.RESTMapper
Infos []*resource.Info Infos []*resource.Info
genericclioptions.IOStreams genericclioptions.IOStreams
@ -103,8 +101,6 @@ func (o *ResumeConfig) CompleteResume(f cmdutil.Factory, cmd *cobra.Command, arg
return cmdutil.UsageErrorf(cmd, "%s", cmd.Use) return cmdutil.UsageErrorf(cmd, "%s", cmd.Use)
} }
o.Mapper = f.RESTMapper()
o.Resumer = f.Resumer o.Resumer = f.Resumer
cmdNamespace, enforceNamespace, err := f.DefaultNamespace() cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
@ -165,7 +161,7 @@ func (o ResumeConfig) RunResume() error {
allErrs = append(allErrs, err) allErrs = append(allErrs, err)
continue continue
} }
printer.PrintObj(info.AsVersioned(legacyscheme.Scheme), o.Out) printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), o.Out)
} }
obj, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch) obj, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch)
@ -180,7 +176,7 @@ func (o ResumeConfig) RunResume() error {
allErrs = append(allErrs, err) allErrs = append(allErrs, err)
continue continue
} }
printer.PrintObj(info.AsVersioned(legacyscheme.Scheme), o.Out) printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), o.Out)
} }
return utilerrors.NewAggregate(allErrs) return utilerrors.NewAggregate(allErrs)

View File

@ -19,7 +19,6 @@ package rollout
import ( import (
"io" "io"
"k8s.io/apimachinery/pkg/api/meta"
utilerrors "k8s.io/apimachinery/pkg/util/errors" utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
@ -41,7 +40,6 @@ type UndoOptions struct {
ToPrinter func(string) (printers.ResourcePrinterFunc, error) ToPrinter func(string) (printers.ResourcePrinterFunc, error)
Rollbackers []kubectl.Rollbacker Rollbackers []kubectl.Rollbacker
Mapper meta.RESTMapper
Infos []*resource.Info Infos []*resource.Info
ToRevision int64 ToRevision int64
DryRun bool DryRun bool
@ -107,7 +105,6 @@ func (o *UndoOptions) CompleteUndo(f cmdutil.Factory, cmd *cobra.Command, out io
} }
o.ToRevision = cmdutil.GetFlagInt64(cmd, "to-revision") o.ToRevision = cmdutil.GetFlagInt64(cmd, "to-revision")
o.Mapper = f.RESTMapper()
o.Out = out o.Out = out
o.DryRun = cmdutil.GetDryRunFlag(cmd) o.DryRun = cmdutil.GetDryRunFlag(cmd)
@ -171,7 +168,7 @@ func (o *UndoOptions) RunUndo() error {
allErrs = append(allErrs, err) allErrs = append(allErrs, err)
continue continue
} }
printer.PrintObj(info.AsVersioned(legacyscheme.Scheme), o.Out) printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), o.Out)
} }
return utilerrors.NewAggregate(allErrs) return utilerrors.NewAggregate(allErrs)
} }

View File

@ -643,7 +643,10 @@ func (o *RunOptions) createGeneratedObject(f cmdutil.Factory, cmd *cobra.Command
return nil, err return nil, err
} }
mapper := f.RESTMapper() mapper, err := f.RESTMapper()
if err != nil {
return nil, err
}
// run has compiled knowledge of the thing is is creating // run has compiled knowledge of the thing is is creating
groupVersionKinds, _, err := legacyscheme.Scheme.ObjectKinds(obj) groupVersionKinds, _, err := legacyscheme.Scheme.ObjectKinds(obj)
if err != nil { if err != nil {
@ -693,7 +696,7 @@ func (o *RunOptions) createGeneratedObject(f cmdutil.Factory, cmd *cobra.Command
return nil, err return nil, err
} }
versioned = info.AsVersioned(legacyscheme.Scheme) versioned = cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping)
} }
return &RunObject{ return &RunObject{
Versioned: versioned, Versioned: versioned,

View File

@ -327,7 +327,7 @@ func (o *EnvOptions) RunEnv() error {
return err return err
} }
patches := CalculatePatches(infos, cmdutil.InternalVersionJSONEncoder(), func(info *resource.Info) ([]byte, error) { patches := CalculatePatches(infos, cmdutil.InternalVersionJSONEncoder(), func(info *resource.Info) ([]byte, error) {
info.Object = info.AsVersioned(legacyscheme.Scheme) info.Object = cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping)
_, err := o.updatePodSpecForObject(info.Object, func(spec *v1.PodSpec) error { _, err := o.updatePodSpecForObject(info.Object, func(spec *v1.PodSpec) error {
resolutionErrorsEncountered := false resolutionErrorsEncountered := false
containers, _ := selectContainers(spec.Containers, o.ContainerSelector) containers, _ := selectContainers(spec.Containers, o.ContainerSelector)
@ -418,7 +418,7 @@ func (o *EnvOptions) RunEnv() error {
} }
if o.Local || o.dryRun { if o.Local || o.dryRun {
if err := o.PrintObj(patch.Info.AsVersioned(legacyscheme.Scheme), o.Out); err != nil { if err := o.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(patch.Info.Object, patch.Info.Mapping), o.Out); err != nil {
return err return err
} }
continue continue
@ -437,7 +437,7 @@ func (o *EnvOptions) RunEnv() error {
return fmt.Errorf("at least one environment variable must be provided") return fmt.Errorf("at least one environment variable must be provided")
} }
if err := o.PrintObj(info.AsVersioned(legacyscheme.Scheme), o.Out); err != nil { if err := o.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), o.Out); err != nil {
return err return err
} }
} }

View File

@ -211,7 +211,7 @@ func (o *SetImageOptions) Run() error {
patches := CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), func(info *resource.Info) ([]byte, error) { patches := CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), func(info *resource.Info) ([]byte, error) {
transformed := false transformed := false
info.Object = info.AsVersioned(legacyscheme.Scheme) info.Object = cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping)
_, err := o.UpdatePodSpecForObject(info.Object, func(spec *v1.PodSpec) error { _, err := o.UpdatePodSpecForObject(info.Object, func(spec *v1.PodSpec) error {
for name, image := range o.ContainerImages { for name, image := range o.ContainerImages {
var ( var (
@ -275,7 +275,7 @@ func (o *SetImageOptions) Run() error {
} }
if o.Local || o.DryRun { if o.Local || o.DryRun {
if err := o.PrintObj(patch.Info.AsVersioned(legacyscheme.Scheme), o.Out); err != nil { if err := o.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(patch.Info.Object, patch.Info.Mapping), o.Out); err != nil {
return err return err
} }
continue continue
@ -289,7 +289,7 @@ func (o *SetImageOptions) Run() error {
} }
info.Refresh(obj, true) info.Refresh(obj, true)
if err := o.PrintObj(info.AsVersioned(legacyscheme.Scheme), o.Out); err != nil { if err := o.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), o.Out); err != nil {
return err return err
} }
} }

View File

@ -224,7 +224,7 @@ func (o *SetResourcesOptions) Run() error {
allErrs := []error{} allErrs := []error{}
patches := CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), func(info *resource.Info) ([]byte, error) { patches := CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), func(info *resource.Info) ([]byte, error) {
transformed := false transformed := false
info.Object = info.AsVersioned(legacyscheme.Scheme) info.Object = cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping)
_, err := o.UpdatePodSpecForObject(info.Object, func(spec *v1.PodSpec) error { _, err := o.UpdatePodSpecForObject(info.Object, func(spec *v1.PodSpec) error {
containers, _ := selectContainers(spec.Containers, o.ContainerSelector) containers, _ := selectContainers(spec.Containers, o.ContainerSelector)
if len(containers) != 0 { if len(containers) != 0 {
@ -277,7 +277,7 @@ func (o *SetResourcesOptions) Run() error {
} }
if o.Local || o.DryRun { if o.Local || o.DryRun {
if err := o.PrintObj(patch.Info.AsVersioned(legacyscheme.Scheme), o.Out); err != nil { if err := o.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(patch.Info.Object, patch.Info.Mapping), o.Out); err != nil {
return err return err
} }
continue continue
@ -290,7 +290,7 @@ func (o *SetResourcesOptions) Run() error {
} }
info.Refresh(obj, true) info.Refresh(obj, true)
if err := o.PrintObj(info.AsVersioned(legacyscheme.Scheme), o.Out); err != nil { if err := o.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), o.Out); err != nil {
return err return err
} }
} }

View File

@ -59,7 +59,6 @@ type SetSelectorOptions struct {
Recorder genericclioptions.Recorder Recorder genericclioptions.Recorder
builder *resource.Builder builder *resource.Builder
mapper meta.RESTMapper
genericclioptions.IOStreams genericclioptions.IOStreams
} }
@ -140,9 +139,6 @@ func (o *SetSelectorOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, arg
return err return err
} }
mapper := f.RESTMapper()
o.mapper = mapper
o.resources, o.selector, err = getResourcesAndSelector(args) o.resources, o.selector, err = getResourcesAndSelector(args)
if err != nil { if err != nil {
return err return err
@ -208,7 +204,7 @@ func (o *SetSelectorOptions) RunSelector() error {
return r.Visit(func(info *resource.Info, err error) error { return r.Visit(func(info *resource.Info, err error) error {
patch := &Patch{Info: info} patch := &Patch{Info: info}
CalculatePatch(patch, cmdutil.InternalVersionJSONEncoder(), func(info *resource.Info) ([]byte, error) { CalculatePatch(patch, cmdutil.InternalVersionJSONEncoder(), func(info *resource.Info) ([]byte, error) {
versioned := info.AsVersioned(legacyscheme.Scheme) versioned := cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping)
patch.Info.Object = versioned patch.Info.Object = versioned
selectErr := updateSelectorForObject(info.Object, *o.selector) selectErr := updateSelectorForObject(info.Object, *o.selector)
if selectErr != nil { if selectErr != nil {
@ -236,7 +232,7 @@ func (o *SetSelectorOptions) RunSelector() error {
} }
info.Refresh(patched, true) info.Refresh(patched, true)
return o.PrintObj(patch.Info.AsVersioned(legacyscheme.Scheme), o.Out) return o.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(patch.Info.Object, info.Mapping), o.Out)
}) })
} }

View File

@ -174,7 +174,7 @@ func (o *SetServiceAccountOptions) Complete(f cmdutil.Factory, cmd *cobra.Comman
func (o *SetServiceAccountOptions) Run() error { func (o *SetServiceAccountOptions) Run() error {
patchErrs := []error{} patchErrs := []error{}
patchFn := func(info *resource.Info) ([]byte, error) { patchFn := func(info *resource.Info) ([]byte, error) {
info.Object = info.AsVersioned(legacyscheme.Scheme) info.Object = cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping)
_, err := o.updatePodSpecForObject(info.Object, func(podSpec *v1.PodSpec) error { _, err := o.updatePodSpecForObject(info.Object, func(podSpec *v1.PodSpec) error {
podSpec.ServiceAccountName = o.serviceAccountName podSpec.ServiceAccountName = o.serviceAccountName
return nil return nil
@ -198,7 +198,7 @@ func (o *SetServiceAccountOptions) Run() error {
continue continue
} }
if o.local || o.dryRun { if o.local || o.dryRun {
if err := o.PrintObj(patch.Info.AsVersioned(legacyscheme.Scheme), o.Out); err != nil { if err := o.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(patch.Info.Object, patch.Info.Mapping), o.Out); err != nil {
return err return err
} }
continue continue
@ -210,7 +210,7 @@ func (o *SetServiceAccountOptions) Run() error {
} }
info.Refresh(patched, true) info.Refresh(patched, true)
if err := o.PrintObj(info.AsVersioned(legacyscheme.Scheme), o.Out); err != nil { if err := o.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), o.Out); err != nil {
return err return err
} }
} }

View File

@ -230,7 +230,7 @@ func (o *SubjectOptions) Run(fn updateSubjects) error {
transformed, err := updateSubjectForObject(info.Object, subjects, fn) transformed, err := updateSubjectForObject(info.Object, subjects, fn)
if transformed && err == nil { if transformed && err == nil {
// TODO: switch UpdatePodSpecForObject to work on v1.PodSpec // TODO: switch UpdatePodSpecForObject to work on v1.PodSpec
return runtime.Encode(cmdutil.InternalVersionJSONEncoder(), info.AsVersioned(legacyscheme.Scheme)) return runtime.Encode(cmdutil.InternalVersionJSONEncoder(), cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping))
} }
return nil, err return nil, err
}) })
@ -263,7 +263,7 @@ func (o *SubjectOptions) Run(fn updateSubjects) error {
} }
info.Refresh(obj, true) info.Refresh(obj, true)
return o.PrintObj(info.AsVersioned(legacyscheme.Scheme), o.Out) return o.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), o.Out)
} }
return utilerrors.NewAggregate(allErrs) return utilerrors.NewAggregate(allErrs)
} }

View File

@ -22,6 +22,7 @@ go_library(
"//pkg/printers:go_default_library", "//pkg/printers:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",

View File

@ -28,6 +28,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/api/meta/testrestmapper"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
@ -337,7 +338,7 @@ func (f *TestFactory) Command(*cobra.Command, bool) string {
} }
func (f *TestFactory) NewBuilder() *resource.Builder { func (f *TestFactory) NewBuilder() *resource.Builder {
mapper := f.RESTMapper() mapper, err := f.RESTMapper()
return resource.NewBuilder( return resource.NewBuilder(
&resource.Mapper{ &resource.Mapper{
@ -351,7 +352,7 @@ func (f *TestFactory) NewBuilder() *resource.Builder {
Decoder: unstructured.UnstructuredJSONScheme, Decoder: unstructured.UnstructuredJSONScheme,
}, },
f.CategoryExpander(), f.CategoryExpander(),
) ).AddError(err)
} }
func (f *TestFactory) KubernetesClientSet() (*kubernetes.Clientset, error) { func (f *TestFactory) KubernetesClientSet() (*kubernetes.Clientset, error) {
@ -425,7 +426,7 @@ func (f *TestFactory) ClientSetForVersion(requiredVersion *schema.GroupVersion)
return f.ClientSet() return f.ClientSet()
} }
func (f *TestFactory) RESTMapper() meta.RESTMapper { func (f *TestFactory) RESTMapper() (meta.RESTMapper, error) {
groupResources := testDynamicResources() groupResources := testDynamicResources()
mapper := discovery.NewRESTMapper(groupResources) mapper := discovery.NewRESTMapper(groupResources)
// for backwards compatibility with existing tests, allow rest mappings from the scheme to show up // for backwards compatibility with existing tests, allow rest mappings from the scheme to show up
@ -433,14 +434,14 @@ func (f *TestFactory) RESTMapper() meta.RESTMapper {
mapper = meta.FirstHitRESTMapper{ mapper = meta.FirstHitRESTMapper{
MultiRESTMapper: meta.MultiRESTMapper{ MultiRESTMapper: meta.MultiRESTMapper{
mapper, mapper,
legacyscheme.Registry.RESTMapper(), testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme),
}, },
} }
// TODO: should probably be the external scheme // TODO: should probably be the external scheme
fakeDs := &fakeCachedDiscoveryClient{} fakeDs := &fakeCachedDiscoveryClient{}
expander := cmdutil.NewShortcutExpander(mapper, fakeDs) expander := cmdutil.NewShortcutExpander(mapper, fakeDs)
return expander return expander, nil
} }
func (f *TestFactory) LogsForObject(object, options runtime.Object, timeout time.Duration) (*restclient.Request, error) { func (f *TestFactory) LogsForObject(object, options runtime.Object, timeout time.Duration) (*restclient.Request, error) {

View File

@ -4,6 +4,7 @@ go_library(
name = "go_default_library", name = "go_default_library",
srcs = [ srcs = [
"cached_discovery.go", "cached_discovery.go",
"conversion.go",
"factory.go", "factory.go",
"factory_builder.go", "factory_builder.go",
"factory_client_access.go", "factory_client_access.go",
@ -104,6 +105,7 @@ go_test(
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",

View File

@ -0,0 +1,40 @@
/*
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 util
import (
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kubernetes/pkg/api/legacyscheme"
)
// AsDefaultVersionedOrOriginal returns the object as a Go object in the external form if possible (matching the
// group version kind of the mapping if provided, a best guess based on serialization if not provided, or obj if it cannot be converted.
// TODO update call sites to specify the scheme they want on their builder.
func AsDefaultVersionedOrOriginal(obj runtime.Object, mapping *meta.RESTMapping) runtime.Object {
converter := runtime.ObjectConvertor(legacyscheme.Scheme)
groupVersioner := runtime.GroupVersioner(schema.GroupVersions(legacyscheme.Registry.RegisteredGroupVersions()))
if mapping != nil {
groupVersioner = mapping.GroupVersionKind.GroupVersion()
}
if obj, err := converter.ConvertToVersion(obj, groupVersioner); err == nil {
return obj
}
return obj
}

View File

@ -164,7 +164,7 @@ type ClientAccessFactory interface {
// Generally they provide object typing and functions that build requests based on the negotiated clients. // Generally they provide object typing and functions that build requests based on the negotiated clients.
type ObjectMappingFactory interface { type ObjectMappingFactory interface {
// Returns interfaces for dealing with arbitrary runtime.Objects. // Returns interfaces for dealing with arbitrary runtime.Objects.
RESTMapper() meta.RESTMapper RESTMapper() (meta.RESTMapper, error)
// Returns interface for expanding categories like `all`. // Returns interface for expanding categories like `all`.
CategoryExpander() categories.CategoryExpander CategoryExpander() categories.CategoryExpander
// Returns a RESTClient for working with the specified RESTMapping or an error. This is intended // Returns a RESTClient for working with the specified RESTMapping or an error. This is intended

View File

@ -47,7 +47,7 @@ func NewBuilderFactory(clientAccessFactory ClientAccessFactory, objectMappingFac
// NewBuilder returns a new resource builder for structured api objects. // NewBuilder returns a new resource builder for structured api objects.
func (f *ring2Factory) NewBuilder() *resource.Builder { func (f *ring2Factory) NewBuilder() *resource.Builder {
clientMapperFunc := resource.ClientMapperFunc(f.objectMappingFactory.ClientForMapping) clientMapperFunc := resource.ClientMapperFunc(f.objectMappingFactory.ClientForMapping)
mapper := f.objectMappingFactory.RESTMapper() mapper, mapperErr := f.objectMappingFactory.RESTMapper()
unstructuredClientMapperFunc := resource.ClientMapperFunc(f.objectMappingFactory.UnstructuredClientForMapping) unstructuredClientMapperFunc := resource.ClientMapperFunc(f.objectMappingFactory.UnstructuredClientForMapping)
@ -65,7 +65,7 @@ func (f *ring2Factory) NewBuilder() *resource.Builder {
Decoder: unstructured.UnstructuredJSONScheme, Decoder: unstructured.UnstructuredJSONScheme,
}, },
categoryExpander, categoryExpander,
) ).AddError(mapperErr)
} }
// PluginLoader loads plugins from a path set by the KUBECTL_PLUGINS_PATH env var. // PluginLoader loads plugins from a path set by the KUBECTL_PLUGINS_PATH env var.
@ -97,7 +97,11 @@ func (f *ring2Factory) ScaleClient() (scaleclient.ScalesGetter, error) {
return nil, err return nil, err
} }
resolver := scaleclient.NewDiscoveryScaleKindResolver(discoClient) resolver := scaleclient.NewDiscoveryScaleKindResolver(discoClient)
mapper := f.objectMappingFactory.RESTMapper() mapper, err := f.objectMappingFactory.RESTMapper()
if err != nil {
return nil, err
}
return scaleclient.New(restClient, mapper, dynamic.LegacyAPIPathResolverFunc, resolver), nil return scaleclient.New(restClient, mapper, dynamic.LegacyAPIPathResolverFunc, resolver), nil
} }

View File

@ -27,8 +27,6 @@ import (
"sync" "sync"
"time" "time"
"github.com/golang/glog"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -37,7 +35,6 @@ import (
"k8s.io/client-go/discovery" "k8s.io/client-go/discovery"
"k8s.io/client-go/dynamic" "k8s.io/client-go/dynamic"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/apis/apps" "k8s.io/kubernetes/pkg/apis/apps"
"k8s.io/kubernetes/pkg/apis/batch" "k8s.io/kubernetes/pkg/apis/batch"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
@ -72,26 +69,18 @@ func NewObjectMappingFactory(clientAccessFactory ClientAccessFactory) ObjectMapp
return f return f
} }
// objectLoader attempts to perform discovery against the server, and will fall back to // RESTMapper returns a mapper.
// the built in mapper if necessary. It supports unstructured objects either way, since func (f *ring1Factory) RESTMapper() (meta.RESTMapper, error) {
// the underlying Scheme supports Unstructured. The mapper will return converters that can
// convert versioned types to unstructured and back.
func (f *ring1Factory) restMapper() (meta.RESTMapper, error) {
discoveryClient, err := f.clientAccessFactory.DiscoveryClient() discoveryClient, err := f.clientAccessFactory.DiscoveryClient()
if err != nil { if err != nil {
glog.V(3).Infof("Unable to get a discovery client to find server resources, falling back to hardcoded types: %v", err) return nil, err
return legacyscheme.Registry.RESTMapper(), nil
} }
// allow conversion between typed and unstructured objects // allow conversion between typed and unstructured objects
mapper := discovery.NewDeferredDiscoveryRESTMapper(discoveryClient) mapper := discovery.NewDeferredDiscoveryRESTMapper(discoveryClient)
// TODO: should this also indicate it recognizes typed objects? // TODO: should this also indicate it recognizes typed objects?
expander := NewShortcutExpander(mapper, discoveryClient) expander := NewShortcutExpander(mapper, discoveryClient)
return expander, err return expander, nil
}
func (f *ring1Factory) RESTMapper() meta.RESTMapper {
return meta.NewLazyRESTMapperLoader(f.restMapper)
} }
func (f *ring1Factory) CategoryExpander() categories.CategoryExpander { func (f *ring1Factory) CategoryExpander() categories.CategoryExpander {

View File

@ -26,6 +26,7 @@ import (
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
apiequality "k8s.io/apimachinery/pkg/api/equality" apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/api/meta/testrestmapper"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
@ -34,6 +35,7 @@ import (
"k8s.io/apimachinery/pkg/watch" "k8s.io/apimachinery/pkg/watch"
manualfake "k8s.io/client-go/rest/fake" manualfake "k8s.io/client-go/rest/fake"
testcore "k8s.io/client-go/testing" testcore "k8s.io/client-go/testing"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/testapi"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
@ -470,7 +472,7 @@ func TestDiscoveryReplaceAliases(t *testing.T) {
} }
ds := &fakeDiscoveryClient{} ds := &fakeDiscoveryClient{}
mapper := NewShortcutExpander(testapi.Default.RESTMapper(), ds) mapper := NewShortcutExpander(testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme), ds)
b := resource.NewBuilder( b := resource.NewBuilder(
&resource.Mapper{ &resource.Mapper{
RESTMapper: mapper, RESTMapper: mapper,

View File

@ -19,9 +19,10 @@ package util
import ( import (
"testing" "testing"
"k8s.io/apimachinery/pkg/api/meta/testrestmapper"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/legacyscheme"
) )
func TestReplaceAliases(t *testing.T) { func TestReplaceAliases(t *testing.T) {
@ -126,7 +127,7 @@ func TestReplaceAliases(t *testing.T) {
} }
ds := &fakeDiscoveryClient{} ds := &fakeDiscoveryClient{}
mapper := NewShortcutExpander(testapi.Default.RESTMapper(), ds) mapper := NewShortcutExpander(testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme), ds)
for _, test := range tests { for _, test := range tests {
ds.serverResourcesHandler = func() ([]*metav1.APIResourceList, error) { ds.serverResourcesHandler = func() ([]*metav1.APIResourceList, error) {
@ -178,7 +179,7 @@ func TestKindFor(t *testing.T) {
} }
ds := &fakeDiscoveryClient{} ds := &fakeDiscoveryClient{}
mapper := NewShortcutExpander(testapi.Default.RESTMapper(), ds) mapper := NewShortcutExpander(testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme), ds)
for i, test := range tests { for i, test := range tests {
ds.serverResourcesHandler = func() ([]*metav1.APIResourceList, error) { ds.serverResourcesHandler = func() ([]*metav1.APIResourceList, error) {

View File

@ -51,6 +51,7 @@ go_test(
deps = [ deps = [
"//pkg/kubectl/cmd/util/openapi/testing:go_default_library", "//pkg/kubectl/cmd/util/openapi/testing:go_default_library",
"//pkg/kubectl/scheme:go_default_library", "//pkg/kubectl/scheme:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
], ],
) )

View File

@ -20,6 +20,7 @@ import (
"reflect" "reflect"
"testing" "testing"
"k8s.io/apimachinery/pkg/api/meta/testrestmapper"
"k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/scheme"
) )
@ -56,7 +57,7 @@ func TestSplitAndParseResourceRequest(t *testing.T) {
}, },
} }
mapper := scheme.Registry.RESTMapper(scheme.Versions...) mapper := testrestmapper.TestOnlyStaticRESTMapper(scheme.Registry, scheme.Scheme, scheme.Versions...)
for _, test := range tests { for _, test := range tests {
gotInResource, gotFieldsPath, err := SplitAndParseResourceRequest(test.inresource, mapper) gotInResource, gotFieldsPath, err := SplitAndParseResourceRequest(test.inresource, mapper)
if err != nil { if err != nil {

View File

@ -65,6 +65,7 @@ go_test(
"//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",

View File

@ -56,6 +56,9 @@ type Builder struct {
// it does not ever need to rely upon discovery. // it does not ever need to rely upon discovery.
objectTyper runtime.ObjectTyper objectTyper runtime.ObjectTyper
// local indicates that we cannot make server calls
local bool
errs []error errs []error
paths []Visitor paths []Visitor
@ -142,6 +145,14 @@ func (b *Builder) Schema(schema validation.Schema) *Builder {
return b return b
} }
func (b *Builder) AddError(err error) *Builder {
if err == nil {
return b
}
b.errs = append(b.errs, err)
return b
}
// FilenameParam groups input in two categories: URLs and files (files, directories, STDIN) // FilenameParam groups input in two categories: URLs and files (files, directories, STDIN)
// If enforceNamespace is false, namespaces in the specs will be allowed to // If enforceNamespace is false, namespaces in the specs will be allowed to
// override the default namespace. If it is true, namespaces that don't match // override the default namespace. If it is true, namespaces that don't match
@ -192,6 +203,7 @@ func (b *Builder) Unstructured() *Builder {
return b return b
} }
b.mapper = b.unstructured b.mapper = b.unstructured
b.mapper.localFn = b.isLocal
b.objectTyper = unstructuredscheme.NewUnstructuredObjectTyper() b.objectTyper = unstructuredscheme.NewUnstructuredObjectTyper()
return b return b
@ -212,6 +224,7 @@ func (b *Builder) Internal(typer runtime.ObjectTyper) *Builder {
return b return b
} }
b.mapper = b.internal b.mapper = b.internal
b.mapper.localFn = b.isLocal
b.objectTyper = typer b.objectTyper = typer
return b return b
@ -227,12 +240,17 @@ func (b *Builder) LocalParam(local bool) *Builder {
// Local will avoid asking the server for results. // Local will avoid asking the server for results.
func (b *Builder) Local() *Builder { func (b *Builder) Local() *Builder {
b.local = true
mapper := *b.mapper mapper := *b.mapper
mapper.ClientMapper = DisabledClientForMapping{ClientMapper: mapper.ClientMapper} mapper.ClientMapper = DisabledClientForMapping{ClientMapper: mapper.ClientMapper}
b.mapper = &mapper b.mapper = &mapper
return b return b
} }
func (b *Builder) isLocal() bool {
return b.local
}
// Mapper returns a copy of the current mapper. // Mapper returns a copy of the current mapper.
func (b *Builder) Mapper() *Mapper { func (b *Builder) Mapper() *Mapper {
mapper := *b.mapper mapper := *b.mapper

View File

@ -34,6 +34,7 @@ import (
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
apiequality "k8s.io/apimachinery/pkg/api/equality" apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/api/meta/testrestmapper"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
@ -58,7 +59,7 @@ var (
corev1GV = schema.GroupVersion{Version: "v1"} corev1GV = schema.GroupVersion{Version: "v1"}
corev1Codec = scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(corev1GV), scheme.Codecs.UniversalDecoder(corev1GV), corev1GV, corev1GV) corev1Codec = scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(corev1GV), scheme.Codecs.UniversalDecoder(corev1GV), corev1GV, corev1GV)
metaAccessor = meta.NewAccessor() metaAccessor = meta.NewAccessor()
restmapper = scheme.Registry.RESTMapper() restmapper = testrestmapper.TestOnlyStaticRESTMapper(scheme.Registry, scheme.Scheme)
) )
func stringBody(body string) io.ReadCloser { func stringBody(body string) io.ReadCloser {
@ -299,7 +300,8 @@ func TestPathBuilderAndVersionedObjectNotDefaulted(t *testing.T) {
if info.Name != "update-demo-kitten" || info.Namespace != "" || info.Object == nil { if info.Name != "update-demo-kitten" || info.Namespace != "" || info.Object == nil {
t.Errorf("unexpected info: %#v", info) t.Errorf("unexpected info: %#v", info)
} }
obj := info.AsVersioned(legacyscheme.Scheme)
obj := info.Object
version, ok := obj.(*v1.ReplicationController) version, ok := obj.(*v1.ReplicationController)
// versioned object does not have defaulting applied // versioned object does not have defaulting applied
if obj == nil || !ok || version.Spec.Replicas != nil { if obj == nil || !ok || version.Spec.Replicas != nil {

View File

@ -22,6 +22,8 @@ import (
client "k8s.io/client-go/rest" client "k8s.io/client-go/rest"
) )
type RESTMapperFunc func() (meta.RESTMapper, error)
// RESTClient is a client helper for dealing with RESTful resources // RESTClient is a client helper for dealing with RESTful resources
// in a generic way. // in a generic way.
type RESTClient interface { type RESTClient interface {

View File

@ -28,6 +28,9 @@ import (
// Mapper is a convenience struct for holding references to the interfaces // Mapper is a convenience struct for holding references to the interfaces
// needed to create Info for arbitrary objects. // needed to create Info for arbitrary objects.
type Mapper struct { type Mapper struct {
// localFn indicates the call can't make server requests
localFn func() bool
RESTMapper meta.RESTMapper RESTMapper meta.RESTMapper
ClientMapper ClientMapper ClientMapper ClientMapper
Decoder runtime.Decoder Decoder runtime.Decoder
@ -42,31 +45,34 @@ func (m *Mapper) InfoForData(data []byte, source string) (*Info, error) {
return nil, fmt.Errorf("unable to decode %q: %v", source, err) return nil, fmt.Errorf("unable to decode %q: %v", source, err)
} }
mapping, err := m.RESTMapper.RESTMapping(gvk.GroupKind(), gvk.Version)
if err != nil {
return nil, fmt.Errorf("unable to recognize %q: %v", source, err)
}
client, err := m.ClientMapper.ClientForMapping(mapping)
if err != nil {
return nil, fmt.Errorf("unable to connect to a server to handle %q: %v", mapping.Resource, err)
}
name, _ := metadataAccessor.Name(obj) name, _ := metadataAccessor.Name(obj)
namespace, _ := metadataAccessor.Namespace(obj) namespace, _ := metadataAccessor.Namespace(obj)
resourceVersion, _ := metadataAccessor.ResourceVersion(obj) resourceVersion, _ := metadataAccessor.ResourceVersion(obj)
return &Info{ ret := &Info{
Client: client,
Mapping: mapping,
Source: source, Source: source,
Namespace: namespace, Namespace: namespace,
Name: name, Name: name,
ResourceVersion: resourceVersion, ResourceVersion: resourceVersion,
Object: obj, Object: obj,
}, nil }
if m.localFn == nil || !m.localFn() {
mapping, err := m.RESTMapper.RESTMapping(gvk.GroupKind(), gvk.Version)
if err != nil {
return nil, fmt.Errorf("unable to recognize %q: %v", source, err)
}
ret.Mapping = mapping
client, err := m.ClientMapper.ClientForMapping(mapping)
if err != nil {
return nil, fmt.Errorf("unable to connect to a server to handle %q: %v", mapping.Resource, err)
}
ret.Client = client
}
return ret, nil
} }
// InfoForObject creates an Info object for the given Object. An error is returned // InfoForObject creates an Info object for the given Object. An error is returned
@ -78,33 +84,37 @@ func (m *Mapper) InfoForObject(obj runtime.Object, typer runtime.ObjectTyper, pr
return nil, fmt.Errorf("unable to get type info from the object %q: %v", reflect.TypeOf(obj), err) return nil, fmt.Errorf("unable to get type info from the object %q: %v", reflect.TypeOf(obj), err)
} }
groupVersionKind := groupVersionKinds[0] gvk := groupVersionKinds[0]
if len(groupVersionKinds) > 1 && len(preferredGVKs) > 0 { if len(groupVersionKinds) > 1 && len(preferredGVKs) > 0 {
groupVersionKind = preferredObjectKind(groupVersionKinds, preferredGVKs) gvk = preferredObjectKind(groupVersionKinds, preferredGVKs)
} }
mapping, err := m.RESTMapper.RESTMapping(groupVersionKind.GroupKind(), groupVersionKind.Version)
if err != nil {
return nil, fmt.Errorf("unable to recognize %v: %v", groupVersionKind, err)
}
client, err := m.ClientMapper.ClientForMapping(mapping)
if err != nil {
return nil, fmt.Errorf("unable to connect to a server to handle %q: %v", mapping.Resource, err)
}
name, _ := metadataAccessor.Name(obj) name, _ := metadataAccessor.Name(obj)
namespace, _ := metadataAccessor.Namespace(obj) namespace, _ := metadataAccessor.Namespace(obj)
resourceVersion, _ := metadataAccessor.ResourceVersion(obj) resourceVersion, _ := metadataAccessor.ResourceVersion(obj)
return &Info{ ret := &Info{
Client: client,
Mapping: mapping,
Namespace: namespace, Namespace: namespace,
Name: name, Name: name,
ResourceVersion: resourceVersion, ResourceVersion: resourceVersion,
Object: obj, Object: obj,
}, nil }
if m.localFn == nil || !m.localFn() {
mapping, err := m.RESTMapper.RESTMapping(gvk.GroupKind(), gvk.Version)
if err != nil {
return nil, fmt.Errorf("unable to recognize %v", err)
}
ret.Mapping = mapping
client, err := m.ClientMapper.ClientForMapping(mapping)
if err != nil {
return nil, fmt.Errorf("unable to connect to a server to handle %q: %v", mapping.Resource, err)
}
ret.Client = client
}
return ret, nil
} }
// preferredObjectKind picks the possibility that most closely matches the priority list in this order: // preferredObjectKind picks the possibility that most closely matches the priority list in this order:

View File

@ -180,22 +180,6 @@ func (i *Info) ResourceMapping() *meta.RESTMapping {
return i.Mapping return i.Mapping
} }
// Versioned returns the object as a Go type in the mapping's version or returns an error.
func (i *Info) versioned(convertor runtime.ObjectConvertor) (runtime.Object, error) {
return convertor.ConvertToVersion(i.Object, i.Mapping.GroupVersionKind.GroupVersion())
}
// AsVersioned returns the object as a Go object in the external form if possible (matching the
// group version kind of the mapping, or i.Object if it cannot be converted.
// Deprecated this function will be removed once calling code is updated to indicate the correct
// negoticatedserializers during construction of the builder
func (i *Info) AsVersioned(convertor runtime.ObjectConvertor) runtime.Object {
if obj, err := i.versioned(convertor); err == nil {
return obj
}
return i.Object
}
// VisitorList implements Visit for the sub visitors it contains. The first error // VisitorList implements Visit for the sub visitors it contains. The first error
// returned from a child Visitor will terminate iteration. // returned from a child Visitor will terminate iteration.
type VisitorList []Visitor type VisitorList []Visitor

View File

@ -71,18 +71,6 @@ func init() {
"PersistentVolume", "PersistentVolume",
"ComponentStatus", "ComponentStatus",
), ),
IgnoredKinds: sets.NewString(
"ListOptions",
"DeleteOptions",
"Status",
"PodLogOptions",
"PodExecOptions",
"PodAttachOptions",
"PodPortForwardOptions",
"PodProxyOptions",
"NodeProxyOptions",
"ServiceProxyOptions",
),
}, },
announced.VersionToSchemeFunc{ announced.VersionToSchemeFunc{
corev1.SchemeGroupVersion.Version: corev1.AddToScheme, corev1.SchemeGroupVersion.Version: corev1.AddToScheme,

View File

@ -30,6 +30,7 @@ go_test(
"//pkg/api/legacyscheme:go_default_library", "//pkg/api/legacyscheme:go_default_library",
"//pkg/apis/core:go_default_library", "//pkg/apis/core:go_default_library",
"//pkg/kubeapiserver/admission:go_default_library", "//pkg/kubeapiserver/admission:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime: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/runtime/schema:go_default_library",

View File

@ -20,6 +20,7 @@ import (
"strings" "strings"
"testing" "testing"
"k8s.io/apimachinery/pkg/api/meta/testrestmapper"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
@ -87,7 +88,7 @@ func newGCPermissionsEnforcement() (*gcPermissionsEnforcement, error) {
} }
genericPluginInitializer := initializer.New(nil, nil, fakeAuthorizer{}, nil) genericPluginInitializer := initializer.New(nil, nil, fakeAuthorizer{}, nil)
pluginInitializer := kubeadmission.NewPluginInitializer(nil, nil, nil, legacyscheme.Registry.RESTMapper(), nil) pluginInitializer := kubeadmission.NewPluginInitializer(nil, nil, nil, testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme), nil)
initializersChain := admission.PluginInitializers{} initializersChain := admission.PluginInitializers{}
initializersChain = append(initializersChain, genericPluginInitializer) initializersChain = append(initializersChain, genericPluginInitializer)
initializersChain = append(initializersChain, pluginInitializer) initializersChain = append(initializersChain, pluginInitializer)

View File

@ -65,6 +65,7 @@ filegroup(
srcs = [ srcs = [
":package-srcs", ":package-srcs",
"//staging/src/k8s.io/apimachinery/pkg/api/meta/table:all-srcs", "//staging/src/k8s.io/apimachinery/pkg/api/meta/table:all-srcs",
"//staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper:all-srcs",
], ],
tags = ["automanaged"], tags = ["automanaged"],
) )

View File

@ -0,0 +1,30 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["test_restmapper.go"],
importpath = "k8s.io/apimachinery/pkg/api/meta/testrestmapper",
visibility = ["//visibility:public"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery/registered: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/sets: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

@ -0,0 +1,132 @@
/*
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/apimachinery"
"k8s.io/apimachinery/pkg/apimachinery/registered"
"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 perferred version, legacy
// kube any version, extensions any version, metrics any version, all other groups alphabetical preferred version,
// all other groups alphabetical.
func TestOnlyStaticRESTMapper(m *registered.APIRegistrationManager, scheme *runtime.Scheme, versionPatterns ...schema.GroupVersion) meta.RESTMapper {
unionMapper := meta.MultiRESTMapper{}
unionedGroups := sets.NewString()
for _, enabledVersion := range m.RegisteredGroupVersions() {
if !unionedGroups.Has(enabledVersion.Group) {
unionedGroups.Insert(enabledVersion.Group)
groupMeta := m.GroupOrDie(enabledVersion.Group)
if groupMeta != nil {
unionMapper = append(unionMapper, newRESTMapper(scheme, groupMeta))
}
}
}
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(m, prioritizedGroups...)
prioritizedGroupsSet := sets.NewString(prioritizedGroups...)
remainingGroups := sets.String{}
for _, enabledVersion := range m.RegisteredGroupVersions() {
if !prioritizedGroupsSet.Has(enabledVersion.Group) {
remainingGroups.Insert(enabledVersion.Group)
}
}
remainingResourcePriority, remainingKindPriority := prioritiesForGroups(m, 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(m *registered.APIRegistrationManager, groups ...string) ([]schema.GroupVersionResource, []schema.GroupVersionKind) {
resourcePriority := []schema.GroupVersionResource{}
kindPriority := []schema.GroupVersionKind{}
for _, group := range groups {
availableVersions := m.RegisteredVersionsForGroup(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(scheme *runtime.Scheme, groupMeta *apimachinery.GroupMeta) meta.RESTMapper {
// the list of kinds that are scoped at the root of the api hierarchy
// if a kind is not enumerated here, it is assumed to have a namespace scope
rootScoped := sets.NewString()
if groupMeta.RootScopedKinds != nil {
rootScoped = groupMeta.RootScopedKinds
}
mapper := meta.NewDefaultRESTMapper(groupMeta.GroupVersions)
for _, gv := range groupMeta.GroupVersions {
for kind := range scheme.KnownTypes(gv) {
if ignoredKinds.Has(kind) {
continue
}
scope := meta.RESTScopeNamespace
if rootScoped.Has(kind) {
scope = meta.RESTScopeRoot
}
mapper.Add(gv.WithKind(kind), scope)
}
}
return mapper
}
// 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

@ -13,7 +13,6 @@ go_library(
], ],
importpath = "k8s.io/apimachinery/pkg/apimachinery", importpath = "k8s.io/apimachinery/pkg/apimachinery",
deps = [ deps = [
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
], ],

View File

@ -11,7 +11,6 @@ go_library(
importpath = "k8s.io/apimachinery/pkg/apimachinery/announced", importpath = "k8s.io/apimachinery/pkg/apimachinery/announced",
deps = [ deps = [
"//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apimachinery:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",

View File

@ -21,7 +21,6 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/apimachinery" "k8s.io/apimachinery/pkg/apimachinery"
"k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/apimachinery/registered"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
@ -49,7 +48,6 @@ type GroupMetaFactoryArgs struct {
VersionPreferenceOrder []string VersionPreferenceOrder []string
// RootScopedKinds are resources that are not namespaced. // RootScopedKinds are resources that are not namespaced.
RootScopedKinds sets.String // nil is allowed RootScopedKinds sets.String // nil is allowed
IgnoredKinds sets.String // nil is allowed
// May be nil if there are no internal objects. // May be nil if there are no internal objects.
AddInternalObjectsToScheme SchemeFunc AddInternalObjectsToScheme SchemeFunc
@ -154,40 +152,9 @@ func (gmf *GroupMetaFactory) Register(m *registered.APIRegistrationManager, sche
GroupVersions: externalVersions, GroupVersions: externalVersions,
RootScopedKinds: gmf.GroupArgs.RootScopedKinds, RootScopedKinds: gmf.GroupArgs.RootScopedKinds,
} }
groupMeta.RESTMapper = gmf.newRESTMapper(scheme, externalVersions, groupMeta)
if err := m.RegisterGroup(*groupMeta); err != nil { if err := m.RegisterGroup(*groupMeta); err != nil {
return err return err
} }
return nil return nil
}
func (gmf *GroupMetaFactory) newRESTMapper(scheme *runtime.Scheme, externalVersions []schema.GroupVersion, groupMeta *apimachinery.GroupMeta) meta.RESTMapper {
// the list of kinds that are scoped at the root of the api hierarchy
// if a kind is not enumerated here, it is assumed to have a namespace scope
rootScoped := sets.NewString()
if gmf.GroupArgs.RootScopedKinds != nil {
rootScoped = gmf.GroupArgs.RootScopedKinds
}
ignoredKinds := sets.NewString()
if gmf.GroupArgs.IgnoredKinds != nil {
ignoredKinds = gmf.GroupArgs.IgnoredKinds
}
mapper := meta.NewDefaultRESTMapper(externalVersions)
for _, gv := range externalVersions {
for kind := range scheme.KnownTypes(gv) {
if ignoredKinds.Has(kind) {
continue
}
scope := meta.RESTScopeNamespace
if rootScoped.Has(kind) {
scope = meta.RESTScopeRoot
}
mapper.Add(gv.WithKind(kind), scope)
}
}
return mapper
} }

View File

@ -21,10 +21,8 @@ go_library(
srcs = ["registered.go"], srcs = ["registered.go"],
importpath = "k8s.io/apimachinery/pkg/apimachinery/registered", importpath = "k8s.io/apimachinery/pkg/apimachinery/registered",
deps = [ deps = [
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apimachinery:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
], ],
) )

View File

@ -22,10 +22,8 @@ import (
"sort" "sort"
"strings" "strings"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/apimachinery" "k8s.io/apimachinery/pkg/apimachinery"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets"
) )
// APIRegistrationManager provides the concept of what API groups are enabled. // APIRegistrationManager provides the concept of what API groups are enabled.
@ -140,73 +138,6 @@ func (m *APIRegistrationManager) GroupOrDie(group string) *apimachinery.GroupMet
return &groupMetaCopy return &groupMetaCopy
} }
// RESTMapper 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 perferred version, legacy
// kube any version, extensions any version, metrics any version, all other groups alphabetical preferred version,
// all other groups alphabetical.
func (m *APIRegistrationManager) RESTMapper(versionPatterns ...schema.GroupVersion) meta.RESTMapper {
unionMapper := meta.MultiRESTMapper{}
unionedGroups := sets.NewString()
for enabledVersion := range m.registeredVersions {
if !unionedGroups.Has(enabledVersion.Group) {
unionedGroups.Insert(enabledVersion.Group)
groupMeta := m.groupMetaMap[enabledVersion.Group]
if groupMeta != nil {
unionMapper = append(unionMapper, groupMeta.RESTMapper)
}
}
}
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 := m.prioritiesForGroups(prioritizedGroups...)
prioritizedGroupsSet := sets.NewString(prioritizedGroups...)
remainingGroups := sets.String{}
for enabledVersion := range m.registeredVersions {
if !prioritizedGroupsSet.Has(enabledVersion.Group) {
remainingGroups.Insert(enabledVersion.Group)
}
}
remainingResourcePriority, remainingKindPriority := m.prioritiesForGroups(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 (m *APIRegistrationManager) prioritiesForGroups(groups ...string) ([]schema.GroupVersionResource, []schema.GroupVersionKind) {
resourcePriority := []schema.GroupVersionResource{}
kindPriority := []schema.GroupVersionKind{}
for _, group := range groups {
availableVersions := m.RegisteredVersionsForGroup(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
}
// AllPreferredGroupVersions returns the preferred versions of all registered // AllPreferredGroupVersions returns the preferred versions of all registered
// groups in the form of "group1/version1,group2/version2,..." // groups in the form of "group1/version1,group2/version2,..."
func (m *APIRegistrationManager) AllPreferredGroupVersions() string { func (m *APIRegistrationManager) AllPreferredGroupVersions() string {

View File

@ -17,7 +17,6 @@ limitations under the License.
package apimachinery package apimachinery
import ( import (
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
) )
@ -28,8 +27,4 @@ type GroupMeta struct {
GroupVersions []schema.GroupVersion GroupVersions []schema.GroupVersion
RootScopedKinds sets.String RootScopedKinds sets.String
// RESTMapper provides the default mapping between REST paths and the objects declared in a Scheme and all known
// versions.
RESTMapper meta.RESTMapper
} }

View File

@ -16,7 +16,6 @@ go_test(
embed = [":go_default_library"], embed = [":go_default_library"],
deps = [ deps = [
"//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apimachinery:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",

View File

@ -34,7 +34,6 @@ import (
// "github.com/go-openapi/spec" // "github.com/go-openapi/spec"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/apimachinery" "k8s.io/apimachinery/pkg/apimachinery"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
@ -153,13 +152,8 @@ func TestInstallAPIGroups(t *testing.T) {
scheme.AddKnownTypes(v1GroupVersion, &metav1.Status{}) scheme.AddKnownTypes(v1GroupVersion, &metav1.Status{})
metav1.AddToGroupVersion(scheme, v1GroupVersion) metav1.AddToGroupVersion(scheme, v1GroupVersion)
mapper := meta.NewDefaultRESTMapper([]schema.GroupVersion{gv})
for kind := range scheme.KnownTypes(gv) {
mapper.Add(gv.WithKind(kind), meta.RESTScopeNamespace)
}
groupMeta := apimachinery.GroupMeta{ groupMeta := apimachinery.GroupMeta{
GroupVersions: []schema.GroupVersion{gv}, GroupVersions: []schema.GroupVersion{gv},
RESTMapper: mapper,
} }
return APIGroupInfo{ return APIGroupInfo{

View File

@ -147,8 +147,11 @@ func TestServerSidePrint(t *testing.T) {
printer := newFakePrinter(printersinternal.AddHandlers) printer := newFakePrinter(printersinternal.AddHandlers)
factory := util.NewFactory(clientcmd.NewDefaultClientConfig(*createKubeConfig(s.URL), &clientcmd.ConfigOverrides{})) factory := util.NewFactory(clientcmd.NewDefaultClientConfig(*createKubeConfig(s.URL), &clientcmd.ConfigOverrides{}))
mapper := factory.RESTMapper() mapper, err := factory.RESTMapper()
if err != nil {
t.Errorf("unexpected error getting mapper: %v", err)
return
}
for gvk, apiType := range legacyscheme.Scheme.AllKnownTypes() { for gvk, apiType := range legacyscheme.Scheme.AllKnownTypes() {
// we do not care about internal objects or lists // TODO make sure this is always true // we do not care about internal objects or lists // TODO make sure this is always true
if gvk.Version == runtime.APIVersionInternal || strings.HasSuffix(apiType.Name(), "List") { if gvk.Version == runtime.APIVersionInternal || strings.HasSuffix(apiType.Name(), "List") {

View File

@ -21,7 +21,6 @@ go_test(
"//cmd/kube-apiserver/app/options:go_default_library", "//cmd/kube-apiserver/app/options:go_default_library",
"//pkg/api/legacyscheme:go_default_library", "//pkg/api/legacyscheme:go_default_library",
"//pkg/apis/core:go_default_library", "//pkg/apis/core:go_default_library",
"//pkg/kubectl/cmd/util:go_default_library",
"//pkg/master:go_default_library", "//pkg/master:go_default_library",
"//test/integration:go_default_library", "//test/integration:go_default_library",
"//test/integration/framework:go_default_library", "//test/integration/framework:go_default_library",
@ -38,10 +37,10 @@ go_test(
"//vendor/k8s.io/apiserver/pkg/server:go_default_library", "//vendor/k8s.io/apiserver/pkg/server:go_default_library",
"//vendor/k8s.io/apiserver/pkg/server/options:go_default_library", "//vendor/k8s.io/apiserver/pkg/server/options:go_default_library",
"//vendor/k8s.io/apiserver/pkg/storage/storagebackend:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/storagebackend:go_default_library",
"//vendor/k8s.io/client-go/discovery:go_default_library",
"//vendor/k8s.io/client-go/discovery/cached:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library",
"//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library",
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
"//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library",
"//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library",
], ],
) )

View File

@ -43,16 +43,15 @@ import (
genericapiserver "k8s.io/apiserver/pkg/server" genericapiserver "k8s.io/apiserver/pkg/server"
genericapiserveroptions "k8s.io/apiserver/pkg/server/options" genericapiserveroptions "k8s.io/apiserver/pkg/server/options"
"k8s.io/apiserver/pkg/storage/storagebackend" "k8s.io/apiserver/pkg/storage/storagebackend"
"k8s.io/client-go/discovery"
cacheddiscovery "k8s.io/client-go/discovery/cached"
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"k8s.io/client-go/util/flowcontrol" "k8s.io/client-go/util/flowcontrol"
"k8s.io/kubernetes/cmd/kube-apiserver/app" "k8s.io/kubernetes/cmd/kube-apiserver/app"
"k8s.io/kubernetes/cmd/kube-apiserver/app/options" "k8s.io/kubernetes/cmd/kube-apiserver/app/options"
"k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/legacyscheme"
kapi "k8s.io/kubernetes/pkg/apis/core" kapi "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/test/integration" "k8s.io/kubernetes/test/integration"
"k8s.io/kubernetes/test/integration/framework" "k8s.io/kubernetes/test/integration/framework"
@ -434,84 +433,84 @@ var etcdStorageData = map[schema.GroupVersionResource]struct {
var ephemeralWhiteList = createEphemeralWhiteList( var ephemeralWhiteList = createEphemeralWhiteList(
// k8s.io/kubernetes/pkg/api/v1 // k8s.io/kubernetes/pkg/api/v1
gvr("", "v1", "bindings"), // annotation on pod, not stored in etcd gvk("", "v1", "Binding"), // annotation on pod, not stored in etcd
gvr("", "v1", "rangeallocations"), // stored in various places in etcd but cannot be directly created gvk("", "v1", "RangeAllocation"), // stored in various places in etcd but cannot be directly created
gvr("", "v1", "componentstatuses"), // status info not stored in etcd gvk("", "v1", "ComponentStatus"), // status info not stored in etcd
gvr("", "v1", "serializedreferences"), // used for serilization, not stored in etcd gvk("", "v1", "SerializedReference"), // used for serilization, not stored in etcd
gvr("", "v1", "nodeconfigsources"), // subfield of node.spec, but shouldn't be directly created gvk("", "v1", "NodeConfigSource"), // subfield of node.spec, but shouldn't be directly created
gvr("", "v1", "podstatusresults"), // wrapper object not stored in etcd gvk("", "v1", "PodStatusResult"), // wrapper object not stored in etcd
// -- // --
// k8s.io/kubernetes/pkg/apis/authentication/v1beta1 // k8s.io/kubernetes/pkg/apis/authentication/v1beta1
gvr("authentication.k8s.io", "v1beta1", "tokenreviews"), // not stored in etcd gvk("authentication.k8s.io", "v1beta1", "TokenReview"), // not stored in etcd
// -- // --
// k8s.io/kubernetes/pkg/apis/authentication/v1 // k8s.io/kubernetes/pkg/apis/authentication/v1
gvr("authentication.k8s.io", "v1", "tokenreviews"), // not stored in etcd gvk("authentication.k8s.io", "v1", "TokenReview"), // not stored in etcd
gvr("authentication.k8s.io", "v1", "tokenrequests"), // not stored in etcd gvk("authentication.k8s.io", "v1", "TokenRequest"), // not stored in etcd
// -- // --
// k8s.io/kubernetes/pkg/apis/authorization/v1beta1 // k8s.io/kubernetes/pkg/apis/authorization/v1beta1
// SRR objects that are not stored in etcd // SRR objects that are not stored in etcd
gvr("authorization.k8s.io", "v1beta1", "selfsubjectrulesreviews"), gvk("authorization.k8s.io", "v1beta1", "SelfSubjectRulesReview"),
// SAR objects that are not stored in etcd // SAR objects that are not stored in etcd
gvr("authorization.k8s.io", "v1beta1", "selfsubjectaccessreviews"), gvk("authorization.k8s.io", "v1beta1", "SelfSubjectAccessReview"),
gvr("authorization.k8s.io", "v1beta1", "localsubjectaccessreviews"), gvk("authorization.k8s.io", "v1beta1", "LocalSubjectAccessReview"),
gvr("authorization.k8s.io", "v1beta1", "subjectaccessreviews"), gvk("authorization.k8s.io", "v1beta1", "SubjectAccessReview"),
// -- // --
// k8s.io/kubernetes/pkg/apis/authorization/v1 // k8s.io/kubernetes/pkg/apis/authorization/v1
// SRR objects that are not stored in etcd // SRR objects that are not stored in etcd
gvr("authorization.k8s.io", "v1", "selfsubjectrulesreviews"), gvk("authorization.k8s.io", "v1", "SelfSubjectRulesReview"),
// SAR objects that are not stored in etcd // SAR objects that are not stored in etcd
gvr("authorization.k8s.io", "v1", "selfsubjectaccessreviews"), gvk("authorization.k8s.io", "v1", "SelfSubjectAccessReview"),
gvr("authorization.k8s.io", "v1", "localsubjectaccessreviews"), gvk("authorization.k8s.io", "v1", "LocalSubjectAccessReview"),
gvr("authorization.k8s.io", "v1", "subjectaccessreviews"), gvk("authorization.k8s.io", "v1", "SubjectAccessReview"),
// -- // --
// k8s.io/kubernetes/pkg/apis/autoscaling/v1 // k8s.io/kubernetes/pkg/apis/autoscaling/v1
gvr("autoscaling", "v1", "scales"), // not stored in etcd, part of kapiv1.ReplicationController gvk("autoscaling", "v1", "Scale"), // not stored in etcd, part of kapiv1.ReplicationController
// -- // --
// k8s.io/kubernetes/pkg/apis/apps/v1beta1 // k8s.io/kubernetes/pkg/apis/apps/v1beta1
gvr("apps", "v1beta1", "scales"), // not stored in etcd, part of kapiv1.ReplicationController gvk("apps", "v1beta1", "Scale"), // not stored in etcd, part of kapiv1.ReplicationController
gvr("apps", "v1beta1", "deploymentrollbacks"), // used to rollback deployment, not stored in etcd gvk("apps", "v1beta1", "DeploymentRollback"), // used to rollback deployment, not stored in etcd
// -- // --
// k8s.io/kubernetes/pkg/apis/apps/v1beta2 // k8s.io/kubernetes/pkg/apis/apps/v1beta2
gvr("apps", "v1beta2", "scales"), // not stored in etcd, part of kapiv1.ReplicationController gvk("apps", "v1beta2", "Scale"), // not stored in etcd, part of kapiv1.ReplicationController
// -- // --
// k8s.io/kubernetes/pkg/apis/batch/v1beta1 // k8s.io/kubernetes/pkg/apis/batch/v1beta1
gvr("batch", "v1beta1", "jobtemplates"), // not stored in etcd gvk("batch", "v1beta1", "JobTemplate"), // not stored in etcd
// -- // --
// k8s.io/kubernetes/pkg/apis/batch/v2alpha1 // k8s.io/kubernetes/pkg/apis/batch/v2alpha1
gvr("batch", "v2alpha1", "jobtemplates"), // not stored in etcd gvk("batch", "v2alpha1", "JobTemplate"), // not stored in etcd
// -- // --
// k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1 // k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1
gvr("componentconfig", "v1alpha1", "kubeschedulerconfigurations"), // not stored in etcd gvk("componentconfig", "v1alpha1", "KubeSchedulerConfiguration"), // not stored in etcd
// -- // --
// k8s.io/kubernetes/pkg/apis/extensions/v1beta1 // k8s.io/kubernetes/pkg/apis/extensions/v1beta1
gvr("extensions", "v1beta1", "deploymentrollbacks"), // used to rollback deployment, not stored in etcd gvk("extensions", "v1beta1", "DeploymentRollback"), // used to rollback deployment, not stored in etcd
gvr("extensions", "v1beta1", "replicationcontrollerdummies"), // not stored in etcd gvk("extensions", "v1beta1", "ReplicationControllerDummy"), // not stored in etcd
gvr("extensions", "v1beta1", "scales"), // not stored in etcd, part of kapiv1.ReplicationController gvk("extensions", "v1beta1", "Scale"), // not stored in etcd, part of kapiv1.ReplicationController
// -- // --
// k8s.io/kubernetes/pkg/apis/imagepolicy/v1alpha1 // k8s.io/kubernetes/pkg/apis/imagepolicy/v1alpha1
gvr("imagepolicy.k8s.io", "v1alpha1", "imagereviews"), // not stored in etcd gvk("imagepolicy.k8s.io", "v1alpha1", "ImageReview"), // not stored in etcd
// -- // --
// k8s.io/kubernetes/pkg/apis/policy/v1beta1 // k8s.io/kubernetes/pkg/apis/policy/v1beta1
gvr("policy", "v1beta1", "evictions"), // not stored in etcd, deals with evicting kapiv1.Pod gvk("policy", "v1beta1", "Eviction"), // not stored in etcd, deals with evicting kapiv1.Pod
// -- // --
// k8s.io/kubernetes/pkg/apis/admission/v1beta1 // k8s.io/kubernetes/pkg/apis/admission/v1beta1
gvr("admission.k8s.io", "v1beta1", "admissionreviews"), // not stored in etcd, call out to webhooks. gvk("admission.k8s.io", "v1beta1", "AdmissionReview"), // not stored in etcd, call out to webhooks.
// -- // --
) )
@ -561,7 +560,7 @@ func TestEtcdStoragePath(t *testing.T) {
kindSeen := sets.NewString() kindSeen := sets.NewString()
pathSeen := map[string][]schema.GroupVersionResource{} pathSeen := map[string][]schema.GroupVersionResource{}
etcdSeen := map[schema.GroupVersionResource]empty{} etcdSeen := map[schema.GroupVersionResource]empty{}
ephemeralSeen := map[schema.GroupVersionResource]empty{} ephemeralSeen := map[schema.GroupVersionKind]empty{}
cohabitatingResources := map[string]map[schema.GroupVersionKind]empty{} cohabitatingResources := map[string]map[schema.GroupVersionKind]empty{}
for gvk, apiType := range legacyscheme.Scheme.AllKnownTypes() { for gvk, apiType := range legacyscheme.Scheme.AllKnownTypes() {
@ -577,6 +576,11 @@ func TestEtcdStoragePath(t *testing.T) {
kindSeen.Insert(kind) kindSeen.Insert(kind)
continue continue
} }
_, isEphemeral := ephemeralWhiteList[gvk]
if isEphemeral {
ephemeralSeen[gvk] = empty{}
continue
}
mapping, err := mapper.RESTMapping(gvk.GroupKind(), gvk.Version) mapping, err := mapper.RESTMapping(gvk.GroupKind(), gvk.Version)
if err != nil { if err != nil {
@ -588,25 +592,12 @@ func TestEtcdStoragePath(t *testing.T) {
etcdSeen[gvResource] = empty{} etcdSeen[gvResource] = empty{}
testData, hasTest := etcdStorageData[gvResource] testData, hasTest := etcdStorageData[gvResource]
_, isEphemeral := ephemeralWhiteList[gvResource]
if !hasTest && !isEphemeral { if !hasTest {
t.Errorf("no test data for %s from %s. Please add a test for your new type to etcdStorageData.", kind, pkgPath) t.Errorf("no test data for %s from %s. Please add a test for your new type to etcdStorageData.", kind, pkgPath)
continue continue
} }
if hasTest && isEphemeral {
t.Errorf("duplicate test data for %s from %s. Object has both test data and is ephemeral.", kind, pkgPath)
continue
}
if isEphemeral { // TODO it would be nice if we could remove this and infer if an object is not stored in etcd
// t.Logf("Skipping test for %s from %s", kind, pkgPath)
ephemeralSeen[gvResource] = empty{}
delete(etcdSeen, gvResource)
continue
}
if len(testData.expectedEtcdPath) == 0 { if len(testData.expectedEtcdPath) == 0 {
t.Errorf("empty test data for %s from %s", kind, pkgPath) t.Errorf("empty test data for %s from %s", kind, pkgPath)
continue continue
@ -811,7 +802,11 @@ func startRealMasterOrDie(t *testing.T, certDir string) (*allClient, clientv3.KV
t.Fatal(err) t.Fatal(err)
} }
mapper := util.NewFactory(clientcmd.NewDefaultClientConfig(*clientcmdapi.NewConfig(), &clientcmd.ConfigOverrides{})).RESTMapper() discoveryClient := cacheddiscovery.NewMemCacheClient(kubeClient.Discovery())
restMapper := discovery.NewDeferredDiscoveryRESTMapper(discoveryClient)
restMapper.Reset()
// allow conversion between typed and unstructured objects
mapper := discovery.NewDeferredDiscoveryRESTMapper(discoveryClient)
return client, kvClient, mapper return client, kvClient, mapper
} }
@ -888,17 +883,21 @@ func gvr(g, v, r string) schema.GroupVersionResource {
return schema.GroupVersionResource{Group: g, Version: v, Resource: r} return schema.GroupVersionResource{Group: g, Version: v, Resource: r}
} }
func gvk(g, v, k string) schema.GroupVersionKind {
return schema.GroupVersionKind{Group: g, Version: v, Kind: k}
}
func gvkP(g, v, k string) *schema.GroupVersionKind { func gvkP(g, v, k string) *schema.GroupVersionKind {
return &schema.GroupVersionKind{Group: g, Version: v, Kind: k} return &schema.GroupVersionKind{Group: g, Version: v, Kind: k}
} }
func createEphemeralWhiteList(gvrs ...schema.GroupVersionResource) map[schema.GroupVersionResource]empty { func createEphemeralWhiteList(gvks ...schema.GroupVersionKind) map[schema.GroupVersionKind]empty {
ephemeral := map[schema.GroupVersionResource]empty{} ephemeral := map[schema.GroupVersionKind]empty{}
for _, gvResource := range gvrs { for _, gvKind := range gvks {
if _, ok := ephemeral[gvResource]; ok { if _, ok := ephemeral[gvKind]; ok {
panic("invalid ephemeral whitelist contains duplicate keys") panic("invalid ephemeral whitelist contains duplicate keys")
} }
ephemeral[gvResource] = empty{} ephemeral[gvKind] = empty{}
} }
return ephemeral return ephemeral
} }