mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	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:
		@@ -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() {
 | 
			
		||||
 
 | 
			
		||||
@@ -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")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -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.
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user