Don't filter items when resources requested by name

Add tracking on resource.Builder if a "named" item is requested (from
file, stream, url, or resource args) and use that in `get` to accurately
determine whether to filter resources. Add tests.
This commit is contained in:
Clayton Coleman
2017-02-27 21:36:42 -05:00
parent 70797f51e1
commit bace937438
4 changed files with 143 additions and 44 deletions

View File

@@ -567,25 +567,31 @@ func (b *Builder) visitorResult() *Result {
}
func (b *Builder) visitBySelector() *Result {
result := &Result{
targetsSingleItems: false,
}
if len(b.names) != 0 {
return &Result{err: fmt.Errorf("name cannot be provided when a selector is specified")}
return result.withError(fmt.Errorf("name cannot be provided when a selector is specified"))
}
if len(b.resourceTuples) != 0 {
return &Result{err: fmt.Errorf("selectors and the all flag cannot be used when passing resource/name arguments")}
return result.withError(fmt.Errorf("selectors and the all flag cannot be used when passing resource/name arguments"))
}
if len(b.resources) == 0 {
return &Result{err: fmt.Errorf("at least one resource must be specified to use a selector")}
return result.withError(fmt.Errorf("at least one resource must be specified to use a selector"))
}
mappings, err := b.resourceMappings()
if err != nil {
return &Result{err: err}
result.err = err
return result
}
visitors := []Visitor{}
for _, mapping := range mappings {
client, err := b.mapper.ClientForMapping(mapping)
if err != nil {
return &Result{err: err}
result.err = err
return result
}
selectorNamespace := b.namespace
if mapping.Scope.Name() != meta.RESTScopeNameNamespace {
@@ -594,9 +600,12 @@ func (b *Builder) visitBySelector() *Result {
visitors = append(visitors, NewSelector(client, mapping, selectorNamespace, b.selector, b.export))
}
if b.continueOnError {
return &Result{visitor: EagerVisitorList(visitors), sources: visitors}
result.visitor = EagerVisitorList(visitors)
} else {
result.visitor = VisitorList(visitors)
}
return &Result{visitor: VisitorList(visitors), sources: visitors}
result.sources = visitors
return result
}
func (b *Builder) visitByResource() *Result {
@@ -607,14 +616,20 @@ func (b *Builder) visitByResource() *Result {
isSingleItemImplied = len(b.resourceTuples) == 1
}
result := &Result{
singleItemImplied: isSingleItemImplied,
targetsSingleItems: true,
}
if len(b.resources) != 0 {
return &Result{singleItemImplied: isSingleItemImplied, err: fmt.Errorf("you may not specify individual resources and bulk resources in the same call")}
return result.withError(fmt.Errorf("you may not specify individual resources and bulk resources in the same call"))
}
// retrieve one client for each resource
mappings, err := b.resourceTupleMappings()
if err != nil {
return &Result{singleItemImplied: isSingleItemImplied, err: err}
result.err = err
return result
}
clients := make(map[string]RESTClient)
for _, mapping := range mappings {
@@ -624,7 +639,8 @@ func (b *Builder) visitByResource() *Result {
}
client, err := b.mapper.ClientForMapping(mapping)
if err != nil {
return &Result{err: err}
result.err = err
return result
}
clients[s] = client
}
@@ -633,12 +649,12 @@ func (b *Builder) visitByResource() *Result {
for _, tuple := range b.resourceTuples {
mapping, ok := mappings[tuple.Resource]
if !ok {
return &Result{singleItemImplied: isSingleItemImplied, err: fmt.Errorf("resource %q is not recognized: %v", tuple.Resource, mappings)}
return result.withError(fmt.Errorf("resource %q is not recognized: %v", tuple.Resource, mappings))
}
s := fmt.Sprintf("%s/%s", mapping.GroupVersionKind.GroupVersion().String(), mapping.Resource)
client, ok := clients[s]
if !ok {
return &Result{singleItemImplied: isSingleItemImplied, err: fmt.Errorf("could not find a client for resource %q", tuple.Resource)}
return result.withError(fmt.Errorf("could not find a client for resource %q", tuple.Resource))
}
selectorNamespace := b.namespace
@@ -650,7 +666,7 @@ func (b *Builder) visitByResource() *Result {
if b.allNamespace {
errMsg = "a resource cannot be retrieved by name across all namespaces"
}
return &Result{singleItemImplied: isSingleItemImplied, err: fmt.Errorf(errMsg)}
return result.withError(fmt.Errorf(errMsg))
}
}
@@ -664,31 +680,38 @@ func (b *Builder) visitByResource() *Result {
} else {
visitors = VisitorList(items)
}
return &Result{singleItemImplied: isSingleItemImplied, visitor: visitors, sources: items}
result.visitor = visitors
result.sources = items
return result
}
func (b *Builder) visitByName() *Result {
isSingleItemImplied := len(b.names) == 1
result := &Result{
singleItemImplied: len(b.names) == 1,
targetsSingleItems: true,
}
if len(b.paths) != 0 {
return &Result{singleItemImplied: isSingleItemImplied, err: fmt.Errorf("when paths, URLs, or stdin is provided as input, you may not specify a resource by arguments as well")}
return result.withError(fmt.Errorf("when paths, URLs, or stdin is provided as input, you may not specify a resource by arguments as well"))
}
if len(b.resources) == 0 {
return &Result{singleItemImplied: isSingleItemImplied, err: fmt.Errorf("you must provide a resource and a resource name together")}
return result.withError(fmt.Errorf("you must provide a resource and a resource name together"))
}
if len(b.resources) > 1 {
return &Result{singleItemImplied: isSingleItemImplied, err: fmt.Errorf("you must specify only one resource")}
return result.withError(fmt.Errorf("you must specify only one resource"))
}
mappings, err := b.resourceMappings()
if err != nil {
return &Result{singleItemImplied: isSingleItemImplied, err: err}
result.err = err
return result
}
mapping := mappings[0]
client, err := b.mapper.ClientForMapping(mapping)
if err != nil {
return &Result{err: err}
result.err = err
return result
}
selectorNamespace := b.namespace
@@ -700,7 +723,7 @@ func (b *Builder) visitByName() *Result {
if b.allNamespace {
errMsg = "a resource cannot be retrieved by name across all namespaces"
}
return &Result{singleItemImplied: isSingleItemImplied, err: fmt.Errorf(errMsg)}
return result.withError(fmt.Errorf(errMsg))
}
}
@@ -709,19 +732,25 @@ func (b *Builder) visitByName() *Result {
info := NewInfo(client, mapping, selectorNamespace, name, b.export)
visitors = append(visitors, info)
}
return &Result{singleItemImplied: isSingleItemImplied, visitor: VisitorList(visitors), sources: visitors}
result.visitor = VisitorList(visitors)
result.sources = visitors
return result
}
func (b *Builder) visitByPaths() *Result {
singleItemImplied := !b.dir && !b.stream && len(b.paths) == 1
result := &Result{
singleItemImplied: !b.dir && !b.stream && len(b.paths) == 1,
targetsSingleItems: true,
}
if len(b.resources) != 0 {
return &Result{singleItemImplied: singleItemImplied, err: fmt.Errorf("when paths, URLs, or stdin is provided as input, you may not specify resource arguments as well")}
return result.withError(fmt.Errorf("when paths, URLs, or stdin is provided as input, you may not specify resource arguments as well"))
}
if len(b.names) != 0 {
return &Result{err: fmt.Errorf("name cannot be provided when a path is specified")}
return result.withError(fmt.Errorf("name cannot be provided when a path is specified"))
}
if len(b.resourceTuples) != 0 {
return &Result{err: fmt.Errorf("resource/name arguments cannot be provided when a path is specified")}
return result.withError(fmt.Errorf("resource/name arguments cannot be provided when a path is specified"))
}
var visitors Visitor
@@ -746,7 +775,9 @@ func (b *Builder) visitByPaths() *Result {
if b.selector != nil {
visitors = NewFilteredVisitor(visitors, FilterBySelector(b.selector))
}
return &Result{singleItemImplied: singleItemImplied, visitor: visitors, sources: b.paths}
result.visitor = visitors
result.sources = b.paths
return result
}
// Do returns a Result object with a Visitor for the resources identified by the Builder.