Merge pull request #39038 from ncdc/fix-kubectl-get-list

Automatic merge from submit-queue

Fix kubectl get -f <file> -o <nondefault printer> so it prints all items in the file

**What this PR does / why we need it**: Fix kubectl get -f <file> -o <nondefault printer> so it prints all the objects in the file, instead of just the first one. Also add a test for this feature.

**Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes #38907 

**Special notes for your reviewer**:

**Release note**:

```release-note
```

cc @AdoHe @deads2k @liggitt @fabianofranz @kubernetes/kubectl @kubernetes/sig-cli-misc
This commit is contained in:
Kubernetes Submit Queue 2017-01-11 09:58:38 -08:00 committed by GitHub
commit 6e5b455b77
8 changed files with 117 additions and 103 deletions

View File

@ -1072,6 +1072,20 @@ run_kubectl_get_tests() {
# cleanup
kubectl delete pods valid-pod "${kube_flags[@]}"
### Test 'kubectl get -f <file> -o <non default printer>' prints all the items in the file's list
# Pre-condition: no POD exists
kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
# Command
kubectl create -f test/fixtures/doc-yaml/user-guide/multi-pod.yaml "${kube_flags[@]}"
# Post-condition: PODs redis-master and redis-proxy exist
# Check that all items in the list are printed
output_message=$(kubectl get -f test/fixtures/doc-yaml/user-guide/multi-pod.yaml -o jsonpath="{..metadata.name}" "${kube_flags[@]}")
kube::test::if_has_string "${output_message}" "redis-master redis-proxy"
# cleanup
kubectl delete pods redis-master redis-proxy "${kube_flags[@]}"
}
run_kubectl_request_timeout_tests() {

View File

@ -197,14 +197,14 @@ func (o AnnotateOptions) RunAnnotate(f cmdutil.Factory, cmd *cobra.Command) erro
return err
}
var singularResource bool
r.IntoSingular(&singularResource)
var singleItemImpliedResource bool
r.IntoSingleItemImplied(&singleItemImpliedResource)
// only apply resource version locking on a single resource.
// we must perform this check after o.builder.Do() as
// []o.resources can not not accurately return the proper number
// of resources when they are not passed in "resource/name" format.
if !singularResource && len(o.resourceVersion) > 0 {
if !singleItemImpliedResource && len(o.resourceVersion) > 0 {
return fmt.Errorf("--resource-version may only be used with a single resource")
}

View File

@ -162,8 +162,8 @@ func (o *ConvertOptions) RunConvert() error {
return err
}
singular := false
infos, err := r.IntoSingular(&singular).Infos()
singleItemImplied := false
infos, err := r.IntoSingleItemImplied(&singleItemImplied).Infos()
if err != nil {
return err
}
@ -172,7 +172,7 @@ func (o *ConvertOptions) RunConvert() error {
return fmt.Errorf("no objects passed to convert")
}
objects, err := resource.AsVersionedObject(infos, !singular, o.outputVersion, o.encoder)
objects, err := resource.AsVersionedObject(infos, !singleItemImplied, o.outputVersion, o.encoder)
if err != nil {
return err
}

View File

@ -307,10 +307,10 @@ func RunGet(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args [
// 2. if there is a single item and that item is a list, leave it as its specific list
// 3. if there is a single item and it is not a a list, leave it as a single item
var errs []error
singular := false
infos, err := r.IntoSingular(&singular).Infos()
singleItemImplied := false
infos, err := r.IntoSingleItemImplied(&singleItemImplied).Infos()
if err != nil {
if singular {
if singleItemImplied {
return err
}
errs = append(errs, err)
@ -325,9 +325,7 @@ func RunGet(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args [
}
var obj runtime.Object
if singular {
obj = infos[0].Object
} else {
if !singleItemImplied || len(infos) > 1 {
// we have more than one item, so coerce all items into a list
list := &unstructured.UnstructuredList{
Object: map[string]interface{}{
@ -340,6 +338,8 @@ func RunGet(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args [
list.Items = append(list.Items, info.Object.(*unstructured.Unstructured))
}
obj = list
} else {
obj = infos[0].Object
}
isList := meta.IsListType(obj)

View File

@ -187,7 +187,7 @@ func (o *LabelOptions) RunLabel(f cmdutil.Factory, cmd *cobra.Command) error {
Latest()
}
one := false
r := b.Do().IntoSingular(&one)
r := b.Do().IntoSingleItemImplied(&one)
if err := r.Err(); err != nil {
return err
}

View File

@ -72,7 +72,7 @@ type Builder struct {
singleResourceType bool
continueOnError bool
singular bool
singleItemImplied bool
export bool
@ -139,7 +139,7 @@ func (b *Builder) FilenameParam(enforceNamespace bool, filenameOptions *Filename
b.URL(defaultHttpGetAttempts, url)
default:
if !recursive {
b.singular = true
b.singleItemImplied = true
}
b.Path(recursive, s)
}
@ -600,21 +600,21 @@ func (b *Builder) visitBySelector() *Result {
}
func (b *Builder) visitByResource() *Result {
// if b.singular is false, this could be by default, so double-check length
// of resourceTuples to determine if in fact it is singular or not
isSingular := b.singular
if !isSingular {
isSingular = len(b.resourceTuples) == 1
// if b.singleItemImplied is false, this could be by default, so double-check length
// of resourceTuples to determine if in fact it is singleItemImplied or not
isSingleItemImplied := b.singleItemImplied
if !isSingleItemImplied {
isSingleItemImplied = len(b.resourceTuples) == 1
}
if len(b.resources) != 0 {
return &Result{singular: isSingular, err: fmt.Errorf("you may not specify individual resources and bulk resources in the same call")}
return &Result{singleItemImplied: isSingleItemImplied, err: 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{singular: isSingular, err: err}
return &Result{singleItemImplied: isSingleItemImplied, err: err}
}
clients := make(map[string]RESTClient)
for _, mapping := range mappings {
@ -633,12 +633,12 @@ func (b *Builder) visitByResource() *Result {
for _, tuple := range b.resourceTuples {
mapping, ok := mappings[tuple.Resource]
if !ok {
return &Result{singular: isSingular, err: fmt.Errorf("resource %q is not recognized: %v", tuple.Resource, mappings)}
return &Result{singleItemImplied: isSingleItemImplied, err: 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{singular: isSingular, err: fmt.Errorf("could not find a client for resource %q", tuple.Resource)}
return &Result{singleItemImplied: isSingleItemImplied, err: fmt.Errorf("could not find a client for resource %q", tuple.Resource)}
}
selectorNamespace := b.namespace
@ -650,7 +650,7 @@ func (b *Builder) visitByResource() *Result {
if b.allNamespace {
errMsg = "a resource cannot be retrieved by name across all namespaces"
}
return &Result{singular: isSingular, err: fmt.Errorf(errMsg)}
return &Result{singleItemImplied: isSingleItemImplied, err: fmt.Errorf(errMsg)}
}
}
@ -664,25 +664,25 @@ func (b *Builder) visitByResource() *Result {
} else {
visitors = VisitorList(items)
}
return &Result{singular: isSingular, visitor: visitors, sources: items}
return &Result{singleItemImplied: isSingleItemImplied, visitor: visitors, sources: items}
}
func (b *Builder) visitByName() *Result {
isSingular := len(b.names) == 1
isSingleItemImplied := len(b.names) == 1
if len(b.paths) != 0 {
return &Result{singular: isSingular, err: fmt.Errorf("when paths, URLs, or stdin is provided as input, you may not specify a resource by arguments as well")}
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")}
}
if len(b.resources) == 0 {
return &Result{singular: isSingular, err: fmt.Errorf("you must provide a resource and a resource name together")}
return &Result{singleItemImplied: isSingleItemImplied, err: fmt.Errorf("you must provide a resource and a resource name together")}
}
if len(b.resources) > 1 {
return &Result{singular: isSingular, err: fmt.Errorf("you must specify only one resource")}
return &Result{singleItemImplied: isSingleItemImplied, err: fmt.Errorf("you must specify only one resource")}
}
mappings, err := b.resourceMappings()
if err != nil {
return &Result{singular: isSingular, err: err}
return &Result{singleItemImplied: isSingleItemImplied, err: err}
}
mapping := mappings[0]
@ -700,7 +700,7 @@ func (b *Builder) visitByName() *Result {
if b.allNamespace {
errMsg = "a resource cannot be retrieved by name across all namespaces"
}
return &Result{singular: isSingular, err: fmt.Errorf(errMsg)}
return &Result{singleItemImplied: isSingleItemImplied, err: fmt.Errorf(errMsg)}
}
}
@ -709,13 +709,13 @@ func (b *Builder) visitByName() *Result {
info := NewInfo(client, mapping, selectorNamespace, name, b.export)
visitors = append(visitors, info)
}
return &Result{singular: isSingular, visitor: VisitorList(visitors), sources: visitors}
return &Result{singleItemImplied: isSingleItemImplied, visitor: VisitorList(visitors), sources: visitors}
}
func (b *Builder) visitByPaths() *Result {
singular := !b.dir && !b.stream && len(b.paths) == 1
singleItemImplied := !b.dir && !b.stream && len(b.paths) == 1
if len(b.resources) != 0 {
return &Result{singular: singular, err: fmt.Errorf("when paths, URLs, or stdin is provided as input, you may not specify resource arguments as well")}
return &Result{singleItemImplied: singleItemImplied, err: 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")}
@ -746,7 +746,7 @@ func (b *Builder) visitByPaths() *Result {
if b.selector != nil {
visitors = NewFilteredVisitor(visitors, FilterBySelector(b.selector))
}
return &Result{singular: singular, visitor: visitors, sources: b.paths}
return &Result{singleItemImplied: singleItemImplied, visitor: visitors, sources: b.paths}
}
// Do returns a Result object with a Visitor for the resources identified by the Builder.

View File

@ -258,11 +258,11 @@ func TestPathBuilderAndVersionedObjectNotDefaulted(t *testing.T) {
FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../test/fixtures/pkg/kubectl/builder/kitten-rc.yaml"}})
test := &testVisitor{}
singular := false
singleItemImplied := false
err := b.Do().IntoSingular(&singular).Visit(test.Handle)
if err != nil || !singular || len(test.Infos) != 1 {
t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos)
err := b.Do().IntoSingleItemImplied(&singleItemImplied).Visit(test.Handle)
if err != nil || !singleItemImplied || len(test.Infos) != 1 {
t.Fatalf("unexpected response: %v %t %#v", err, singleItemImplied, test.Infos)
}
info := test.Infos[0]
@ -362,11 +362,11 @@ func TestPathBuilderWithMultiple(t *testing.T) {
NamespaceParam("test").DefaultNamespace()
testVisitor := &testVisitor{}
singular := false
singleItemImplied := false
err := b.Do().IntoSingular(&singular).Visit(testVisitor.Handle)
err := b.Do().IntoSingleItemImplied(&singleItemImplied).Visit(testVisitor.Handle)
if err != nil {
t.Fatalf("unexpected response: %v %t %#v %s", err, singular, testVisitor.Infos, test.name)
t.Fatalf("unexpected response: %v %t %#v %s", err, singleItemImplied, testVisitor.Infos, test.name)
}
info := testVisitor.Infos
@ -421,11 +421,11 @@ func TestPathBuilderWithMultipleInvalid(t *testing.T) {
NamespaceParam("test").DefaultNamespace()
testVisitor := &testVisitor{}
singular := false
singleItemImplied := false
err := b.Do().IntoSingular(&singular).Visit(testVisitor.Handle)
err := b.Do().IntoSingleItemImplied(&singleItemImplied).Visit(testVisitor.Handle)
if err == nil {
t.Fatalf("unexpected response: %v %t %#v %s", err, singular, testVisitor.Infos, test.name)
t.Fatalf("unexpected response: %v %t %#v %s", err, singleItemImplied, testVisitor.Infos, test.name)
}
}
}
@ -436,11 +436,11 @@ func TestDirectoryBuilder(t *testing.T) {
NamespaceParam("test").DefaultNamespace()
test := &testVisitor{}
singular := false
singleItemImplied := false
err := b.Do().IntoSingular(&singular).Visit(test.Handle)
if err != nil || singular || len(test.Infos) < 3 {
t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos)
err := b.Do().IntoSingleItemImplied(&singleItemImplied).Visit(test.Handle)
if err != nil || singleItemImplied || len(test.Infos) < 3 {
t.Fatalf("unexpected response: %v %t %#v", err, singleItemImplied, test.Infos)
}
found := false
@ -527,11 +527,11 @@ func TestURLBuilderRequireNamespace(t *testing.T) {
NamespaceParam("test").RequireNamespace()
test := &testVisitor{}
singular := false
singleItemImplied := false
err := b.Do().IntoSingular(&singular).Visit(test.Handle)
if err == nil || !singular || len(test.Infos) != 0 {
t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos)
err := b.Do().IntoSingleItemImplied(&singleItemImplied).Visit(test.Handle)
if err == nil || !singleItemImplied || len(test.Infos) != 0 {
t.Fatalf("unexpected response: %v %t %#v", err, singleItemImplied, test.Infos)
}
}
@ -543,7 +543,7 @@ func TestResourceByName(t *testing.T) {
NamespaceParam("test")
test := &testVisitor{}
singular := false
singleItemImplied := false
if b.Do().Err() == nil {
t.Errorf("unexpected non-error")
@ -551,9 +551,9 @@ func TestResourceByName(t *testing.T) {
b.ResourceTypeOrNameArgs(true, "pods", "foo")
err := b.Do().IntoSingular(&singular).Visit(test.Handle)
if err != nil || !singular || len(test.Infos) != 1 {
t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos)
err := b.Do().IntoSingleItemImplied(&singleItemImplied).Visit(test.Handle)
if err != nil || !singleItemImplied || len(test.Infos) != 1 {
t.Fatalf("unexpected response: %v %t %#v", err, singleItemImplied, test.Infos)
}
if !reflect.DeepEqual(&pods.Items[0], test.Objects()[0]) {
t.Errorf("unexpected object: %#v", test.Objects()[0])
@ -579,7 +579,7 @@ func TestMultipleResourceByTheSameName(t *testing.T) {
NamespaceParam("test")
test := &testVisitor{}
singular := false
singleItemImplied := false
if b.Do().Err() == nil {
t.Errorf("unexpected non-error")
@ -587,9 +587,9 @@ func TestMultipleResourceByTheSameName(t *testing.T) {
b.ResourceTypeOrNameArgs(true, "pods,services", "foo", "baz")
err := b.Do().IntoSingular(&singular).Visit(test.Handle)
if err != nil || singular || len(test.Infos) != 4 {
t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos)
err := b.Do().IntoSingleItemImplied(&singleItemImplied).Visit(test.Handle)
if err != nil || singleItemImplied || len(test.Infos) != 4 {
t.Fatalf("unexpected response: %v %t %#v", err, singleItemImplied, test.Infos)
}
if !api.Semantic.DeepDerivative([]runtime.Object{&pods.Items[0], &pods.Items[1], &svcs.Items[0], &svcs.Items[0]}, test.Objects()) {
t.Errorf("unexpected visited objects: %#v", test.Objects())
@ -655,7 +655,7 @@ func TestResourceByNameWithoutRequireObject(t *testing.T) {
NamespaceParam("test")
test := &testVisitor{}
singular := false
singleItemImplied := false
if b.Do().Err() == nil {
t.Errorf("unexpected non-error")
@ -663,9 +663,9 @@ func TestResourceByNameWithoutRequireObject(t *testing.T) {
b.ResourceTypeOrNameArgs(true, "pods", "foo").RequireObject(false)
err := b.Do().IntoSingular(&singular).Visit(test.Handle)
if err != nil || !singular || len(test.Infos) != 1 {
t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos)
err := b.Do().IntoSingleItemImplied(&singleItemImplied).Visit(test.Handle)
if err != nil || !singleItemImplied || len(test.Infos) != 1 {
t.Fatalf("unexpected response: %v %t %#v", err, singleItemImplied, test.Infos)
}
if test.Infos[0].Name != "foo" {
t.Errorf("unexpected name: %#v", test.Infos[0].Name)
@ -692,10 +692,10 @@ func TestResourceByNameAndEmptySelector(t *testing.T) {
SelectorParam("").
ResourceTypeOrNameArgs(true, "pods", "foo")
singular := false
infos, err := b.Do().IntoSingular(&singular).Infos()
if err != nil || !singular || len(infos) != 1 {
t.Fatalf("unexpected response: %v %t %#v", err, singular, infos)
singleItemImplied := false
infos, err := b.Do().IntoSingleItemImplied(&singleItemImplied).Infos()
if err != nil || !singleItemImplied || len(infos) != 1 {
t.Fatalf("unexpected response: %v %t %#v", err, singleItemImplied, infos)
}
if !reflect.DeepEqual(&pods.Items[0], infos[0].Object) {
t.Errorf("unexpected object: %#v", infos[0])
@ -722,7 +722,7 @@ func TestSelector(t *testing.T) {
Flatten()
test := &testVisitor{}
singular := false
singleItemImplied := false
if b.Do().Err() == nil {
t.Errorf("unexpected non-error")
@ -730,9 +730,9 @@ func TestSelector(t *testing.T) {
b.ResourceTypeOrNameArgs(true, "pods,service")
err := b.Do().IntoSingular(&singular).Visit(test.Handle)
if err != nil || singular || len(test.Infos) != 3 {
t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos)
err := b.Do().IntoSingleItemImplied(&singleItemImplied).Visit(test.Handle)
if err != nil || singleItemImplied || len(test.Infos) != 3 {
t.Fatalf("unexpected response: %v %t %#v", err, singleItemImplied, test.Infos)
}
if !api.Semantic.DeepDerivative([]runtime.Object{&pods.Items[0], &pods.Items[1], &svc.Items[0]}, test.Objects()) {
t.Errorf("unexpected visited objects: %#v", test.Objects())
@ -838,9 +838,9 @@ func TestResourceTuple(t *testing.T) {
continue
}
switch {
case (r.singular && len(testCase.args) != 1),
(!r.singular && len(testCase.args) == 1):
t.Errorf("%s: result had unexpected singular value", k)
case (r.singleItemImplied && len(testCase.args) != 1),
(!r.singleItemImplied && len(testCase.args) == 1):
t.Errorf("%s: result had unexpected singleItemImplied value", k)
}
info, err := r.Infos()
if err != nil {
@ -860,11 +860,11 @@ func TestStream(t *testing.T) {
NamespaceParam("test").Stream(r, "STDIN").Flatten()
test := &testVisitor{}
singular := false
singleItemImplied := false
err := b.Do().IntoSingular(&singular).Visit(test.Handle)
if err != nil || singular || len(test.Infos) != 3 {
t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos)
err := b.Do().IntoSingleItemImplied(&singleItemImplied).Visit(test.Handle)
if err != nil || singleItemImplied || len(test.Infos) != 3 {
t.Fatalf("unexpected response: %v %t %#v", err, singleItemImplied, test.Infos)
}
if !api.Semantic.DeepDerivative([]runtime.Object{&pods.Items[0], &pods.Items[1], &rc.Items[0]}, test.Objects()) {
t.Errorf("unexpected visited objects: %#v", test.Objects())
@ -877,11 +877,11 @@ func TestYAMLStream(t *testing.T) {
NamespaceParam("test").Stream(r, "STDIN").Flatten()
test := &testVisitor{}
singular := false
singleItemImplied := false
err := b.Do().IntoSingular(&singular).Visit(test.Handle)
if err != nil || singular || len(test.Infos) != 3 {
t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos)
err := b.Do().IntoSingleItemImplied(&singleItemImplied).Visit(test.Handle)
if err != nil || singleItemImplied || len(test.Infos) != 3 {
t.Fatalf("unexpected response: %v %t %#v", err, singleItemImplied, test.Infos)
}
if !api.Semantic.DeepDerivative([]runtime.Object{&pods.Items[0], &pods.Items[1], &rc.Items[0]}, test.Objects()) {
t.Errorf("unexpected visited objects: %#v", test.Objects())
@ -940,7 +940,7 @@ func TestContinueOnErrorVisitor(t *testing.T) {
}
}
func TestSingularObject(t *testing.T) {
func TestSingleItemImpliedObject(t *testing.T) {
obj, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
NamespaceParam("test").DefaultNamespace().
FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml"}}).
@ -960,7 +960,7 @@ func TestSingularObject(t *testing.T) {
}
}
func TestSingularObjectNoExtension(t *testing.T) {
func TestSingleItemImpliedObjectNoExtension(t *testing.T) {
obj, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
NamespaceParam("test").DefaultNamespace().
FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../examples/pod"}}).
@ -980,7 +980,7 @@ func TestSingularObjectNoExtension(t *testing.T) {
}
}
func TestSingularRootScopedObject(t *testing.T) {
func TestSingleItemImpliedRootScopedObject(t *testing.T) {
node := &api.Node{ObjectMeta: api.ObjectMeta{Name: "test"}, Spec: api.NodeSpec{ExternalID: "test"}}
r := streamTestObject(node)
infos, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()).
@ -1130,11 +1130,11 @@ func TestLatest(t *testing.T) {
NamespaceParam("other").Stream(r, "STDIN").Flatten().Latest()
test := &testVisitor{}
singular := false
singleItemImplied := false
err := b.Do().IntoSingular(&singular).Visit(test.Handle)
if err != nil || singular || len(test.Infos) != 3 {
t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos)
err := b.Do().IntoSingleItemImplied(&singleItemImplied).Visit(test.Handle)
if err != nil || singleItemImplied || len(test.Infos) != 3 {
t.Fatalf("unexpected response: %v %t %#v", err, singleItemImplied, test.Infos)
}
if !api.Semantic.DeepDerivative([]runtime.Object{newPod, newPod2, newSvc}, test.Objects()) {
t.Errorf("unexpected visited objects: %#v", test.Objects())
@ -1163,11 +1163,11 @@ func TestReceiveMultipleErrors(t *testing.T) {
ContinueOnError()
test := &testVisitor{}
singular := false
singleItemImplied := false
err := b.Do().IntoSingular(&singular).Visit(test.Handle)
if err == nil || singular || len(test.Infos) != 2 {
t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos)
err := b.Do().IntoSingleItemImplied(&singleItemImplied).Visit(test.Handle)
if err == nil || singleItemImplied || len(test.Infos) != 2 {
t.Fatalf("unexpected response: %v %t %#v", err, singleItemImplied, test.Infos)
}
errs, ok := err.(utilerrors.Aggregate)

View File

@ -40,8 +40,8 @@ type Result struct {
err error
visitor Visitor
sources []Visitor
singular bool
sources []Visitor
singleItemImplied bool
ignoreErrors []utilerrors.Matcher
@ -82,10 +82,10 @@ func (r *Result) Visit(fn VisitorFunc) error {
return utilerrors.FilterOut(err, r.ignoreErrors...)
}
// IntoSingular sets the provided boolean pointer to true if the Builder input
// reflected a single item, or multiple.
func (r *Result) IntoSingular(b *bool) *Result {
*b = r.singular
// IntoSingleItemImplied sets the provided boolean pointer to true if the Builder input
// implies a single item, or multiple.
func (r *Result) IntoSingleItemImplied(b *bool) *Result {
*b = r.singleItemImplied
return r
}
@ -136,7 +136,7 @@ func (r *Result) Object() (runtime.Object, error) {
}
if len(objects) == 1 {
if r.singular {
if r.singleItemImplied {
return objects[0], nil
}
// if the item is a list already, don't create another list