mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 10:51:29 +00:00
Merge pull request #43622 from deads2k/cli-10-category
Automatic merge from submit-queue (batch tested with PRs 42087, 43383, 43622) move category expansion out of restmapper RESTMapping isn't related to CategoryExpansion (the bit that expands "all" into items to be RESTMapped). This provides that separation and simplifies the RESTMapper interface. @kubernetes/sig-cli-pr-reviews
This commit is contained in:
commit
f14618a56b
@ -83,9 +83,6 @@ func enableVersions(externalVersions []schema.GroupVersion) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// userResources is a group of resources mostly used by a kubectl user
|
||||
var userResources = []string{"svc"}
|
||||
|
||||
func newRESTMapper(externalVersions []schema.GroupVersion) 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
|
||||
@ -100,8 +97,6 @@ func newRESTMapper(externalVersions []schema.GroupVersion) meta.RESTMapper {
|
||||
"Status")
|
||||
|
||||
mapper := meta.NewDefaultRESTMapperFromScheme(externalVersions, interfacesFor, importPrefix, ignoredKinds, rootScoped, core.Scheme)
|
||||
// setup aliases for groups of resources
|
||||
mapper.AddResourceAlias("all", userResources...)
|
||||
|
||||
return mapper
|
||||
}
|
||||
|
@ -190,7 +190,7 @@ func (o AnnotateOptions) RunAnnotate(f cmdutil.Factory, cmd *cobra.Command) erro
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
b := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
ContinueOnError().
|
||||
NamespaceParam(namespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
|
@ -205,7 +205,7 @@ func RunApply(f cmdutil.Factory, cmd *cobra.Command, out, errOut io.Writer, opti
|
||||
}
|
||||
}
|
||||
|
||||
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
r := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
Schema(schema).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
|
@ -120,7 +120,7 @@ func (o *SetLastAppliedOptions) Complete(f cmdutil.Factory, cmd *cobra.Command)
|
||||
}
|
||||
|
||||
func (o *SetLastAppliedOptions) Validate(f cmdutil.Factory, cmd *cobra.Command) error {
|
||||
r := resource.NewBuilder(o.Mapper, o.Typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
r := resource.NewBuilder(o.Mapper, f.CategoryExpander(), o.Typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
NamespaceParam(o.Namespace).DefaultNamespace().
|
||||
FilenameParam(o.EnforceNamespace, &o.FilenameOptions).
|
||||
Latest().
|
||||
|
@ -90,7 +90,7 @@ func (o *ViewLastAppliedOptions) Complete(f cmdutil.Factory, args []string) erro
|
||||
return err
|
||||
}
|
||||
|
||||
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
r := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
ResourceTypeOrNameArgs(enforceNamespace, args...).
|
||||
|
@ -146,7 +146,7 @@ func (p *AttachOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn [
|
||||
}
|
||||
|
||||
mapper, typer := f.Object()
|
||||
builder := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
builder := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
NamespaceParam(namespace).DefaultNamespace()
|
||||
|
||||
switch len(argsIn) {
|
||||
|
@ -91,7 +91,7 @@ func RunAutoscale(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s
|
||||
}
|
||||
|
||||
mapper, typer := f.Object()
|
||||
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
r := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
ContinueOnError().
|
||||
NamespaceParam(namespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, options).
|
||||
|
@ -167,7 +167,7 @@ func (options *CertificateOptions) modifyCertificateCondition(f cmdutil.Factory,
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
r := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
ContinueOnError().
|
||||
FilenameParam(false, &options.FilenameOptions).
|
||||
ResourceNames("certificatesigningrequest", options.csrNames...).
|
||||
|
@ -79,7 +79,7 @@ func RunClusterInfo(f cmdutil.Factory, out io.Writer, cmd *cobra.Command) error
|
||||
}
|
||||
|
||||
// TODO use generalized labels once they are implemented (#341)
|
||||
b := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
b := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
SelectorParam("kubernetes.io/cluster-service=true").
|
||||
ResourceTypeOrNameArgs(false, []string{"services"}...).
|
||||
|
@ -132,9 +132,9 @@ func (o *ConvertOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.C
|
||||
|
||||
if o.local {
|
||||
fmt.Fprintln(os.Stderr, "running in local mode...")
|
||||
o.builder = resource.NewBuilder(mapper, typer, resource.DisabledClientForMapping{ClientMapper: clientMapper}, f.Decoder(true))
|
||||
o.builder = resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.DisabledClientForMapping{ClientMapper: clientMapper}, f.Decoder(true))
|
||||
} else {
|
||||
o.builder = resource.NewBuilder(mapper, typer, clientMapper, f.Decoder(true))
|
||||
o.builder = resource.NewBuilder(mapper, f.CategoryExpander(), typer, clientMapper, f.Decoder(true))
|
||||
schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"), cmdutil.GetFlagString(cmd, "schema-cache-dir"))
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -128,7 +128,7 @@ func RunCreate(f cmdutil.Factory, cmd *cobra.Command, out, errOut io.Writer, opt
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
r := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
Schema(schema).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
|
@ -175,7 +175,7 @@ func (o *DeleteOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args
|
||||
return err
|
||||
}
|
||||
o.Mapper = mapper
|
||||
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
r := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
|
@ -121,7 +121,7 @@ func RunDescribe(f cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, a
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
r := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces).
|
||||
FilenameParam(enforceNamespace, options).
|
||||
@ -181,7 +181,7 @@ func DescribeMatchingResources(mapper meta.RESTMapper, typer runtime.ObjectTyper
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
r := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
NamespaceParam(namespace).DefaultNamespace().
|
||||
ResourceTypeOrNameArgs(true, rsrc).
|
||||
SingleResourceType().
|
||||
|
@ -385,7 +385,7 @@ func getMapperAndResult(f cmdutil.Factory, args []string, options *resource.File
|
||||
return nil, nil, nil, "", err
|
||||
}
|
||||
|
||||
b := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme)
|
||||
b := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme)
|
||||
if editMode == NormalEditMode {
|
||||
// if in normal mode, also read from args, and fetch latest from the server
|
||||
b = b.ResourceTypeOrNameArgs(true, args...).Latest()
|
||||
@ -403,7 +403,7 @@ func getMapperAndResult(f cmdutil.Factory, args []string, options *resource.File
|
||||
|
||||
updatedResultGetter := func(data []byte) *resource.Result {
|
||||
// resource builder to read objects from edited data
|
||||
return resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
return resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
Stream(bytes.NewReader(data), "edited-file").
|
||||
ContinueOnError().
|
||||
Flatten().
|
||||
|
@ -127,7 +127,7 @@ func RunExpose(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
|
||||
}
|
||||
|
||||
mapper, typer := f.Object()
|
||||
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
r := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
ContinueOnError().
|
||||
NamespaceParam(namespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, options).
|
||||
|
@ -193,7 +193,7 @@ func RunGet(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args [
|
||||
// handle watch separately since we cannot watch multiple resource types
|
||||
isWatch, isWatchOnly := cmdutil.GetFlagBool(cmd, "watch"), cmdutil.GetFlagBool(cmd, "watch-only")
|
||||
if isWatch || isWatchOnly {
|
||||
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
r := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces).
|
||||
FilenameParam(enforceNamespace, &options.FilenameOptions).
|
||||
SelectorParam(selector).
|
||||
@ -283,7 +283,7 @@ func RunGet(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args [
|
||||
return nil
|
||||
}
|
||||
|
||||
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
r := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces).
|
||||
FilenameParam(enforceNamespace, &options.FilenameOptions).
|
||||
SelectorParam(selector).
|
||||
|
@ -185,7 +185,7 @@ func (o *LabelOptions) RunLabel(f cmdutil.Factory, cmd *cobra.Command) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
b := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
|
@ -198,7 +198,7 @@ func (o *LogsOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Comm
|
||||
mapper, typer := f.Object()
|
||||
decoder := f.Decoder(true)
|
||||
if o.Object == nil {
|
||||
builder := resource.NewBuilder(mapper, typer, o.ClientMapper, decoder).
|
||||
builder := resource.NewBuilder(mapper, f.CategoryExpander(), typer, o.ClientMapper, decoder).
|
||||
NamespaceParam(o.Namespace).DefaultNamespace().
|
||||
SingleResourceType()
|
||||
if o.ResourceArg != "" {
|
||||
|
@ -153,7 +153,7 @@ func RunPatch(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []strin
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
r := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &options.FilenameOptions).
|
||||
|
@ -129,7 +129,7 @@ func RunReplace(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
r := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
Schema(schema).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
@ -200,7 +200,7 @@ func forceReplace(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
r := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, options).
|
||||
@ -249,7 +249,7 @@ func forceReplace(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s
|
||||
})
|
||||
})
|
||||
|
||||
r = resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
r = resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme).
|
||||
Schema(schema).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
|
@ -205,7 +205,7 @@ func RunRollingUpdate(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args
|
||||
return err
|
||||
}
|
||||
|
||||
request := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
request := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
Schema(schema).
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &resource.FilenameOptions{Recursive: false, Filenames: []string{filename}}).
|
||||
|
@ -81,7 +81,7 @@ func RunHistory(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []str
|
||||
return err
|
||||
}
|
||||
|
||||
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
r := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, options).
|
||||
ResourceTypeOrNameArgs(true, args...).
|
||||
|
@ -111,7 +111,7 @@ func (o *PauseConfig) CompletePause(f cmdutil.Factory, cmd *cobra.Command, out i
|
||||
return err
|
||||
}
|
||||
|
||||
r := resource.NewBuilder(o.Mapper, o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
r := resource.NewBuilder(o.Mapper, f.CategoryExpander(), o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
ResourceTypeOrNameArgs(true, args...).
|
||||
|
@ -109,7 +109,7 @@ func (o *ResumeConfig) CompleteResume(f cmdutil.Factory, cmd *cobra.Command, out
|
||||
return err
|
||||
}
|
||||
|
||||
r := resource.NewBuilder(o.Mapper, o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
r := resource.NewBuilder(o.Mapper, f.CategoryExpander(), o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
ResourceTypeOrNameArgs(true, args...).
|
||||
|
@ -84,7 +84,7 @@ func RunStatus(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []stri
|
||||
return err
|
||||
}
|
||||
|
||||
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
r := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, options).
|
||||
ResourceTypeOrNameArgs(true, args...).
|
||||
|
@ -110,7 +110,7 @@ func (o *UndoOptions) CompleteUndo(f cmdutil.Factory, cmd *cobra.Command, out io
|
||||
return err
|
||||
}
|
||||
|
||||
r := resource.NewBuilder(o.Mapper, o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
r := resource.NewBuilder(o.Mapper, f.CategoryExpander(), o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
ResourceTypeOrNameArgs(true, args...).
|
||||
|
@ -339,7 +339,7 @@ func Run(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cobr
|
||||
return err
|
||||
}
|
||||
_, typer := f.Object()
|
||||
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
r := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
ContinueOnError().
|
||||
NamespaceParam(namespace).DefaultNamespace().
|
||||
ResourceNames(mapping.Resource, name).
|
||||
|
@ -106,7 +106,7 @@ func RunScale(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []strin
|
||||
}
|
||||
|
||||
mapper, typer := f.Object()
|
||||
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
r := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, options).
|
||||
|
@ -136,7 +136,7 @@ func (o *ImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st
|
||||
return err
|
||||
}
|
||||
|
||||
builder := resource.NewBuilder(o.Mapper, o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
builder := resource.NewBuilder(o.Mapper, f.CategoryExpander(), o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
|
@ -140,7 +140,7 @@ func (o *ResourcesOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
|
||||
return err
|
||||
}
|
||||
|
||||
builder := resource.NewBuilder(o.Mapper, o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
builder := resource.NewBuilder(o.Mapper, f.CategoryExpander(), o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
//FilenameParam(enforceNamespace, o.Filenames...).
|
||||
|
@ -84,7 +84,7 @@ func RunStop(f cmdutil.Factory, cmd *cobra.Command, args []string, out io.Writer
|
||||
}
|
||||
|
||||
mapper, typer := f.Object()
|
||||
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
r := resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
ResourceTypeOrNameArgs(false, args...).
|
||||
|
@ -226,7 +226,7 @@ func (o *TaintOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Com
|
||||
}
|
||||
|
||||
mapper, typer := f.Object()
|
||||
o.builder = resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
o.builder = resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
|
||||
ContinueOnError().
|
||||
NamespaceParam(namespace).DefaultNamespace()
|
||||
if o.all {
|
||||
|
@ -277,6 +277,10 @@ func (f *FakeFactory) UnstructuredObject() (meta.RESTMapper, runtime.ObjectTyper
|
||||
return expander, typer, err
|
||||
}
|
||||
|
||||
func (f *FakeFactory) CategoryExpander() resource.CategoryExpander {
|
||||
return resource.LegacyCategoryExpander
|
||||
}
|
||||
|
||||
func (f *FakeFactory) Decoder(bool) runtime.Decoder {
|
||||
return f.Codec
|
||||
}
|
||||
@ -689,7 +693,7 @@ func (f *fakeAPIFactory) PrinterForMapping(cmd *cobra.Command, mapping *meta.RES
|
||||
func (f *fakeAPIFactory) NewBuilder() *resource.Builder {
|
||||
mapper, typer := f.Object()
|
||||
|
||||
return resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true))
|
||||
return resource.NewBuilder(mapper, f.CategoryExpander(), typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true))
|
||||
}
|
||||
|
||||
func (f *fakeAPIFactory) SuggestedPodTemplateResources() []schema.GroupResource {
|
||||
|
@ -189,6 +189,8 @@ type ObjectMappingFactory interface {
|
||||
// Returns interfaces for dealing with arbitrary
|
||||
// runtime.Unstructured. This performs API calls to discover types.
|
||||
UnstructuredObject() (meta.RESTMapper, runtime.ObjectTyper, error)
|
||||
// Returns interface for expanding categories like `all`.
|
||||
CategoryExpander() resource.CategoryExpander
|
||||
// Returns a RESTClient for working with the specified RESTMapping or an error. This is intended
|
||||
// for working with arbitrary resources and is not guaranteed to point to a Kubernetes APIServer.
|
||||
ClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error)
|
||||
|
@ -126,6 +126,7 @@ func (f *ring2Factory) PrintObject(cmd *cobra.Command, mapper meta.RESTMapper, o
|
||||
|
||||
func (f *ring2Factory) NewBuilder() *resource.Builder {
|
||||
mapper, typer := f.objectMappingFactory.Object()
|
||||
categoryExpander := f.objectMappingFactory.CategoryExpander()
|
||||
|
||||
return resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.objectMappingFactory.ClientForMapping), f.clientAccessFactory.Decoder(true))
|
||||
return resource.NewBuilder(mapper, categoryExpander, typer, resource.ClientMapperFunc(f.objectMappingFactory.ClientForMapping), f.clientAccessFactory.Decoder(true))
|
||||
}
|
||||
|
@ -105,6 +105,20 @@ func (f *ring1Factory) UnstructuredObject() (meta.RESTMapper, runtime.ObjectType
|
||||
return expander, typer, err
|
||||
}
|
||||
|
||||
func (f *ring1Factory) CategoryExpander() resource.CategoryExpander {
|
||||
var categoryExpander resource.CategoryExpander
|
||||
categoryExpander = resource.LegacyCategoryExpander
|
||||
discoveryClient, err := f.clientAccessFactory.DiscoveryClient()
|
||||
if err == nil {
|
||||
// wrap with discovery based filtering
|
||||
categoryExpander, err = resource.NewDiscoveryFilteredExpander(categoryExpander, discoveryClient)
|
||||
// you only have an error on missing discoveryClient, so this shouldn't fail. Check anyway.
|
||||
CheckErr(err)
|
||||
}
|
||||
|
||||
return categoryExpander
|
||||
}
|
||||
|
||||
func (f *ring1Factory) ClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) {
|
||||
cfg, err := f.clientAccessFactory.ClientConfig()
|
||||
if err != nil {
|
||||
|
@ -740,12 +740,12 @@ func TestDiscoveryReplaceAliases(t *testing.T) {
|
||||
{
|
||||
name: "all-replacement",
|
||||
arg: "all",
|
||||
expected: "pods,replicationcontrollers,services,statefulsets,horizontalpodautoscalers,jobs,deployments,replicasets",
|
||||
expected: "pods,replicationcontrollers,services,statefulsets.apps,horizontalpodautoscalers.autoscaling,jobs.batch,deployments.extensions,replicasets.extensions",
|
||||
},
|
||||
{
|
||||
name: "alias-in-comma-separated-arg",
|
||||
arg: "all,secrets",
|
||||
expected: "pods,replicationcontrollers,services,statefulsets,horizontalpodautoscalers,jobs,deployments,replicasets,secrets",
|
||||
expected: "pods,replicationcontrollers,services,statefulsets.apps,horizontalpodautoscalers.autoscaling,jobs.batch,deployments.extensions,replicasets.extensions,secrets",
|
||||
},
|
||||
}
|
||||
|
||||
@ -754,7 +754,7 @@ func TestDiscoveryReplaceAliases(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create shortcut expander, err = %s", err.Error())
|
||||
}
|
||||
b := resource.NewBuilder(mapper, api.Scheme, fakeClient(), testapi.Default.Codec())
|
||||
b := resource.NewBuilder(mapper, resource.LegacyCategoryExpander, api.Scheme, fakeClient(), testapi.Default.Codec())
|
||||
|
||||
for _, test := range tests {
|
||||
replaced := b.ReplaceAliases(test.arg)
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/discovery"
|
||||
@ -31,8 +32,6 @@ import (
|
||||
type shortcutExpander struct {
|
||||
RESTMapper meta.RESTMapper
|
||||
|
||||
All []schema.GroupResource
|
||||
|
||||
discoveryClient discovery.DiscoveryInterface
|
||||
}
|
||||
|
||||
@ -42,33 +41,7 @@ func NewShortcutExpander(delegate meta.RESTMapper, client discovery.DiscoveryInt
|
||||
if client == nil {
|
||||
return shortcutExpander{}, errors.New("Please provide discovery client to shortcut expander")
|
||||
}
|
||||
return shortcutExpander{All: UserResources, RESTMapper: delegate, discoveryClient: client}, nil
|
||||
}
|
||||
|
||||
func (e shortcutExpander) getAll() []schema.GroupResource {
|
||||
// Check if we have access to server resources
|
||||
apiResources, err := e.discoveryClient.ServerResources()
|
||||
if err != nil {
|
||||
return e.All
|
||||
}
|
||||
|
||||
availableResources, err := discovery.GroupVersionResources(apiResources)
|
||||
if err != nil {
|
||||
return e.All
|
||||
}
|
||||
|
||||
availableAll := []schema.GroupResource{}
|
||||
for _, requestedResource := range e.All {
|
||||
for availableResource := range availableResources {
|
||||
if requestedResource.Group == availableResource.Group &&
|
||||
requestedResource.Resource == availableResource.Resource {
|
||||
availableAll = append(availableAll, requestedResource)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return availableAll
|
||||
return shortcutExpander{RESTMapper: delegate, discoveryClient: client}, nil
|
||||
}
|
||||
|
||||
func (e shortcutExpander) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) {
|
||||
@ -99,38 +72,6 @@ func (e shortcutExpander) RESTMappings(gk schema.GroupKind, versions ...string)
|
||||
return e.RESTMapper.RESTMappings(gk, versions...)
|
||||
}
|
||||
|
||||
// UserResources are the resource names that apply to the primary, user facing resources used by
|
||||
// client tools. They are in deletion-first order - dependent resources should be last.
|
||||
// Should remain exported in order to expose a current list of resources to downstream
|
||||
// composition that wants to build on the concept of 'all' for their CLIs.
|
||||
var UserResources = []schema.GroupResource{
|
||||
{Group: "", Resource: "pods"},
|
||||
{Group: "", Resource: "replicationcontrollers"},
|
||||
{Group: "", Resource: "services"},
|
||||
{Group: "apps", Resource: "statefulsets"},
|
||||
{Group: "autoscaling", Resource: "horizontalpodautoscalers"},
|
||||
{Group: "batch", Resource: "jobs"},
|
||||
{Group: "extensions", Resource: "deployments"},
|
||||
{Group: "extensions", Resource: "replicasets"},
|
||||
}
|
||||
|
||||
// AliasesForResource returns whether a resource has an alias or not
|
||||
func (e shortcutExpander) AliasesForResource(resource string) ([]string, bool) {
|
||||
if strings.ToLower(resource) == "all" {
|
||||
var resources []schema.GroupResource
|
||||
if resources = e.getAll(); len(resources) == 0 {
|
||||
resources = UserResources
|
||||
}
|
||||
aliases := []string{}
|
||||
for _, r := range resources {
|
||||
aliases = append(aliases, r.Resource)
|
||||
}
|
||||
return aliases, true
|
||||
}
|
||||
expanded := e.expandResourceShortcut(schema.GroupVersionResource{Resource: resource}).Resource
|
||||
return []string{expanded}, (expanded != resource)
|
||||
}
|
||||
|
||||
// getShortcutMappings returns a set of tuples which holds short names for resources.
|
||||
// First the list of potential resources will be taken from the API server.
|
||||
// Next we will append the hardcoded list of resources - to be backward compatible with old servers.
|
||||
|
@ -17,7 +17,6 @@ limitations under the License.
|
||||
package util
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@ -29,43 +28,25 @@ func TestReplaceAliases(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
arg string
|
||||
expected string
|
||||
expected schema.GroupVersionResource
|
||||
srvRes []*metav1.APIResourceList
|
||||
}{
|
||||
{
|
||||
name: "no-replacement",
|
||||
arg: "service",
|
||||
expected: "service",
|
||||
srvRes: []*metav1.APIResourceList{},
|
||||
},
|
||||
{
|
||||
name: "all-replacement",
|
||||
arg: "all",
|
||||
expected: "pods,replicationcontrollers,services,statefulsets,horizontalpodautoscalers,jobs,deployments,replicasets",
|
||||
srvRes: []*metav1.APIResourceList{},
|
||||
},
|
||||
{
|
||||
name: "alias-in-comma-separated-arg",
|
||||
arg: "all,secrets",
|
||||
expected: "pods,replicationcontrollers,services,statefulsets,horizontalpodautoscalers,jobs,deployments,replicasets,secrets",
|
||||
srvRes: []*metav1.APIResourceList{},
|
||||
},
|
||||
{
|
||||
name: "rc-resolves-to-replicationcontrollers",
|
||||
arg: "rc",
|
||||
expected: "replicationcontrollers",
|
||||
expected: schema.GroupVersionResource{Resource: "replicationcontrollers"},
|
||||
srvRes: []*metav1.APIResourceList{},
|
||||
},
|
||||
{
|
||||
name: "storageclasses-no-replacement",
|
||||
arg: "storageclasses",
|
||||
expected: "storageclasses",
|
||||
expected: schema.GroupVersionResource{Resource: "storageclasses"},
|
||||
srvRes: []*metav1.APIResourceList{},
|
||||
},
|
||||
{
|
||||
name: "hpa-priority",
|
||||
arg: "hpa",
|
||||
expected: "superhorizontalpodautoscalers",
|
||||
expected: schema.GroupVersionResource{Resource: "superhorizontalpodautoscalers"},
|
||||
srvRes: []*metav1.APIResourceList{
|
||||
{
|
||||
GroupVersion: "autoscaling/v1",
|
||||
@ -96,16 +77,12 @@ func TestReplaceAliases(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
resources := []string{}
|
||||
ds.serverResourcesHandler = func() ([]*metav1.APIResourceList, error) {
|
||||
return test.srvRes, nil
|
||||
}
|
||||
for _, arg := range strings.Split(test.arg, ",") {
|
||||
curr, _ := mapper.AliasesForResource(arg)
|
||||
resources = append(resources, curr...)
|
||||
}
|
||||
if strings.Join(resources, ",") != test.expected {
|
||||
t.Errorf("%s: unexpected argument: expected %s, got %s", test.name, test.expected, resources)
|
||||
actual := mapper.expandResourceShortcut(schema.GroupVersionResource{Resource: test.arg})
|
||||
if actual != test.expected {
|
||||
t.Errorf("%s: unexpected argument: expected %s, got %s", test.name, test.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"builder.go",
|
||||
"categories.go",
|
||||
"doc.go",
|
||||
"helper.go",
|
||||
"interfaces.go",
|
||||
@ -40,6 +41,7 @@ go_library(
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/yaml",
|
||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||
"//vendor:k8s.io/client-go/discovery",
|
||||
"//vendor:k8s.io/client-go/rest",
|
||||
],
|
||||
)
|
||||
@ -48,6 +50,7 @@ go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"builder_test.go",
|
||||
"categories_test.go",
|
||||
"helper_test.go",
|
||||
"visitor_test.go",
|
||||
],
|
||||
@ -72,6 +75,7 @@ go_test(
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/labels",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/serializer/streaming",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/errors",
|
||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||
|
@ -42,7 +42,8 @@ const defaultHttpGetAttempts int = 3
|
||||
// from the command line and converting them to a list of resources to iterate
|
||||
// over using the Visitor interface.
|
||||
type Builder struct {
|
||||
mapper *Mapper
|
||||
mapper *Mapper
|
||||
categoryExpander CategoryExpander
|
||||
|
||||
errs []error
|
||||
|
||||
@ -105,10 +106,11 @@ type resourceTuple struct {
|
||||
}
|
||||
|
||||
// NewBuilder creates a builder that operates on generic objects.
|
||||
func NewBuilder(mapper meta.RESTMapper, typer runtime.ObjectTyper, clientMapper ClientMapper, decoder runtime.Decoder) *Builder {
|
||||
func NewBuilder(mapper meta.RESTMapper, categoryExpander CategoryExpander, typer runtime.ObjectTyper, clientMapper ClientMapper, decoder runtime.Decoder) *Builder {
|
||||
return &Builder{
|
||||
mapper: &Mapper{typer, mapper, clientMapper, decoder},
|
||||
requireObject: true,
|
||||
mapper: &Mapper{typer, mapper, clientMapper, decoder},
|
||||
categoryExpander: categoryExpander,
|
||||
requireObject: true,
|
||||
}
|
||||
}
|
||||
|
||||
@ -371,8 +373,16 @@ func (b *Builder) ResourceTypeOrNameArgs(allowEmptySelector bool, args ...string
|
||||
func (b *Builder) ReplaceAliases(input string) string {
|
||||
replaced := []string{}
|
||||
for _, arg := range strings.Split(input, ",") {
|
||||
if aliases, ok := b.mapper.AliasesForResource(arg); ok {
|
||||
arg = strings.Join(aliases, ",")
|
||||
if resources, ok := b.categoryExpander.Expand(arg); ok {
|
||||
asStrings := []string{}
|
||||
for _, resource := range resources {
|
||||
if len(resource.Group) == 0 {
|
||||
asStrings = append(asStrings, resource.Resource)
|
||||
continue
|
||||
}
|
||||
asStrings = append(asStrings, resource.Resource+"."+resource.Group)
|
||||
}
|
||||
arg = strings.Join(asStrings, ",")
|
||||
}
|
||||
replaced = append(replaced, arg)
|
||||
}
|
||||
|
@ -255,7 +255,7 @@ var aRC string = `
|
||||
`
|
||||
|
||||
func TestPathBuilderAndVersionedObjectNotDefaulted(t *testing.T) {
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../test/fixtures/pkg/kubectl/builder/kitten-rc.yaml"}})
|
||||
|
||||
test := &testVisitor{}
|
||||
@ -294,7 +294,7 @@ func TestNodeBuilder(t *testing.T) {
|
||||
w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), node)))
|
||||
}()
|
||||
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
NamespaceParam("test").Stream(r, "STDIN")
|
||||
|
||||
test := &testVisitor{}
|
||||
@ -358,7 +358,7 @@ func TestPathBuilderWithMultiple(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
FilenameParam(false, &FilenameOptions{Recursive: test.recursive, Filenames: []string{test.directory}}).
|
||||
NamespaceParam("test").DefaultNamespace()
|
||||
|
||||
@ -417,7 +417,7 @@ func TestPathBuilderWithMultipleInvalid(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
FilenameParam(false, &FilenameOptions{Recursive: test.recursive, Filenames: []string{test.directory}}).
|
||||
NamespaceParam("test").DefaultNamespace()
|
||||
|
||||
@ -432,7 +432,7 @@ func TestPathBuilderWithMultipleInvalid(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDirectoryBuilder(t *testing.T) {
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/guestbook/legacy"}}).
|
||||
NamespaceParam("test").DefaultNamespace()
|
||||
|
||||
@ -463,7 +463,7 @@ func TestNamespaceOverride(t *testing.T) {
|
||||
}))
|
||||
defer s.Close()
|
||||
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{s.URL}}).
|
||||
NamespaceParam("test")
|
||||
|
||||
@ -474,7 +474,7 @@ func TestNamespaceOverride(t *testing.T) {
|
||||
t.Fatalf("unexpected response: %v %#v", err, test.Infos)
|
||||
}
|
||||
|
||||
b = NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
b = NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
FilenameParam(true, &FilenameOptions{Recursive: false, Filenames: []string{s.URL}}).
|
||||
NamespaceParam("test")
|
||||
|
||||
@ -494,7 +494,7 @@ func TestURLBuilder(t *testing.T) {
|
||||
}))
|
||||
defer s.Close()
|
||||
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{s.URL}}).
|
||||
NamespaceParam("foo")
|
||||
|
||||
@ -523,7 +523,7 @@ func TestURLBuilderRequireNamespace(t *testing.T) {
|
||||
}))
|
||||
defer s.Close()
|
||||
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{s.URL}}).
|
||||
NamespaceParam("test").RequireNamespace()
|
||||
|
||||
@ -538,7 +538,7 @@ func TestURLBuilderRequireNamespace(t *testing.T) {
|
||||
|
||||
func TestResourceByName(t *testing.T) {
|
||||
pods, _ := testData()
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClientWith("", t, map[string]string{
|
||||
"/namespaces/test/pods/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[0]),
|
||||
}), testapi.Default.Codec()).
|
||||
NamespaceParam("test")
|
||||
@ -571,7 +571,7 @@ func TestResourceByName(t *testing.T) {
|
||||
|
||||
func TestMultipleResourceByTheSameName(t *testing.T) {
|
||||
pods, svcs := testData()
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClientWith("", t, map[string]string{
|
||||
"/namespaces/test/pods/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[0]),
|
||||
"/namespaces/test/pods/baz": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[1]),
|
||||
"/namespaces/test/services/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &svcs.Items[0]),
|
||||
@ -603,7 +603,7 @@ func TestMultipleResourceByTheSameName(t *testing.T) {
|
||||
|
||||
func TestResourceNames(t *testing.T) {
|
||||
pods, svc := testData()
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClientWith("", t, map[string]string{
|
||||
"/namespaces/test/pods/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[0]),
|
||||
"/namespaces/test/services/baz": runtime.EncodeOrDie(testapi.Default.Codec(), &svc.Items[0]),
|
||||
}), testapi.Default.Codec()).
|
||||
@ -631,7 +631,7 @@ func TestResourceNames(t *testing.T) {
|
||||
|
||||
func TestResourceNamesWithoutResource(t *testing.T) {
|
||||
pods, svc := testData()
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClientWith("", t, map[string]string{
|
||||
"/namespaces/test/pods/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[0]),
|
||||
"/namespaces/test/services/baz": runtime.EncodeOrDie(testapi.Default.Codec(), &svc.Items[0]),
|
||||
}), testapi.Default.Codec()).
|
||||
@ -652,7 +652,7 @@ func TestResourceNamesWithoutResource(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResourceByNameWithoutRequireObject(t *testing.T) {
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{}), testapi.Default.Codec()).
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClientWith("", t, map[string]string{}), testapi.Default.Codec()).
|
||||
NamespaceParam("test")
|
||||
|
||||
test := &testVisitor{}
|
||||
@ -686,7 +686,7 @@ func TestResourceByNameWithoutRequireObject(t *testing.T) {
|
||||
|
||||
func TestResourceByNameAndEmptySelector(t *testing.T) {
|
||||
pods, _ := testData()
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClientWith("", t, map[string]string{
|
||||
"/namespaces/test/pods/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[0]),
|
||||
}), testapi.Default.Codec()).
|
||||
NamespaceParam("test").
|
||||
@ -714,7 +714,7 @@ func TestResourceByNameAndEmptySelector(t *testing.T) {
|
||||
func TestSelector(t *testing.T) {
|
||||
pods, svc := testData()
|
||||
labelKey := metav1.LabelSelectorQueryParam(api.Registry.GroupOrDie(api.GroupName).GroupVersion.String())
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClientWith("", t, map[string]string{
|
||||
"/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), pods),
|
||||
"/namespaces/test/services?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), svc),
|
||||
}), testapi.Default.Codec()).
|
||||
@ -745,7 +745,7 @@ func TestSelector(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSelectorRequiresKnownTypes(t *testing.T) {
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
SelectorParam("a=b").
|
||||
NamespaceParam("test").
|
||||
ResourceTypes("unknown")
|
||||
@ -756,7 +756,7 @@ func TestSelectorRequiresKnownTypes(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSingleResourceType(t *testing.T) {
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
SelectorParam("a=b").
|
||||
SingleResourceType().
|
||||
ResourceTypeOrNameArgs(true, "pods,services")
|
||||
@ -826,7 +826,7 @@ func TestResourceTuple(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith(k, t, expectedRequests), testapi.Default.Codec()).
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClientWith(k, t, expectedRequests), testapi.Default.Codec()).
|
||||
NamespaceParam("test").DefaultNamespace().
|
||||
ResourceTypeOrNameArgs(true, testCase.args...).RequireObject(requireObject)
|
||||
|
||||
@ -857,7 +857,7 @@ func TestResourceTuple(t *testing.T) {
|
||||
|
||||
func TestStream(t *testing.T) {
|
||||
r, pods, rc := streamTestData()
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
NamespaceParam("test").Stream(r, "STDIN").Flatten()
|
||||
|
||||
test := &testVisitor{}
|
||||
@ -874,7 +874,7 @@ func TestStream(t *testing.T) {
|
||||
|
||||
func TestYAMLStream(t *testing.T) {
|
||||
r, pods, rc := streamYAMLTestData()
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
NamespaceParam("test").Stream(r, "STDIN").Flatten()
|
||||
|
||||
test := &testVisitor{}
|
||||
@ -891,7 +891,7 @@ func TestYAMLStream(t *testing.T) {
|
||||
|
||||
func TestMultipleObject(t *testing.T) {
|
||||
r, pods, svc := streamTestData()
|
||||
obj, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
obj, err := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
NamespaceParam("test").Stream(r, "STDIN").Flatten().
|
||||
Do().Object()
|
||||
|
||||
@ -913,7 +913,7 @@ func TestMultipleObject(t *testing.T) {
|
||||
|
||||
func TestContinueOnErrorVisitor(t *testing.T) {
|
||||
r, _, _ := streamTestData()
|
||||
req := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
req := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
ContinueOnError().
|
||||
NamespaceParam("test").Stream(r, "STDIN").Flatten().
|
||||
Do()
|
||||
@ -942,7 +942,7 @@ func TestContinueOnErrorVisitor(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSingleItemImpliedObject(t *testing.T) {
|
||||
obj, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
obj, err := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
NamespaceParam("test").DefaultNamespace().
|
||||
FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml"}}).
|
||||
Flatten().
|
||||
@ -962,7 +962,7 @@ func TestSingleItemImpliedObject(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSingleItemImpliedObjectNoExtension(t *testing.T) {
|
||||
obj, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
obj, err := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
NamespaceParam("test").DefaultNamespace().
|
||||
FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/pod"}}).
|
||||
Flatten().
|
||||
@ -984,7 +984,7 @@ func TestSingleItemImpliedObjectNoExtension(t *testing.T) {
|
||||
func TestSingleItemImpliedRootScopedObject(t *testing.T) {
|
||||
node := &api.Node{ObjectMeta: metav1.ObjectMeta{Name: "test"}, Spec: api.NodeSpec{ExternalID: "test"}}
|
||||
r := streamTestObject(node)
|
||||
infos, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
infos, err := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
NamespaceParam("test").DefaultNamespace().
|
||||
Stream(r, "STDIN").
|
||||
Flatten().
|
||||
@ -1009,7 +1009,7 @@ func TestSingleItemImpliedRootScopedObject(t *testing.T) {
|
||||
func TestListObject(t *testing.T) {
|
||||
pods, _ := testData()
|
||||
labelKey := metav1.LabelSelectorQueryParam(api.Registry.GroupOrDie(api.GroupName).GroupVersion.String())
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClientWith("", t, map[string]string{
|
||||
"/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), pods),
|
||||
}), testapi.Default.Codec()).
|
||||
SelectorParam("a=b").
|
||||
@ -1042,7 +1042,7 @@ func TestListObject(t *testing.T) {
|
||||
func TestListObjectWithDifferentVersions(t *testing.T) {
|
||||
pods, svc := testData()
|
||||
labelKey := metav1.LabelSelectorQueryParam(api.Registry.GroupOrDie(api.GroupName).GroupVersion.String())
|
||||
obj, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{
|
||||
obj, err := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClientWith("", t, map[string]string{
|
||||
"/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), pods),
|
||||
"/namespaces/test/services?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), svc),
|
||||
}), testapi.Default.Codec()).
|
||||
@ -1068,7 +1068,7 @@ func TestListObjectWithDifferentVersions(t *testing.T) {
|
||||
|
||||
func TestWatch(t *testing.T) {
|
||||
_, svc := testData()
|
||||
w, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{
|
||||
w, err := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClientWith("", t, map[string]string{
|
||||
"/namespaces/test/services?fieldSelector=metadata.name%3Dredis-master&resourceVersion=12&watch=true": watchBody(watch.Event{
|
||||
Type: watch.Added,
|
||||
Object: &svc.Items[0],
|
||||
@ -1100,7 +1100,7 @@ func TestWatch(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWatchMultipleError(t *testing.T) {
|
||||
_, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
_, err := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
NamespaceParam("test").DefaultNamespace().
|
||||
FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml"}}).Flatten().
|
||||
FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml"}}).Flatten().
|
||||
@ -1123,7 +1123,7 @@ func TestLatest(t *testing.T) {
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "15"},
|
||||
}
|
||||
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClientWith("", t, map[string]string{
|
||||
"/namespaces/test/pods/foo": runtime.EncodeOrDie(testapi.Default.Codec(), newPod),
|
||||
"/namespaces/test/pods/bar": runtime.EncodeOrDie(testapi.Default.Codec(), newPod2),
|
||||
"/namespaces/test/services/baz": runtime.EncodeOrDie(testapi.Default.Codec(), newSvc),
|
||||
@ -1159,7 +1159,7 @@ func TestReceiveMultipleErrors(t *testing.T) {
|
||||
w2.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), &svc.Items[0])))
|
||||
}()
|
||||
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
b := NewBuilder(testapi.Default.RESTMapper(), LegacyCategoryExpander, api.Scheme, fakeClient(), testapi.Default.Codec()).
|
||||
Stream(r, "1").Stream(r2, "2").
|
||||
ContinueOnError()
|
||||
|
||||
|
109
pkg/kubectl/resource/categories.go
Normal file
109
pkg/kubectl/resource/categories.go
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
Copyright 2017 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 resource
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/discovery"
|
||||
)
|
||||
|
||||
type CategoryExpander interface {
|
||||
Expand(category string) ([]schema.GroupResource, bool)
|
||||
}
|
||||
|
||||
type SimpleCategoryExpander struct {
|
||||
Expansions map[string][]schema.GroupResource
|
||||
}
|
||||
|
||||
func (e SimpleCategoryExpander) Expand(category string) ([]schema.GroupResource, bool) {
|
||||
ret, ok := e.Expansions[category]
|
||||
return ret, ok
|
||||
}
|
||||
|
||||
type discoveryFilteredExpander struct {
|
||||
delegate CategoryExpander
|
||||
|
||||
discoveryClient discovery.DiscoveryInterface
|
||||
}
|
||||
|
||||
// NewDiscoveryFilteredExpander returns a category expander that filters the returned groupresources by
|
||||
// what the server has available
|
||||
func NewDiscoveryFilteredExpander(delegate CategoryExpander, client discovery.DiscoveryInterface) (discoveryFilteredExpander, error) {
|
||||
if client == nil {
|
||||
return discoveryFilteredExpander{}, errors.New("Please provide discovery client to shortcut expander")
|
||||
}
|
||||
return discoveryFilteredExpander{delegate: delegate, discoveryClient: client}, nil
|
||||
}
|
||||
|
||||
func (e discoveryFilteredExpander) Expand(category string) ([]schema.GroupResource, bool) {
|
||||
delegateExpansion, ok := e.delegate.Expand(category)
|
||||
|
||||
// Check if we have access to server resources
|
||||
apiResources, err := e.discoveryClient.ServerResources()
|
||||
if err != nil {
|
||||
return delegateExpansion, ok
|
||||
}
|
||||
|
||||
availableResources, err := discovery.GroupVersionResources(apiResources)
|
||||
if err != nil {
|
||||
return delegateExpansion, ok
|
||||
}
|
||||
|
||||
available := []schema.GroupResource{}
|
||||
for _, requestedResource := range delegateExpansion {
|
||||
for availableResource := range availableResources {
|
||||
if requestedResource.Group == availableResource.Group &&
|
||||
requestedResource.Resource == availableResource.Resource {
|
||||
available = append(available, requestedResource)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return available, ok
|
||||
}
|
||||
|
||||
// legacyUserResources are the resource names that apply to the primary, user facing resources used by
|
||||
// client tools. They are in deletion-first order - dependent resources should be last.
|
||||
// Should remain exported in order to expose a current list of resources to downstream
|
||||
// composition that wants to build on the concept of 'all' for their CLIs.
|
||||
var legacyUserResources = []schema.GroupResource{
|
||||
{Group: "", Resource: "pods"},
|
||||
{Group: "", Resource: "replicationcontrollers"},
|
||||
{Group: "", Resource: "services"},
|
||||
{Group: "apps", Resource: "statefulsets"},
|
||||
{Group: "autoscaling", Resource: "horizontalpodautoscalers"},
|
||||
{Group: "batch", Resource: "jobs"},
|
||||
{Group: "extensions", Resource: "deployments"},
|
||||
{Group: "extensions", Resource: "replicasets"},
|
||||
}
|
||||
|
||||
// LegacyCategoryExpander is the old hardcoded expansion
|
||||
var LegacyCategoryExpander CategoryExpander = SimpleCategoryExpander{
|
||||
Expansions: map[string][]schema.GroupResource{
|
||||
"all": legacyUserResources,
|
||||
},
|
||||
}
|
||||
|
||||
// LegacyFederationCategoryExpander is the old hardcoded expansion for federation
|
||||
var LegacyFederationCategoryExpander CategoryExpander = SimpleCategoryExpander{
|
||||
Expansions: map[string][]schema.GroupResource{
|
||||
"all": {{Group: "", Resource: "services"}},
|
||||
},
|
||||
}
|
65
pkg/kubectl/resource/categories_test.go
Normal file
65
pkg/kubectl/resource/categories_test.go
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
Copyright 2017 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 resource
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
func TestCategoryExpansion(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
arg string
|
||||
|
||||
expected []schema.GroupResource
|
||||
expectedOk bool
|
||||
}{
|
||||
{
|
||||
name: "no-replacement",
|
||||
arg: "service",
|
||||
expected: nil,
|
||||
},
|
||||
{
|
||||
name: "all-replacement",
|
||||
arg: "all",
|
||||
expected: []schema.GroupResource{
|
||||
{Resource: "pods"},
|
||||
{Resource: "replicationcontrollers"},
|
||||
{Resource: "services"},
|
||||
{Resource: "statefulsets", Group: "apps"},
|
||||
{Resource: "horizontalpodautoscalers", Group: "autoscaling"},
|
||||
{Resource: "jobs", Group: "batch"},
|
||||
{Resource: "deployments", Group: "extensions"},
|
||||
{Resource: "replicasets", Group: "extensions"},
|
||||
},
|
||||
expectedOk: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
actual, actualOk := LegacyCategoryExpander.Expand(test.arg)
|
||||
if e, a := test.expected, actual; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("%s: expected %s, got %s", test.name, e, a)
|
||||
}
|
||||
if e, a := test.expectedOk, actualOk; e != a {
|
||||
t.Errorf("%s: expected %v, got %v", test.name, e, a)
|
||||
}
|
||||
}
|
||||
}
|
@ -171,10 +171,6 @@ func (t *thirdPartyResourceDataMapper) RESTMappings(gk schema.GroupKind, version
|
||||
return mappings, nil
|
||||
}
|
||||
|
||||
func (t *thirdPartyResourceDataMapper) AliasesForResource(resource string) ([]string, bool) {
|
||||
return t.mapper.AliasesForResource(resource)
|
||||
}
|
||||
|
||||
func (t *thirdPartyResourceDataMapper) ResourceSingularizer(resource string) (singular string, err error) {
|
||||
return t.mapper.ResourceSingularizer(resource)
|
||||
}
|
||||
|
@ -142,6 +142,5 @@ type RESTMapper interface {
|
||||
// the provided version(s).
|
||||
RESTMappings(gk schema.GroupKind, versions ...string) ([]*RESTMapping, error)
|
||||
|
||||
AliasesForResource(resource string) ([]string, bool)
|
||||
ResourceSingularizer(resource string) (singular string, err error)
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ import (
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
)
|
||||
|
||||
// MultiRESTMapper is a wrapper for multiple RESTMappers.
|
||||
@ -209,23 +208,3 @@ func (m MultiRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string) (
|
||||
}
|
||||
return allMappings, nil
|
||||
}
|
||||
|
||||
// AliasesForResource finds the first alias response for the provided mappers.
|
||||
func (m MultiRESTMapper) AliasesForResource(alias string) ([]string, bool) {
|
||||
seenAliases := sets.NewString()
|
||||
allAliases := []string{}
|
||||
handled := false
|
||||
|
||||
for _, t := range m {
|
||||
if currAliases, currOk := t.AliasesForResource(alias); currOk {
|
||||
for _, currAlias := range currAliases {
|
||||
if !seenAliases.Has(currAlias) {
|
||||
allAliases = append(allAliases, currAlias)
|
||||
seenAliases.Insert(currAlias)
|
||||
}
|
||||
}
|
||||
handled = true
|
||||
}
|
||||
}
|
||||
return allAliases, handled
|
||||
}
|
||||
|
@ -350,10 +350,6 @@ func (m fixedRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string) (
|
||||
return m.mappings, m.err
|
||||
}
|
||||
|
||||
func (m fixedRESTMapper) AliasesForResource(alias string) (aliases []string, ok bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (m fixedRESTMapper) ResourceIsValid(resource schema.GroupVersionResource) bool {
|
||||
return false
|
||||
}
|
||||
|
@ -209,10 +209,6 @@ func (m PriorityRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string
|
||||
return m.Delegate.RESTMappings(gk, versions...)
|
||||
}
|
||||
|
||||
func (m PriorityRESTMapper) AliasesForResource(alias string) (aliases []string, ok bool) {
|
||||
return m.Delegate.AliasesForResource(alias)
|
||||
}
|
||||
|
||||
func (m PriorityRESTMapper) ResourceSingularizer(resource string) (singular string, err error) {
|
||||
return m.Delegate.ResourceSingularizer(resource)
|
||||
}
|
||||
|
@ -79,9 +79,6 @@ type DefaultRESTMapper struct {
|
||||
pluralToSingular map[schema.GroupVersionResource]schema.GroupVersionResource
|
||||
|
||||
interfacesFunc VersionInterfacesFunc
|
||||
|
||||
// aliasToResource is used for mapping aliases to resources
|
||||
aliasToResource map[string][]string
|
||||
}
|
||||
|
||||
func (m *DefaultRESTMapper) String() string {
|
||||
@ -105,7 +102,6 @@ func NewDefaultRESTMapper(defaultGroupVersions []schema.GroupVersion, f VersionI
|
||||
kindToScope := make(map[schema.GroupVersionKind]RESTScope)
|
||||
singularToPlural := make(map[schema.GroupVersionResource]schema.GroupVersionResource)
|
||||
pluralToSingular := make(map[schema.GroupVersionResource]schema.GroupVersionResource)
|
||||
aliasToResource := make(map[string][]string)
|
||||
// TODO: verify name mappings work correctly when versions differ
|
||||
|
||||
return &DefaultRESTMapper{
|
||||
@ -115,7 +111,6 @@ func NewDefaultRESTMapper(defaultGroupVersions []schema.GroupVersion, f VersionI
|
||||
defaultGroupVersions: defaultGroupVersions,
|
||||
singularToPlural: singularToPlural,
|
||||
pluralToSingular: pluralToSingular,
|
||||
aliasToResource: aliasToResource,
|
||||
interfacesFunc: f,
|
||||
}
|
||||
}
|
||||
@ -548,19 +543,3 @@ func (m *DefaultRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string
|
||||
}
|
||||
return mappings, nil
|
||||
}
|
||||
|
||||
// AddResourceAlias maps aliases to resources
|
||||
func (m *DefaultRESTMapper) AddResourceAlias(alias string, resources ...string) {
|
||||
if len(resources) == 0 {
|
||||
return
|
||||
}
|
||||
m.aliasToResource[alias] = resources
|
||||
}
|
||||
|
||||
// AliasesForResource returns whether a resource has an alias or not
|
||||
func (m *DefaultRESTMapper) AliasesForResource(alias string) ([]string, bool) {
|
||||
if res, ok := m.aliasToResource[alias]; ok {
|
||||
return res, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
@ -277,20 +277,6 @@ func (d *DeferredDiscoveryRESTMapper) RESTMappings(gk schema.GroupKind, versions
|
||||
return
|
||||
}
|
||||
|
||||
// AliasesForResource returns whether a resource has an alias or not.
|
||||
func (d *DeferredDiscoveryRESTMapper) AliasesForResource(resource string) (as []string, ok bool) {
|
||||
del, err := d.getDelegate()
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
as, ok = del.AliasesForResource(resource)
|
||||
if len(as) == 0 && !d.cl.Fresh() {
|
||||
d.Reset()
|
||||
as, ok = d.AliasesForResource(resource)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ResourceSingularizer converts a resource name from plural to
|
||||
// singular (e.g., from pods to pod).
|
||||
func (d *DeferredDiscoveryRESTMapper) ResourceSingularizer(resource string) (singular string, err error) {
|
||||
|
Loading…
Reference in New Issue
Block a user