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

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

remove incorrect static restmapper from type registry

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

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

```release-note
NONE
```
This commit is contained in:
Kubernetes Submit Queue
2018-05-01 08:10:37 -07:00
committed by GitHub
71 changed files with 457 additions and 483 deletions

View File

@@ -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
}
}

View File

@@ -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]

View File

@@ -127,16 +127,20 @@ func NewCmdAutoscale(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *
}
func (o *AutoscaleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
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

View File

@@ -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")

View File

@@ -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)

View File

@@ -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)
}

View File

@@ -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")

View File

@@ -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)
}

View File

@@ -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)
}
}

View File

@@ -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) {

View File

@@ -91,12 +91,16 @@ func NewCmdExplain(parent string, f cmdutil.Factory, streams genericclioptions.I
}
func (o *ExplainOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
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

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)
}

View File

@@ -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,

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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)
})
}

View File

@@ -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
}
}

View File

@@ -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)
}

View File

@@ -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",

View File

@@ -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) {

View File

@@ -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",

View File

@@ -0,0 +1,40 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package util
import (
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kubernetes/pkg/api/legacyscheme"
)
// AsDefaultVersionedOrOriginal returns the object as a Go object in the external form if possible (matching the
// group version kind of the mapping if provided, a best guess based on serialization if not provided, or obj if it cannot be converted.
// TODO update call sites to specify the scheme they want on their builder.
func AsDefaultVersionedOrOriginal(obj runtime.Object, mapping *meta.RESTMapping) runtime.Object {
converter := runtime.ObjectConvertor(legacyscheme.Scheme)
groupVersioner := runtime.GroupVersioner(schema.GroupVersions(legacyscheme.Registry.RegisteredGroupVersions()))
if mapping != nil {
groupVersioner = mapping.GroupVersionKind.GroupVersion()
}
if obj, err := converter.ConvertToVersion(obj, groupVersioner); err == nil {
return obj
}
return obj
}

View File

@@ -164,7 +164,7 @@ type ClientAccessFactory interface {
// Generally they provide object typing and functions that build requests based on the negotiated clients.
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

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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) {

View File

@@ -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",
],
)

View File

@@ -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 {

View File

@@ -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",

View File

@@ -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

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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:

View File

@@ -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

View File

@@ -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,