diff --git a/pkg/api/testapi/BUILD b/pkg/api/testapi/BUILD index 6c6f853f595..3e33f7c7afd 100644 --- a/pkg/api/testapi/BUILD +++ b/pkg/api/testapi/BUILD @@ -48,7 +48,6 @@ go_library( "//pkg/apis/settings/install:go_default_library", "//pkg/apis/storage: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/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer/recognizer:go_default_library", diff --git a/pkg/api/testapi/testapi.go b/pkg/api/testapi/testapi.go index 20b3c7f43c5..6b6e7214761 100644 --- a/pkg/api/testapi/testapi.go +++ b/pkg/api/testapi/testapi.go @@ -30,7 +30,6 @@ import ( "reflect" "strings" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/serializer/recognizer" @@ -473,51 +472,3 @@ func (g TestGroup) SubResourcePath(resource, namespace, name, sub string) string 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} -} diff --git a/pkg/apis/core/install/BUILD b/pkg/apis/core/install/BUILD index f3fd44f73a8..305c8f924fb 100644 --- a/pkg/apis/core/install/BUILD +++ b/pkg/apis/core/install/BUILD @@ -31,7 +31,6 @@ go_test( "//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/runtime:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", ], ) diff --git a/pkg/apis/core/install/install.go b/pkg/apis/core/install/install.go index 99a251fb66f..ae6e99c0aad 100644 --- a/pkg/apis/core/install/install.go +++ b/pkg/apis/core/install/install.go @@ -45,18 +45,6 @@ func Install(registry *registered.APIRegistrationManager, scheme *runtime.Scheme "PersistentVolume", "ComponentStatus", ), - IgnoredKinds: sets.NewString( - "ListOptions", - "DeleteOptions", - "Status", - "PodLogOptions", - "PodExecOptions", - "PodAttachOptions", - "PodPortForwardOptions", - "PodProxyOptions", - "NodeProxyOptions", - "ServiceProxyOptions", - ), }, announced.VersionToSchemeFunc{ v1.SchemeGroupVersion.Version: v1.AddToScheme, diff --git a/pkg/apis/core/install/install_test.go b/pkg/apis/core/install/install_test.go index 677bfa8b253..e373f059f32 100644 --- a/pkg/apis/core/install/install_test.go +++ b/pkg/apis/core/install/install_test.go @@ -24,7 +24,6 @@ import ( "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/kubernetes/pkg/api/legacyscheme" 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) { for _, obj := range []runtime.Object{ &metav1.Status{}, diff --git a/pkg/apis/core/validation/BUILD b/pkg/apis/core/validation/BUILD index e5ddd2814ac..482ab99b643 100644 --- a/pkg/apis/core/validation/BUILD +++ b/pkg/apis/core/validation/BUILD @@ -14,7 +14,6 @@ go_library( importpath = "k8s.io/kubernetes/pkg/apis/core/validation", visibility = ["//visibility:public"], deps = [ - "//pkg/api/legacyscheme:go_default_library", "//pkg/api/service:go_default_library", "//pkg/apis/core: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/k8s.io/api/core/v1: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/validation: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/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/intstr:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", diff --git a/pkg/apis/core/validation/events.go b/pkg/apis/core/validation/events.go index ab265bd7644..8a860aba9c1 100644 --- a/pkg/apis/core/validation/events.go +++ b/pkg/apis/core/validation/events.go @@ -20,12 +20,9 @@ import ( "fmt" "time" - "k8s.io/apimachinery/pkg/api/meta" 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/field" - "k8s.io/kubernetes/pkg/api/legacyscheme" "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) { allErrs = append(allErrs, field.Invalid(field.NewPath("namespace"), event.Namespace, msg)) } 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 -} diff --git a/pkg/controller/garbagecollector/BUILD b/pkg/controller/garbagecollector/BUILD index 1ef247e2447..6fca5ce338e 100644 --- a/pkg/controller/garbagecollector/BUILD +++ b/pkg/controller/garbagecollector/BUILD @@ -58,6 +58,7 @@ go_test( "//vendor/github.com/stretchr/testify/assert: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/testrestmapper: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/serializer:go_default_library", diff --git a/pkg/controller/garbagecollector/garbagecollector_test.go b/pkg/controller/garbagecollector/garbagecollector_test.go index 79b296fc8ec..aadbf179c6c 100644 --- a/pkg/controller/garbagecollector/garbagecollector_test.go +++ b/pkg/controller/garbagecollector/garbagecollector_test.go @@ -32,6 +32,7 @@ import ( "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/api/meta/testrestmapper" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/serializer" @@ -60,7 +61,7 @@ func TestGarbageCollectorConstruction(t *testing.T) { config := &restclient.Config{} config.ContentConfig.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: metaonly.NewMetadataCodecFactory()} 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) config.ContentConfig.NegotiatedSerializer = nil clientPool := dynamic.NewClientPool(config, rm, dynamic.LegacyAPIPathResolverFunc) @@ -190,15 +191,15 @@ type garbageCollector struct { func setupGC(t *testing.T, config *restclient.Config) garbageCollector { 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 - 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"}: {}} client := fake.NewSimpleClientset() sharedInformers := informers.NewSharedInformerFactory(client, 0) alwaysStarted := make(chan struct{}) 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 { t.Fatal(err) } @@ -433,7 +434,7 @@ func TestGCListWatcher(t *testing.T) { testHandler := &fakeActionHandler{} srv, clientConfig := testServerAndClientConfig(testHandler.ServeHTTP) 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"} client, err := clientPool.ClientForGroupVersionResource(podResource) if err != nil { @@ -822,7 +823,7 @@ func TestGarbageCollectorSync(t *testing.T) { t.Fatal(err) } - rm := &testRESTMapper{legacyscheme.Registry.RESTMapper()} + rm := &testRESTMapper{testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme)} metaOnlyClientPool := dynamic.NewClientPool(clientConfig, rm, dynamic.LegacyAPIPathResolverFunc) clientPool := dynamic.NewClientPool(clientConfig, rm, dynamic.LegacyAPIPathResolverFunc) podResource := map[schema.GroupVersionResource]struct{}{ diff --git a/pkg/controller/podautoscaler/BUILD b/pkg/controller/podautoscaler/BUILD index 7313619df2f..5e9ec7ffa8b 100644 --- a/pkg/controller/podautoscaler/BUILD +++ b/pkg/controller/podautoscaler/BUILD @@ -69,6 +69,7 @@ go_test( "//vendor/k8s.io/api/autoscaling/v1:go_default_library", "//vendor/k8s.io/api/autoscaling/v2beta1: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/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", diff --git a/pkg/controller/podautoscaler/horizontal_test.go b/pkg/controller/podautoscaler/horizontal_test.go index 7788e1ec65d..95511e79cca 100644 --- a/pkg/controller/podautoscaler/horizontal_test.go +++ b/pkg/controller/podautoscaler/horizontal_test.go @@ -27,6 +27,7 @@ import ( autoscalingv1 "k8s.io/api/autoscaling/v1" autoscalingv2 "k8s.io/api/autoscaling/v2beta1" "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta/testrestmapper" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -511,7 +512,7 @@ func (tc *testCase) prepareTestClient(t *testing.T) (*fake.Clientset, *metricsfa } name := getForAction.GetName() - mapper := legacyscheme.Registry.RESTMapper() + mapper := testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme) metrics := &cmapi.MetricValueList{} var matchedTarget *autoscalingv2.MetricSpec for i, target := range tc.metricsTarget { @@ -649,7 +650,7 @@ func (tc *testCase) setupController(t *testing.T) (*HorizontalController, inform eventClient.Core(), testScaleClient, testClient.Autoscaling(), - legacyscheme.Registry.RESTMapper(), + testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme), replicaCalc, informerFactory.Autoscaling().V1().HorizontalPodAutoscalers(), controller.NoResyncPeriodFunc(), diff --git a/pkg/controller/podautoscaler/legacy_horizontal_test.go b/pkg/controller/podautoscaler/legacy_horizontal_test.go index 1254634d51e..3229b2352c9 100644 --- a/pkg/controller/podautoscaler/legacy_horizontal_test.go +++ b/pkg/controller/podautoscaler/legacy_horizontal_test.go @@ -30,6 +30,7 @@ import ( autoscalingv1 "k8s.io/api/autoscaling/v1" autoscalingv2 "k8s.io/api/autoscaling/v2beta1" "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta/testrestmapper" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -497,7 +498,7 @@ func (tc *legacyTestCase) runTest(t *testing.T) { eventClient.Core(), testScaleClient, testClient.Autoscaling(), - legacyscheme.Registry.RESTMapper(), + testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme), replicaCalc, informerFactory.Autoscaling().V1().HorizontalPodAutoscalers(), controller.NoResyncPeriodFunc(), diff --git a/pkg/controller/podautoscaler/metrics/BUILD b/pkg/controller/podautoscaler/metrics/BUILD index 7dd3d7acca1..92f686e883d 100644 --- a/pkg/controller/podautoscaler/metrics/BUILD +++ b/pkg/controller/podautoscaler/metrics/BUILD @@ -47,6 +47,7 @@ go_test( "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/k8s.io/api/autoscaling/v2beta1: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/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", diff --git a/pkg/controller/podautoscaler/metrics/rest_metrics_client_test.go b/pkg/controller/podautoscaler/metrics/rest_metrics_client_test.go index 26977f832d3..7275a752f0e 100644 --- a/pkg/controller/podautoscaler/metrics/rest_metrics_client_test.go +++ b/pkg/controller/podautoscaler/metrics/rest_metrics_client_test.go @@ -23,6 +23,7 @@ import ( autoscalingapi "k8s.io/api/autoscaling/v2beta1" "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta/testrestmapper" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -153,7 +154,7 @@ func (tc *restClientTestCase) prepareTestClient(t *testing.T) (*metricsfake.Clie return true, &metrics, nil } else { 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") gk := schema.FromAPIVersionAndKind(tc.singleObject.APIVersion, tc.singleObject.Kind).GroupKind() mapping, err := mapper.RESTMapping(gk) diff --git a/pkg/controller/podautoscaler/replica_calculator_test.go b/pkg/controller/podautoscaler/replica_calculator_test.go index b67bcc4710b..448d8100b8f 100644 --- a/pkg/controller/podautoscaler/replica_calculator_test.go +++ b/pkg/controller/podautoscaler/replica_calculator_test.go @@ -24,6 +24,7 @@ import ( autoscalingv2 "k8s.io/api/autoscaling/v2beta1" "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta/testrestmapper" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -221,7 +222,7 @@ func (tc *replicaCalcTestCase) prepareTestClient(t *testing.T) (*fake.Clientset, return true, &metrics, nil } name := getForAction.GetName() - mapper := legacyscheme.Registry.RESTMapper() + mapper := testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme) metrics := &cmapi.MetricValueList{} 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() diff --git a/pkg/kubectl/cmd/apply_set_last_applied.go b/pkg/kubectl/cmd/apply_set_last_applied.go index 032cc131ab4..40ca8841c60 100644 --- a/pkg/kubectl/cmd/apply_set_last_applied.go +++ b/pkg/kubectl/cmd/apply_set_last_applied.go @@ -25,7 +25,6 @@ import ( "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/types" - "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" @@ -46,7 +45,6 @@ type SetLastAppliedOptions struct { FilenameOptions resource.FilenameOptions infoList []*resource.Info - mapper meta.RESTMapper namespace string enforceNamespace bool dryRun bool @@ -117,7 +115,6 @@ func (o *SetLastAppliedOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) o.output = cmdutil.GetFlagString(cmd, "output") o.shortOutput = o.output == "name" - o.mapper = f.RESTMapper() var err error o.namespace, o.enforceNamespace, err = f.DefaultNamespace() if err != nil { @@ -205,7 +202,7 @@ func (o *SetLastAppliedOptions) RunSetLastApplied() error { } 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 } } diff --git a/pkg/kubectl/cmd/auth/cani.go b/pkg/kubectl/cmd/auth/cani.go index 7640a473f48..d0269f2f8a9 100644 --- a/pkg/kubectl/cmd/auth/cani.go +++ b/pkg/kubectl/cmd/auth/cani.go @@ -127,7 +127,10 @@ func (o *CanIOptions) Complete(f cmdutil.Factory, args []string) error { break } 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]) if len(resourceTokens) > 1 { o.ResourceName = resourceTokens[1] diff --git a/pkg/kubectl/cmd/autoscale.go b/pkg/kubectl/cmd/autoscale.go index 97534836e44..e1a0d61c518 100644 --- a/pkg/kubectl/cmd/autoscale.go +++ b/pkg/kubectl/cmd/autoscale.go @@ -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 { + var err error o.dryRun = cmdutil.GetFlagBool(cmd, "dry-run") o.createAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag) o.builder = f.NewBuilder() o.canBeAutoscaled = f.CanBeAutoscaled - o.mapper = f.RESTMapper() + o.mapper, err = f.RESTMapper() + if err != nil { + return err + } + o.clientForMapping = f.ClientForMapping o.args = args o.RecordFlags.Complete(f.Command(cmd, false)) - var err error o.Recorder, err = o.RecordFlags.ToRecorder() if err != nil { return err @@ -249,7 +253,7 @@ func (o *AutoscaleOptions) Run() error { if err != nil { 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 { @@ -266,7 +270,7 @@ func (o *AutoscaleOptions) Run() error { if err != nil { 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 { return err diff --git a/pkg/kubectl/cmd/certificates.go b/pkg/kubectl/cmd/certificates.go index d12db1e5a32..d7357cba955 100644 --- a/pkg/kubectl/cmd/certificates.go +++ b/pkg/kubectl/cmd/certificates.go @@ -228,7 +228,7 @@ func (options *CertificateOptions) modifyCertificateCondition(builder *resource. } found++ - return options.PrintObj(info.AsVersioned(legacyscheme.Scheme), options.Out) + return options.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), options.Out) }) if found == 0 { fmt.Fprintf(options.Out, "No resources found\n") diff --git a/pkg/kubectl/cmd/create/create.go b/pkg/kubectl/cmd/create/create.go index d4524e39790..e1dfc5b866b 100644 --- a/pkg/kubectl/cmd/create/create.go +++ b/pkg/kubectl/cmd/create/create.go @@ -389,7 +389,10 @@ func RunCreateSubcommand(f cmdutil.Factory, options *CreateSubcommandOptions) er if err != nil { return err } - mapper := f.RESTMapper() + mapper, err := f.RESTMapper() + if err != nil { + return err + } if !options.DryRun { // create subcommands have compiled knowledge of things they create, so type them directly 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 - obj = info.AsVersioned(legacyscheme.Scheme) + obj = cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping) } else { if meta, err := meta.Accessor(obj); err == nil && nsOverriden { meta.SetNamespace(namespace) diff --git a/pkg/kubectl/cmd/create/create_clusterrole_test.go b/pkg/kubectl/cmd/create/create_clusterrole_test.go index caddc639e13..8609e63c19e 100644 --- a/pkg/kubectl/cmd/create/create_clusterrole_test.go +++ b/pkg/kubectl/cmd/create/create_clusterrole_test.go @@ -437,8 +437,12 @@ func TestClusterRoleValidate(t *testing.T) { for name, test := range tests { t.Run(name, func(t *testing.T) { - test.clusterRoleOptions.Mapper = tf.RESTMapper() - err := test.clusterRoleOptions.Validate() + var err error + test.clusterRoleOptions.Mapper, err = tf.RESTMapper() + if err != nil { + t.Fatal(err) + } + err = test.clusterRoleOptions.Validate() if test.expectErr && err == nil { t.Errorf("%s: expect error happens, but validate passes.", name) } diff --git a/pkg/kubectl/cmd/create/create_role.go b/pkg/kubectl/cmd/create/create_role.go index 29895d51821..c3ba4130ae4 100644 --- a/pkg/kubectl/cmd/create/create_role.go +++ b/pkg/kubectl/cmd/create/create_role.go @@ -205,7 +205,10 @@ func (o *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args o.ResourceNames = resourceNames // 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.OutputFormat = cmdutil.GetFlagString(cmd, "output") diff --git a/pkg/kubectl/cmd/create/create_role_test.go b/pkg/kubectl/cmd/create/create_role_test.go index c1a75a3770e..bad465e4d48 100644 --- a/pkg/kubectl/cmd/create/create_role_test.go +++ b/pkg/kubectl/cmd/create/create_role_test.go @@ -339,8 +339,12 @@ func TestValidate(t *testing.T) { } for name, test := range tests { - test.roleOptions.Mapper = tf.RESTMapper() - err := test.roleOptions.Validate() + var err error + test.roleOptions.Mapper, err = tf.RESTMapper() + if err != nil { + t.Fatal(err) + } + err = test.roleOptions.Validate() if test.expectErr && err == nil { t.Errorf("%s: expect error happens but validate passes.", name) } diff --git a/pkg/kubectl/cmd/drain.go b/pkg/kubectl/cmd/drain.go index 92fe50d6d8e..db4ae94ef64 100644 --- a/pkg/kubectl/cmd/drain.go +++ b/pkg/kubectl/cmd/drain.go @@ -29,7 +29,6 @@ import ( corev1 "k8s.io/api/core/v1" policyv1beta1 "k8s.io/api/policy/v1beta1" apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" @@ -68,7 +67,6 @@ type DrainOptions struct { DeleteLocalData bool Selector string PodSelector string - mapper meta.RESTMapper nodeInfos []*resource.Info typer runtime.ObjectTyper @@ -741,7 +739,7 @@ func (o *DrainOptions) RunCordonOrUncordon(desired bool) error { fmt.Printf("error: %v", err) continue } - printer.PrintObj(nodeInfo.AsVersioned(legacyscheme.Scheme), o.Out) + printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(nodeInfo.Object, nodeInfo.Mapping), o.Out) } else { if !o.DryRun { helper := resource.NewHelper(o.restClient, nodeInfo.Mapping) @@ -767,7 +765,7 @@ func (o *DrainOptions) RunCordonOrUncordon(desired bool) error { fmt.Fprintf(o.ErrOut, "%v", err) continue } - printer.PrintObj(nodeInfo.AsVersioned(legacyscheme.Scheme), o.Out) + printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(nodeInfo.Object, nodeInfo.Mapping), o.Out) } } else { printer, err := o.ToPrinter("skipped") @@ -775,7 +773,7 @@ func (o *DrainOptions) RunCordonOrUncordon(desired bool) error { fmt.Fprintf(o.ErrOut, "%v", err) continue } - printer.PrintObj(nodeInfo.AsVersioned(legacyscheme.Scheme), o.Out) + printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(nodeInfo.Object, nodeInfo.Mapping), o.Out) } } diff --git a/pkg/kubectl/cmd/drain_test.go b/pkg/kubectl/cmd/drain_test.go index 34670e488dc..0d7219000a1 100644 --- a/pkg/kubectl/cmd/drain_test.go +++ b/pkg/kubectl/cmd/drain_test.go @@ -836,7 +836,6 @@ func TestDeletePods(t *testing.T) { o := DrainOptions{ PrintFlags: printers.NewPrintFlags("drained"), } - o.mapper = tf.RESTMapper() o.Out = os.Stdout o.ToPrinter = func(operation string) (printers.ResourcePrinterFunc, error) { diff --git a/pkg/kubectl/cmd/explain.go b/pkg/kubectl/cmd/explain.go index cf4793fee65..120cff94e67 100644 --- a/pkg/kubectl/cmd/explain.go +++ b/pkg/kubectl/cmd/explain.go @@ -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 { + var err error + o.Recursive = cmdutil.GetFlagBool(cmd, "recursive") 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() if err != nil { return err diff --git a/pkg/kubectl/cmd/expose.go b/pkg/kubectl/cmd/expose.go index a5d64a9589e..cf356e58b00 100644 --- a/pkg/kubectl/cmd/expose.go +++ b/pkg/kubectl/cmd/expose.go @@ -187,7 +187,10 @@ func (o *ExposeServiceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) e o.MapBasedSelectorForObject = f.MapBasedSelectorForObject o.PortsForObject = f.PortsForObject o.ProtocolsForObject = f.ProtocolsForObject - o.Mapper = f.RESTMapper() + o.Mapper, err = f.RESTMapper() + if err != nil { + return err + } o.LabelsForObject = f.LabelsForObject o.Namespace, o.EnforceNamespace, err = f.DefaultNamespace() @@ -336,7 +339,7 @@ func (o *ExposeServiceOptions) RunExpose(cmd *cobra.Command, args []string) erro 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 { return err diff --git a/pkg/kubectl/cmd/rollout/rollout_pause.go b/pkg/kubectl/cmd/rollout/rollout_pause.go index 10962de5727..fddf3c8cf47 100644 --- a/pkg/kubectl/cmd/rollout/rollout_pause.go +++ b/pkg/kubectl/cmd/rollout/rollout_pause.go @@ -21,7 +21,6 @@ import ( "github.com/spf13/cobra" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/kubernetes/pkg/api/legacyscheme" @@ -43,7 +42,6 @@ type PauseConfig struct { ToPrinter func(string) (printers.ResourcePrinterFunc, error) Pauser func(info *resource.Info) ([]byte, error) - Mapper meta.RESTMapper Infos []*resource.Info genericclioptions.IOStreams @@ -105,8 +103,6 @@ func (o *PauseConfig) CompletePause(f cmdutil.Factory, cmd *cobra.Command, args return cmdutil.UsageErrorf(cmd, "%s", cmd.Use) } - o.Mapper = f.RESTMapper() - o.Pauser = f.Pauser cmdNamespace, enforceNamespace, err := f.DefaultNamespace() @@ -160,7 +156,7 @@ func (o PauseConfig) RunPause() error { allErrs = append(allErrs, err) continue } - printer.PrintObj(info.AsVersioned(legacyscheme.Scheme), o.Out) + printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), o.Out) continue } @@ -176,7 +172,7 @@ func (o PauseConfig) RunPause() error { allErrs = append(allErrs, err) continue } - printer.PrintObj(info.AsVersioned(legacyscheme.Scheme), o.Out) + printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), o.Out) } return utilerrors.NewAggregate(allErrs) diff --git a/pkg/kubectl/cmd/rollout/rollout_resume.go b/pkg/kubectl/cmd/rollout/rollout_resume.go index a25ed405ba3..ac0c19caead 100644 --- a/pkg/kubectl/cmd/rollout/rollout_resume.go +++ b/pkg/kubectl/cmd/rollout/rollout_resume.go @@ -21,7 +21,6 @@ import ( "github.com/spf13/cobra" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/kubernetes/pkg/api/legacyscheme" @@ -43,7 +42,6 @@ type ResumeConfig struct { ToPrinter func(string) (printers.ResourcePrinterFunc, error) Resumer func(object *resource.Info) ([]byte, error) - Mapper meta.RESTMapper Infos []*resource.Info genericclioptions.IOStreams @@ -103,8 +101,6 @@ func (o *ResumeConfig) CompleteResume(f cmdutil.Factory, cmd *cobra.Command, arg return cmdutil.UsageErrorf(cmd, "%s", cmd.Use) } - o.Mapper = f.RESTMapper() - o.Resumer = f.Resumer cmdNamespace, enforceNamespace, err := f.DefaultNamespace() @@ -165,7 +161,7 @@ func (o ResumeConfig) RunResume() error { allErrs = append(allErrs, err) 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) @@ -180,7 +176,7 @@ func (o ResumeConfig) RunResume() error { allErrs = append(allErrs, err) continue } - printer.PrintObj(info.AsVersioned(legacyscheme.Scheme), o.Out) + printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), o.Out) } return utilerrors.NewAggregate(allErrs) diff --git a/pkg/kubectl/cmd/rollout/rollout_undo.go b/pkg/kubectl/cmd/rollout/rollout_undo.go index aef52b80540..45aaf170384 100644 --- a/pkg/kubectl/cmd/rollout/rollout_undo.go +++ b/pkg/kubectl/cmd/rollout/rollout_undo.go @@ -19,7 +19,6 @@ package rollout import ( "io" - "k8s.io/apimachinery/pkg/api/meta" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/kubectl" @@ -41,7 +40,6 @@ type UndoOptions struct { ToPrinter func(string) (printers.ResourcePrinterFunc, error) Rollbackers []kubectl.Rollbacker - Mapper meta.RESTMapper Infos []*resource.Info ToRevision int64 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.Mapper = f.RESTMapper() o.Out = out o.DryRun = cmdutil.GetDryRunFlag(cmd) @@ -171,7 +168,7 @@ func (o *UndoOptions) RunUndo() error { allErrs = append(allErrs, err) continue } - printer.PrintObj(info.AsVersioned(legacyscheme.Scheme), o.Out) + printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), o.Out) } return utilerrors.NewAggregate(allErrs) } diff --git a/pkg/kubectl/cmd/run.go b/pkg/kubectl/cmd/run.go index a544b4290f4..a56674dd0ce 100644 --- a/pkg/kubectl/cmd/run.go +++ b/pkg/kubectl/cmd/run.go @@ -643,7 +643,10 @@ func (o *RunOptions) createGeneratedObject(f cmdutil.Factory, cmd *cobra.Command 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 groupVersionKinds, _, err := legacyscheme.Scheme.ObjectKinds(obj) if err != nil { @@ -693,7 +696,7 @@ func (o *RunOptions) createGeneratedObject(f cmdutil.Factory, cmd *cobra.Command return nil, err } - versioned = info.AsVersioned(legacyscheme.Scheme) + versioned = cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping) } return &RunObject{ Versioned: versioned, diff --git a/pkg/kubectl/cmd/set/set_env.go b/pkg/kubectl/cmd/set/set_env.go index 6ae37a48bc8..ef2a5c61123 100644 --- a/pkg/kubectl/cmd/set/set_env.go +++ b/pkg/kubectl/cmd/set/set_env.go @@ -327,7 +327,7 @@ func (o *EnvOptions) RunEnv() error { return err } 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 { resolutionErrorsEncountered := false containers, _ := selectContainers(spec.Containers, o.ContainerSelector) @@ -418,7 +418,7 @@ func (o *EnvOptions) RunEnv() error { } 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 } continue @@ -437,7 +437,7 @@ func (o *EnvOptions) RunEnv() error { 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 } } diff --git a/pkg/kubectl/cmd/set/set_image.go b/pkg/kubectl/cmd/set/set_image.go index 1b271d762b2..e3096aa7537 100644 --- a/pkg/kubectl/cmd/set/set_image.go +++ b/pkg/kubectl/cmd/set/set_image.go @@ -211,7 +211,7 @@ func (o *SetImageOptions) Run() error { patches := CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), func(info *resource.Info) ([]byte, error) { 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 { for name, image := range o.ContainerImages { var ( @@ -275,7 +275,7 @@ func (o *SetImageOptions) Run() error { } 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 } continue @@ -289,7 +289,7 @@ func (o *SetImageOptions) Run() error { } 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 } } diff --git a/pkg/kubectl/cmd/set/set_resources.go b/pkg/kubectl/cmd/set/set_resources.go index 1624d5fa531..ceb57798d66 100644 --- a/pkg/kubectl/cmd/set/set_resources.go +++ b/pkg/kubectl/cmd/set/set_resources.go @@ -224,7 +224,7 @@ func (o *SetResourcesOptions) Run() error { allErrs := []error{} patches := CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), func(info *resource.Info) ([]byte, error) { 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 { containers, _ := selectContainers(spec.Containers, o.ContainerSelector) if len(containers) != 0 { @@ -277,7 +277,7 @@ func (o *SetResourcesOptions) Run() error { } 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 } continue @@ -290,7 +290,7 @@ func (o *SetResourcesOptions) Run() error { } 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 } } diff --git a/pkg/kubectl/cmd/set/set_selector.go b/pkg/kubectl/cmd/set/set_selector.go index ad181a452af..6c21fb58bb9 100644 --- a/pkg/kubectl/cmd/set/set_selector.go +++ b/pkg/kubectl/cmd/set/set_selector.go @@ -59,7 +59,6 @@ type SetSelectorOptions struct { Recorder genericclioptions.Recorder builder *resource.Builder - mapper meta.RESTMapper genericclioptions.IOStreams } @@ -140,9 +139,6 @@ func (o *SetSelectorOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, arg return err } - mapper := f.RESTMapper() - o.mapper = mapper - o.resources, o.selector, err = getResourcesAndSelector(args) if err != nil { return err @@ -208,7 +204,7 @@ func (o *SetSelectorOptions) RunSelector() error { return r.Visit(func(info *resource.Info, err error) error { patch := &Patch{Info: info} 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 selectErr := updateSelectorForObject(info.Object, *o.selector) if selectErr != nil { @@ -236,7 +232,7 @@ func (o *SetSelectorOptions) RunSelector() error { } 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) }) } diff --git a/pkg/kubectl/cmd/set/set_serviceaccount.go b/pkg/kubectl/cmd/set/set_serviceaccount.go index 414c8758c8d..217bfff776e 100644 --- a/pkg/kubectl/cmd/set/set_serviceaccount.go +++ b/pkg/kubectl/cmd/set/set_serviceaccount.go @@ -174,7 +174,7 @@ func (o *SetServiceAccountOptions) Complete(f cmdutil.Factory, cmd *cobra.Comman func (o *SetServiceAccountOptions) Run() error { patchErrs := []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 { podSpec.ServiceAccountName = o.serviceAccountName return nil @@ -198,7 +198,7 @@ func (o *SetServiceAccountOptions) Run() error { continue } 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 } continue @@ -210,7 +210,7 @@ func (o *SetServiceAccountOptions) Run() error { } 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 } } diff --git a/pkg/kubectl/cmd/set/set_subject.go b/pkg/kubectl/cmd/set/set_subject.go index 885b237a0f5..fa6a49bf840 100644 --- a/pkg/kubectl/cmd/set/set_subject.go +++ b/pkg/kubectl/cmd/set/set_subject.go @@ -230,7 +230,7 @@ func (o *SubjectOptions) Run(fn updateSubjects) error { transformed, err := updateSubjectForObject(info.Object, subjects, fn) if transformed && err == nil { // 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 }) @@ -263,7 +263,7 @@ func (o *SubjectOptions) Run(fn updateSubjects) error { } 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) } diff --git a/pkg/kubectl/cmd/testing/BUILD b/pkg/kubectl/cmd/testing/BUILD index 5e93aba0f6a..f1348755b0a 100644 --- a/pkg/kubectl/cmd/testing/BUILD +++ b/pkg/kubectl/cmd/testing/BUILD @@ -22,6 +22,7 @@ go_library( "//pkg/printers: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/testrestmapper: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/runtime:go_default_library", diff --git a/pkg/kubectl/cmd/testing/fake.go b/pkg/kubectl/cmd/testing/fake.go index e09bffc7357..aacb908762f 100644 --- a/pkg/kubectl/cmd/testing/fake.go +++ b/pkg/kubectl/cmd/testing/fake.go @@ -28,6 +28,7 @@ import ( "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/api/meta/testrestmapper" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" @@ -337,7 +338,7 @@ func (f *TestFactory) Command(*cobra.Command, bool) string { } func (f *TestFactory) NewBuilder() *resource.Builder { - mapper := f.RESTMapper() + mapper, err := f.RESTMapper() return resource.NewBuilder( &resource.Mapper{ @@ -351,7 +352,7 @@ func (f *TestFactory) NewBuilder() *resource.Builder { Decoder: unstructured.UnstructuredJSONScheme, }, f.CategoryExpander(), - ) + ).AddError(err) } func (f *TestFactory) KubernetesClientSet() (*kubernetes.Clientset, error) { @@ -425,7 +426,7 @@ func (f *TestFactory) ClientSetForVersion(requiredVersion *schema.GroupVersion) return f.ClientSet() } -func (f *TestFactory) RESTMapper() meta.RESTMapper { +func (f *TestFactory) RESTMapper() (meta.RESTMapper, error) { groupResources := testDynamicResources() mapper := discovery.NewRESTMapper(groupResources) // 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{ MultiRESTMapper: meta.MultiRESTMapper{ mapper, - legacyscheme.Registry.RESTMapper(), + testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme), }, } // TODO: should probably be the external scheme fakeDs := &fakeCachedDiscoveryClient{} expander := cmdutil.NewShortcutExpander(mapper, fakeDs) - return expander + return expander, nil } func (f *TestFactory) LogsForObject(object, options runtime.Object, timeout time.Duration) (*restclient.Request, error) { diff --git a/pkg/kubectl/cmd/util/BUILD b/pkg/kubectl/cmd/util/BUILD index e39d587f1f5..c3ce48d37c9 100644 --- a/pkg/kubectl/cmd/util/BUILD +++ b/pkg/kubectl/cmd/util/BUILD @@ -4,6 +4,7 @@ go_library( name = "go_default_library", srcs = [ "cached_discovery.go", + "conversion.go", "factory.go", "factory_builder.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/errors: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/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", diff --git a/pkg/kubectl/cmd/util/conversion.go b/pkg/kubectl/cmd/util/conversion.go new file mode 100644 index 00000000000..960b3e08958 --- /dev/null +++ b/pkg/kubectl/cmd/util/conversion.go @@ -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 +} diff --git a/pkg/kubectl/cmd/util/factory.go b/pkg/kubectl/cmd/util/factory.go index 87da23dba8d..38ee9742cc3 100644 --- a/pkg/kubectl/cmd/util/factory.go +++ b/pkg/kubectl/cmd/util/factory.go @@ -164,7 +164,7 @@ type ClientAccessFactory interface { // Generally they provide object typing and functions that build requests based on the negotiated clients. type ObjectMappingFactory interface { // Returns interfaces for dealing with arbitrary runtime.Objects. - RESTMapper() meta.RESTMapper + RESTMapper() (meta.RESTMapper, error) // Returns interface for expanding categories like `all`. CategoryExpander() categories.CategoryExpander // Returns a RESTClient for working with the specified RESTMapping or an error. This is intended diff --git a/pkg/kubectl/cmd/util/factory_builder.go b/pkg/kubectl/cmd/util/factory_builder.go index c5363e25515..472f89b5ef9 100644 --- a/pkg/kubectl/cmd/util/factory_builder.go +++ b/pkg/kubectl/cmd/util/factory_builder.go @@ -47,7 +47,7 @@ func NewBuilderFactory(clientAccessFactory ClientAccessFactory, objectMappingFac // NewBuilder returns a new resource builder for structured api objects. func (f *ring2Factory) NewBuilder() *resource.Builder { clientMapperFunc := resource.ClientMapperFunc(f.objectMappingFactory.ClientForMapping) - mapper := f.objectMappingFactory.RESTMapper() + mapper, mapperErr := f.objectMappingFactory.RESTMapper() unstructuredClientMapperFunc := resource.ClientMapperFunc(f.objectMappingFactory.UnstructuredClientForMapping) @@ -65,7 +65,7 @@ func (f *ring2Factory) NewBuilder() *resource.Builder { Decoder: unstructured.UnstructuredJSONScheme, }, categoryExpander, - ) + ).AddError(mapperErr) } // 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 } 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 } diff --git a/pkg/kubectl/cmd/util/factory_object_mapping.go b/pkg/kubectl/cmd/util/factory_object_mapping.go index 898478cd71b..ffbee1f2fee 100644 --- a/pkg/kubectl/cmd/util/factory_object_mapping.go +++ b/pkg/kubectl/cmd/util/factory_object_mapping.go @@ -27,8 +27,6 @@ import ( "sync" "time" - "github.com/golang/glog" - "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -37,7 +35,6 @@ import ( "k8s.io/client-go/discovery" "k8s.io/client-go/dynamic" restclient "k8s.io/client-go/rest" - "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/apps" "k8s.io/kubernetes/pkg/apis/batch" api "k8s.io/kubernetes/pkg/apis/core" @@ -72,26 +69,18 @@ func NewObjectMappingFactory(clientAccessFactory ClientAccessFactory) ObjectMapp return f } -// objectLoader attempts to perform discovery against the server, and will fall back to -// the built in mapper if necessary. It supports unstructured objects either way, since -// 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) { +// RESTMapper returns a mapper. +func (f *ring1Factory) RESTMapper() (meta.RESTMapper, error) { discoveryClient, err := f.clientAccessFactory.DiscoveryClient() 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 legacyscheme.Registry.RESTMapper(), nil + return nil, err } // allow conversion between typed and unstructured objects mapper := discovery.NewDeferredDiscoveryRESTMapper(discoveryClient) // TODO: should this also indicate it recognizes typed objects? expander := NewShortcutExpander(mapper, discoveryClient) - return expander, err -} - -func (f *ring1Factory) RESTMapper() meta.RESTMapper { - return meta.NewLazyRESTMapperLoader(f.restMapper) + return expander, nil } func (f *ring1Factory) CategoryExpander() categories.CategoryExpander { diff --git a/pkg/kubectl/cmd/util/factory_test.go b/pkg/kubectl/cmd/util/factory_test.go index 409a834dbcc..6f0154926b2 100644 --- a/pkg/kubectl/cmd/util/factory_test.go +++ b/pkg/kubectl/cmd/util/factory_test.go @@ -26,6 +26,7 @@ import ( "k8s.io/api/core/v1" apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/api/meta/testrestmapper" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" @@ -34,6 +35,7 @@ import ( "k8s.io/apimachinery/pkg/watch" manualfake "k8s.io/client-go/rest/fake" testcore "k8s.io/client-go/testing" + "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/testapi" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" @@ -470,7 +472,7 @@ func TestDiscoveryReplaceAliases(t *testing.T) { } ds := &fakeDiscoveryClient{} - mapper := NewShortcutExpander(testapi.Default.RESTMapper(), ds) + mapper := NewShortcutExpander(testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme), ds) b := resource.NewBuilder( &resource.Mapper{ RESTMapper: mapper, diff --git a/pkg/kubectl/cmd/util/shortcut_restmapper_test.go b/pkg/kubectl/cmd/util/shortcut_restmapper_test.go index 941ac63d93a..34353020ff1 100644 --- a/pkg/kubectl/cmd/util/shortcut_restmapper_test.go +++ b/pkg/kubectl/cmd/util/shortcut_restmapper_test.go @@ -19,9 +19,10 @@ package util import ( "testing" + "k8s.io/apimachinery/pkg/api/meta/testrestmapper" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/kubernetes/pkg/api/testapi" + "k8s.io/kubernetes/pkg/api/legacyscheme" ) func TestReplaceAliases(t *testing.T) { @@ -126,7 +127,7 @@ func TestReplaceAliases(t *testing.T) { } ds := &fakeDiscoveryClient{} - mapper := NewShortcutExpander(testapi.Default.RESTMapper(), ds) + mapper := NewShortcutExpander(testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme), ds) for _, test := range tests { ds.serverResourcesHandler = func() ([]*metav1.APIResourceList, error) { @@ -178,7 +179,7 @@ func TestKindFor(t *testing.T) { } ds := &fakeDiscoveryClient{} - mapper := NewShortcutExpander(testapi.Default.RESTMapper(), ds) + mapper := NewShortcutExpander(testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme), ds) for i, test := range tests { ds.serverResourcesHandler = func() ([]*metav1.APIResourceList, error) { diff --git a/pkg/kubectl/explain/BUILD b/pkg/kubectl/explain/BUILD index fa8aed92451..5cbccb40b13 100644 --- a/pkg/kubectl/explain/BUILD +++ b/pkg/kubectl/explain/BUILD @@ -51,6 +51,7 @@ go_test( deps = [ "//pkg/kubectl/cmd/util/openapi/testing: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", ], ) diff --git a/pkg/kubectl/explain/explain_test.go b/pkg/kubectl/explain/explain_test.go index 46317bfd3f7..04ec14621ad 100644 --- a/pkg/kubectl/explain/explain_test.go +++ b/pkg/kubectl/explain/explain_test.go @@ -20,6 +20,7 @@ import ( "reflect" "testing" + "k8s.io/apimachinery/pkg/api/meta/testrestmapper" "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 { gotInResource, gotFieldsPath, err := SplitAndParseResourceRequest(test.inresource, mapper) if err != nil { diff --git a/pkg/kubectl/resource/BUILD b/pkg/kubectl/resource/BUILD index cf644789313..c227a2edeac 100644 --- a/pkg/kubectl/resource/BUILD +++ b/pkg/kubectl/resource/BUILD @@ -65,6 +65,7 @@ go_test( "//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/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/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", diff --git a/pkg/kubectl/resource/builder.go b/pkg/kubectl/resource/builder.go index a2de3ca6868..299d9eb199b 100644 --- a/pkg/kubectl/resource/builder.go +++ b/pkg/kubectl/resource/builder.go @@ -56,6 +56,9 @@ type Builder struct { // it does not ever need to rely upon discovery. objectTyper runtime.ObjectTyper + // local indicates that we cannot make server calls + local bool + errs []error paths []Visitor @@ -142,6 +145,14 @@ func (b *Builder) Schema(schema validation.Schema) *Builder { 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) // 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 @@ -192,6 +203,7 @@ func (b *Builder) Unstructured() *Builder { return b } b.mapper = b.unstructured + b.mapper.localFn = b.isLocal b.objectTyper = unstructuredscheme.NewUnstructuredObjectTyper() return b @@ -212,6 +224,7 @@ func (b *Builder) Internal(typer runtime.ObjectTyper) *Builder { return b } b.mapper = b.internal + b.mapper.localFn = b.isLocal b.objectTyper = typer return b @@ -227,12 +240,17 @@ func (b *Builder) LocalParam(local bool) *Builder { // Local will avoid asking the server for results. func (b *Builder) Local() *Builder { + b.local = true mapper := *b.mapper mapper.ClientMapper = DisabledClientForMapping{ClientMapper: mapper.ClientMapper} b.mapper = &mapper return b } +func (b *Builder) isLocal() bool { + return b.local +} + // Mapper returns a copy of the current mapper. func (b *Builder) Mapper() *Mapper { mapper := *b.mapper diff --git a/pkg/kubectl/resource/builder_test.go b/pkg/kubectl/resource/builder_test.go index aa6aab61e20..c40ae4eebba 100644 --- a/pkg/kubectl/resource/builder_test.go +++ b/pkg/kubectl/resource/builder_test.go @@ -34,6 +34,7 @@ import ( "k8s.io/api/core/v1" apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/api/meta/testrestmapper" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -58,7 +59,7 @@ var ( corev1GV = schema.GroupVersion{Version: "v1"} corev1Codec = scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(corev1GV), scheme.Codecs.UniversalDecoder(corev1GV), corev1GV, corev1GV) metaAccessor = meta.NewAccessor() - restmapper = scheme.Registry.RESTMapper() + restmapper = testrestmapper.TestOnlyStaticRESTMapper(scheme.Registry, scheme.Scheme) ) 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 { t.Errorf("unexpected info: %#v", info) } - obj := info.AsVersioned(legacyscheme.Scheme) + + obj := info.Object version, ok := obj.(*v1.ReplicationController) // versioned object does not have defaulting applied if obj == nil || !ok || version.Spec.Replicas != nil { diff --git a/pkg/kubectl/resource/interfaces.go b/pkg/kubectl/resource/interfaces.go index 8b75d41dbf9..383649e5773 100644 --- a/pkg/kubectl/resource/interfaces.go +++ b/pkg/kubectl/resource/interfaces.go @@ -22,6 +22,8 @@ import ( client "k8s.io/client-go/rest" ) +type RESTMapperFunc func() (meta.RESTMapper, error) + // RESTClient is a client helper for dealing with RESTful resources // in a generic way. type RESTClient interface { diff --git a/pkg/kubectl/resource/mapper.go b/pkg/kubectl/resource/mapper.go index 61f1ee1c56c..c188a19f8d9 100644 --- a/pkg/kubectl/resource/mapper.go +++ b/pkg/kubectl/resource/mapper.go @@ -28,6 +28,9 @@ import ( // Mapper is a convenience struct for holding references to the interfaces // needed to create Info for arbitrary objects. type Mapper struct { + // localFn indicates the call can't make server requests + localFn func() bool + RESTMapper meta.RESTMapper ClientMapper ClientMapper 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) } - 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) namespace, _ := metadataAccessor.Namespace(obj) resourceVersion, _ := metadataAccessor.ResourceVersion(obj) - return &Info{ - Client: client, - Mapping: mapping, - + ret := &Info{ Source: source, Namespace: namespace, Name: name, ResourceVersion: resourceVersion, 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 @@ -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) } - groupVersionKind := groupVersionKinds[0] + gvk := groupVersionKinds[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) namespace, _ := metadataAccessor.Namespace(obj) resourceVersion, _ := metadataAccessor.ResourceVersion(obj) - return &Info{ - Client: client, - Mapping: mapping, - + ret := &Info{ Namespace: namespace, Name: name, ResourceVersion: resourceVersion, 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: diff --git a/pkg/kubectl/resource/visitor.go b/pkg/kubectl/resource/visitor.go index 88241712994..95b6bbbe0a6 100644 --- a/pkg/kubectl/resource/visitor.go +++ b/pkg/kubectl/resource/visitor.go @@ -180,22 +180,6 @@ func (i *Info) ResourceMapping() *meta.RESTMapping { 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 // returned from a child Visitor will terminate iteration. type VisitorList []Visitor diff --git a/pkg/kubectl/scheme/install.go b/pkg/kubectl/scheme/install.go index 87caea0645f..971da706fe0 100644 --- a/pkg/kubectl/scheme/install.go +++ b/pkg/kubectl/scheme/install.go @@ -71,18 +71,6 @@ func init() { "PersistentVolume", "ComponentStatus", ), - IgnoredKinds: sets.NewString( - "ListOptions", - "DeleteOptions", - "Status", - "PodLogOptions", - "PodExecOptions", - "PodAttachOptions", - "PodPortForwardOptions", - "PodProxyOptions", - "NodeProxyOptions", - "ServiceProxyOptions", - ), }, announced.VersionToSchemeFunc{ corev1.SchemeGroupVersion.Version: corev1.AddToScheme, diff --git a/plugin/pkg/admission/gc/BUILD b/plugin/pkg/admission/gc/BUILD index 2573403a464..60b310a67fd 100644 --- a/plugin/pkg/admission/gc/BUILD +++ b/plugin/pkg/admission/gc/BUILD @@ -30,6 +30,7 @@ go_test( "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/core: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/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", diff --git a/plugin/pkg/admission/gc/gc_admission_test.go b/plugin/pkg/admission/gc/gc_admission_test.go index fb1e0478650..9810fa7ce5d 100644 --- a/plugin/pkg/admission/gc/gc_admission_test.go +++ b/plugin/pkg/admission/gc/gc_admission_test.go @@ -20,6 +20,7 @@ import ( "strings" "testing" + "k8s.io/apimachinery/pkg/api/meta/testrestmapper" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -87,7 +88,7 @@ func newGCPermissionsEnforcement() (*gcPermissionsEnforcement, error) { } 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 = append(initializersChain, genericPluginInitializer) initializersChain = append(initializersChain, pluginInitializer) diff --git a/staging/src/k8s.io/apimachinery/pkg/api/meta/BUILD b/staging/src/k8s.io/apimachinery/pkg/api/meta/BUILD index c198b980e46..8505376e0f8 100644 --- a/staging/src/k8s.io/apimachinery/pkg/api/meta/BUILD +++ b/staging/src/k8s.io/apimachinery/pkg/api/meta/BUILD @@ -65,6 +65,7 @@ filegroup( srcs = [ ":package-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"], ) diff --git a/staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper/BUILD b/staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper/BUILD new file mode 100644 index 00000000000..094b209b68e --- /dev/null +++ b/staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper/BUILD @@ -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"], +) diff --git a/staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper/test_restmapper.go b/staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper/test_restmapper.go new file mode 100644 index 00000000000..fa0506b7826 --- /dev/null +++ b/staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper/test_restmapper.go @@ -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", +) diff --git a/staging/src/k8s.io/apimachinery/pkg/apimachinery/BUILD b/staging/src/k8s.io/apimachinery/pkg/apimachinery/BUILD index ece7c827060..885d7d5f87b 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apimachinery/BUILD +++ b/staging/src/k8s.io/apimachinery/pkg/apimachinery/BUILD @@ -13,7 +13,6 @@ go_library( ], importpath = "k8s.io/apimachinery/pkg/apimachinery", 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/util/sets:go_default_library", ], diff --git a/staging/src/k8s.io/apimachinery/pkg/apimachinery/announced/BUILD b/staging/src/k8s.io/apimachinery/pkg/apimachinery/announced/BUILD index a8c6e1ce2ca..3c82717283a 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apimachinery/announced/BUILD +++ b/staging/src/k8s.io/apimachinery/pkg/apimachinery/announced/BUILD @@ -11,7 +11,6 @@ go_library( importpath = "k8s.io/apimachinery/pkg/apimachinery/announced", deps = [ "//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/registered:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", diff --git a/staging/src/k8s.io/apimachinery/pkg/apimachinery/announced/group_factory.go b/staging/src/k8s.io/apimachinery/pkg/apimachinery/announced/group_factory.go index 6e244a85718..c370d03ff13 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apimachinery/announced/group_factory.go +++ b/staging/src/k8s.io/apimachinery/pkg/apimachinery/announced/group_factory.go @@ -21,7 +21,6 @@ import ( "github.com/golang/glog" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/apimachinery" "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" @@ -49,7 +48,6 @@ type GroupMetaFactoryArgs struct { VersionPreferenceOrder []string // RootScopedKinds are resources that are not namespaced. RootScopedKinds sets.String // nil is allowed - IgnoredKinds sets.String // nil is allowed // May be nil if there are no internal objects. AddInternalObjectsToScheme SchemeFunc @@ -154,40 +152,9 @@ func (gmf *GroupMetaFactory) Register(m *registered.APIRegistrationManager, sche GroupVersions: externalVersions, RootScopedKinds: gmf.GroupArgs.RootScopedKinds, } - groupMeta.RESTMapper = gmf.newRESTMapper(scheme, externalVersions, groupMeta) if err := m.RegisterGroup(*groupMeta); err != nil { return err } 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 } diff --git a/staging/src/k8s.io/apimachinery/pkg/apimachinery/registered/BUILD b/staging/src/k8s.io/apimachinery/pkg/apimachinery/registered/BUILD index 6495093fd57..93cd587da8e 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apimachinery/registered/BUILD +++ b/staging/src/k8s.io/apimachinery/pkg/apimachinery/registered/BUILD @@ -21,10 +21,8 @@ go_library( srcs = ["registered.go"], importpath = "k8s.io/apimachinery/pkg/apimachinery/registered", 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/runtime/schema:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", ], ) diff --git a/staging/src/k8s.io/apimachinery/pkg/apimachinery/registered/registered.go b/staging/src/k8s.io/apimachinery/pkg/apimachinery/registered/registered.go index e6831c15b90..dd6574acd48 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apimachinery/registered/registered.go +++ b/staging/src/k8s.io/apimachinery/pkg/apimachinery/registered/registered.go @@ -22,10 +22,8 @@ import ( "sort" "strings" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/apimachinery" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/util/sets" ) // APIRegistrationManager provides the concept of what API groups are enabled. @@ -140,73 +138,6 @@ func (m *APIRegistrationManager) GroupOrDie(group string) *apimachinery.GroupMet 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 // groups in the form of "group1/version1,group2/version2,..." func (m *APIRegistrationManager) AllPreferredGroupVersions() string { diff --git a/staging/src/k8s.io/apimachinery/pkg/apimachinery/types.go b/staging/src/k8s.io/apimachinery/pkg/apimachinery/types.go index 5c45ec891b7..4b2d113d248 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apimachinery/types.go +++ b/staging/src/k8s.io/apimachinery/pkg/apimachinery/types.go @@ -17,7 +17,6 @@ limitations under the License. package apimachinery import ( - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/sets" ) @@ -28,8 +27,4 @@ type GroupMeta struct { GroupVersions []schema.GroupVersion 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 } diff --git a/staging/src/k8s.io/apiserver/pkg/server/BUILD b/staging/src/k8s.io/apiserver/pkg/server/BUILD index 07bdd7f0a08..afb29af4ba0 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/server/BUILD @@ -16,7 +16,6 @@ go_test( embed = [":go_default_library"], deps = [ "//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/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", diff --git a/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go b/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go index a20d326609e..2e04d848f30 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go +++ b/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go @@ -34,7 +34,6 @@ import ( // "github.com/go-openapi/spec" "github.com/stretchr/testify/assert" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/apimachinery" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -153,13 +152,8 @@ func TestInstallAPIGroups(t *testing.T) { scheme.AddKnownTypes(v1GroupVersion, &metav1.Status{}) 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{ GroupVersions: []schema.GroupVersion{gv}, - RESTMapper: mapper, } return APIGroupInfo{ diff --git a/test/integration/apiserver/print_test.go b/test/integration/apiserver/print_test.go index e6e19fdcfd2..85bfa4c3f4e 100644 --- a/test/integration/apiserver/print_test.go +++ b/test/integration/apiserver/print_test.go @@ -147,8 +147,11 @@ func TestServerSidePrint(t *testing.T) { printer := newFakePrinter(printersinternal.AddHandlers) 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() { // 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") { diff --git a/test/integration/etcd/BUILD b/test/integration/etcd/BUILD index bb8b85daf02..7bdff725faf 100644 --- a/test/integration/etcd/BUILD +++ b/test/integration/etcd/BUILD @@ -21,7 +21,6 @@ go_test( "//cmd/kube-apiserver/app/options:go_default_library", "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/core:go_default_library", - "//pkg/kubectl/cmd/util:go_default_library", "//pkg/master:go_default_library", "//test/integration: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/options: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/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", ], ) diff --git a/test/integration/etcd/etcd_storage_path_test.go b/test/integration/etcd/etcd_storage_path_test.go index 0756210ea46..6c8d212aca0 100644 --- a/test/integration/etcd/etcd_storage_path_test.go +++ b/test/integration/etcd/etcd_storage_path_test.go @@ -43,16 +43,15 @@ import ( genericapiserver "k8s.io/apiserver/pkg/server" genericapiserveroptions "k8s.io/apiserver/pkg/server/options" "k8s.io/apiserver/pkg/storage/storagebackend" + "k8s.io/client-go/discovery" + cacheddiscovery "k8s.io/client-go/discovery/cached" clientset "k8s.io/client-go/kubernetes" 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/kubernetes/cmd/kube-apiserver/app" "k8s.io/kubernetes/cmd/kube-apiserver/app/options" "k8s.io/kubernetes/pkg/api/legacyscheme" kapi "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/test/integration" "k8s.io/kubernetes/test/integration/framework" @@ -434,84 +433,84 @@ var etcdStorageData = map[schema.GroupVersionResource]struct { var ephemeralWhiteList = createEphemeralWhiteList( // k8s.io/kubernetes/pkg/api/v1 - gvr("", "v1", "bindings"), // annotation on pod, not stored in etcd - gvr("", "v1", "rangeallocations"), // stored in various places in etcd but cannot be directly created - gvr("", "v1", "componentstatuses"), // status info not stored in etcd - gvr("", "v1", "serializedreferences"), // used for serilization, not stored in etcd - gvr("", "v1", "nodeconfigsources"), // subfield of node.spec, but shouldn't be directly created - gvr("", "v1", "podstatusresults"), // wrapper object not stored in etcd + gvk("", "v1", "Binding"), // annotation on pod, not stored in etcd + gvk("", "v1", "RangeAllocation"), // stored in various places in etcd but cannot be directly created + gvk("", "v1", "ComponentStatus"), // status info not stored in etcd + gvk("", "v1", "SerializedReference"), // used for serilization, not stored in etcd + gvk("", "v1", "NodeConfigSource"), // subfield of node.spec, but shouldn't be directly created + gvk("", "v1", "PodStatusResult"), // wrapper object not stored in etcd // -- // 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 - gvr("authentication.k8s.io", "v1", "tokenreviews"), // not stored in etcd - gvr("authentication.k8s.io", "v1", "tokenrequests"), // not stored in etcd + gvk("authentication.k8s.io", "v1", "TokenReview"), // not stored in etcd + gvk("authentication.k8s.io", "v1", "TokenRequest"), // not stored in etcd // -- // k8s.io/kubernetes/pkg/apis/authorization/v1beta1 // 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 - gvr("authorization.k8s.io", "v1beta1", "selfsubjectaccessreviews"), - gvr("authorization.k8s.io", "v1beta1", "localsubjectaccessreviews"), - gvr("authorization.k8s.io", "v1beta1", "subjectaccessreviews"), + gvk("authorization.k8s.io", "v1beta1", "SelfSubjectAccessReview"), + gvk("authorization.k8s.io", "v1beta1", "LocalSubjectAccessReview"), + gvk("authorization.k8s.io", "v1beta1", "SubjectAccessReview"), // -- // k8s.io/kubernetes/pkg/apis/authorization/v1 // 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 - gvr("authorization.k8s.io", "v1", "selfsubjectaccessreviews"), - gvr("authorization.k8s.io", "v1", "localsubjectaccessreviews"), - gvr("authorization.k8s.io", "v1", "subjectaccessreviews"), + gvk("authorization.k8s.io", "v1", "SelfSubjectAccessReview"), + gvk("authorization.k8s.io", "v1", "LocalSubjectAccessReview"), + gvk("authorization.k8s.io", "v1", "SubjectAccessReview"), // -- // 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 - gvr("apps", "v1beta1", "scales"), // not stored in etcd, part of kapiv1.ReplicationController - gvr("apps", "v1beta1", "deploymentrollbacks"), // used to rollback deployment, not stored in etcd + gvk("apps", "v1beta1", "Scale"), // not stored in etcd, part of kapiv1.ReplicationController + gvk("apps", "v1beta1", "DeploymentRollback"), // used to rollback deployment, not stored in etcd // -- // 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 - gvr("batch", "v1beta1", "jobtemplates"), // not stored in etcd + gvk("batch", "v1beta1", "JobTemplate"), // not stored in etcd // -- // 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 - gvr("componentconfig", "v1alpha1", "kubeschedulerconfigurations"), // not stored in etcd + gvk("componentconfig", "v1alpha1", "KubeSchedulerConfiguration"), // not stored in etcd // -- // k8s.io/kubernetes/pkg/apis/extensions/v1beta1 - gvr("extensions", "v1beta1", "deploymentrollbacks"), // used to rollback deployment, not stored in etcd - gvr("extensions", "v1beta1", "replicationcontrollerdummies"), // not stored in etcd - gvr("extensions", "v1beta1", "scales"), // not stored in etcd, part of kapiv1.ReplicationController + gvk("extensions", "v1beta1", "DeploymentRollback"), // used to rollback deployment, not stored in etcd + gvk("extensions", "v1beta1", "ReplicationControllerDummy"), // not stored in etcd + gvk("extensions", "v1beta1", "Scale"), // not stored in etcd, part of kapiv1.ReplicationController // -- // 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 - 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 - 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() pathSeen := map[string][]schema.GroupVersionResource{} etcdSeen := map[schema.GroupVersionResource]empty{} - ephemeralSeen := map[schema.GroupVersionResource]empty{} + ephemeralSeen := map[schema.GroupVersionKind]empty{} cohabitatingResources := map[string]map[schema.GroupVersionKind]empty{} for gvk, apiType := range legacyscheme.Scheme.AllKnownTypes() { @@ -577,6 +576,11 @@ func TestEtcdStoragePath(t *testing.T) { kindSeen.Insert(kind) continue } + _, isEphemeral := ephemeralWhiteList[gvk] + if isEphemeral { + ephemeralSeen[gvk] = empty{} + continue + } mapping, err := mapper.RESTMapping(gvk.GroupKind(), gvk.Version) if err != nil { @@ -588,25 +592,12 @@ func TestEtcdStoragePath(t *testing.T) { etcdSeen[gvResource] = empty{} 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) 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 { t.Errorf("empty test data for %s from %s", kind, pkgPath) continue @@ -811,7 +802,11 @@ func startRealMasterOrDie(t *testing.T, certDir string) (*allClient, clientv3.KV 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 } @@ -888,17 +883,21 @@ func gvr(g, v, r string) schema.GroupVersionResource { 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 { return &schema.GroupVersionKind{Group: g, Version: v, Kind: k} } -func createEphemeralWhiteList(gvrs ...schema.GroupVersionResource) map[schema.GroupVersionResource]empty { - ephemeral := map[schema.GroupVersionResource]empty{} - for _, gvResource := range gvrs { - if _, ok := ephemeral[gvResource]; ok { +func createEphemeralWhiteList(gvks ...schema.GroupVersionKind) map[schema.GroupVersionKind]empty { + ephemeral := map[schema.GroupVersionKind]empty{} + for _, gvKind := range gvks { + if _, ok := ephemeral[gvKind]; ok { panic("invalid ephemeral whitelist contains duplicate keys") } - ephemeral[gvResource] = empty{} + ephemeral[gvKind] = empty{} } return ephemeral }