From 1592bf5b0cda208d0e60697a9a4a855a2f987ae4 Mon Sep 17 00:00:00 2001 From: Charlie Voiselle Date: Wed, 29 Nov 2017 19:40:08 -0500 Subject: [PATCH] Handle exact namespace match properly when also matched as prefix This fixes an issue with the nomad namespace inspect and nomad namespace status commands failing to run for namespaces whose names are the start of another namespace's name: for example, foo and foobar. If the argument matches the first possibility returned by prefix exactly, that namespace will be targetted. If no exact match occurs, the behavior is unchanged. --- command/namespace_inspect_test.go | 42 +++++++++++++++++++++++++++++++ command/namespace_status.go | 5 ++++ command/namespace_status_test.go | 42 +++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) diff --git a/command/namespace_inspect_test.go b/command/namespace_inspect_test.go index f39b9cdd1..20a0ef26b 100644 --- a/command/namespace_inspect_test.go +++ b/command/namespace_inspect_test.go @@ -92,3 +92,45 @@ func TestNamespaceInspectCommand_AutocompleteArgs(t *testing.T) { assert.Equal(1, len(res)) assert.Equal(ns.Name, res[0]) } + +// This test should demonstrate the behavior of a namespace +// and prefix collision. In that case, the Namespace status +// command should pull the matching namespace rather than +// displaying the multiple match error +func TestNamespaceInspectCommand_NamespaceMatchesPrefix(t *testing.T) { + t.Parallel() + + // Create a server + srv, client, url := testServer(t, true, nil) + defer srv.Shutdown() + + ui := new(cli.MockUi) + cmd := &NamespaceInspectCommand{Meta: Meta{Ui: ui}} + + // Create a namespace that uses foo as a prefix + ns := &api.Namespace{Name: "fooBar"} + _, err := client.Namespaces().Register(ns, nil) + assert.Nil(t, err) + + // Create a foo namespace + ns2 := &api.Namespace{Name: "foo"} + _, err = client.Namespaces().Register(ns2, nil) + assert.Nil(t, err) + + // Adding a NS after to prevent sort from creating + // false successes + ns = &api.Namespace{Name: "fooBaz"} + _, err = client.Namespaces().Register(ns, nil) + assert.Nil(t, err) + + // Check status on namespace + code := cmd.Run([]string{"-address=" + url, ns2.Name}) + if code != 0 { + t.Fatalf("expected exit 0, got: %d; %v", code, ui.ErrorWriter.String()) + } + // Check to ensure we got the proper foo + out := ui.OutputWriter.String() + if !strings.Contains(out, "= foo\n") { + t.Fatalf("expected namespace foo, got: %s", out) + } +} diff --git a/command/namespace_status.go b/command/namespace_status.go index 866481d84..e2979f1e6 100644 --- a/command/namespace_status.go +++ b/command/namespace_status.go @@ -128,6 +128,11 @@ func getNamespace(client *api.Namespaces, ns string) (match *api.Namespace, poss case l == 1: return namespaces[0], nil, nil default: + // search for an exact match in the returned namespaces + for _, namespace := range namespaces { + if namespace.Name == ns { return namespace, nil, nil } + } + // if not found, return the fuzzy matches. return nil, namespaces, nil } } diff --git a/command/namespace_status_test.go b/command/namespace_status_test.go index d9e85bd09..1d188337d 100644 --- a/command/namespace_status_test.go +++ b/command/namespace_status_test.go @@ -133,3 +133,45 @@ func TestNamespaceStatusCommand_AutocompleteArgs(t *testing.T) { assert.Equal(1, len(res)) assert.Equal(ns.Name, res[0]) } + +// This test should demonstrate the behavior of a namespace +// and prefix collision. In that case, the Namespace status +// command should pull the matching namespace rather than +// displaying the multiple match error +func TestNamespaceStatusCommand_NamespaceMatchesPrefix(t *testing.T) { + t.Parallel() + + // Create a server + srv, client, url := testServer(t, true, nil) + defer srv.Shutdown() + + ui := new(cli.MockUi) + cmd := &NamespaceStatusCommand{Meta: Meta{Ui: ui}} + + // Create a namespace that uses foo as a prefix + ns := &api.Namespace{Name: "fooBar"} + _, err := client.Namespaces().Register(ns, nil) + assert.Nil(t, err) + + // Create a foo namespace + ns2 := &api.Namespace{Name: "foo"} + _, err = client.Namespaces().Register(ns2, nil) + assert.Nil(t, err) + + // Adding a NS after to prevent sort from creating + // false successes + ns = &api.Namespace{Name: "fooBaz"} + _, err = client.Namespaces().Register(ns, nil) + assert.Nil(t, err) + + // Check status on namespace + code := cmd.Run([]string{"-address=" + url, ns2.Name}) + if code != 0 { + t.Fatalf("expected exit 0, got: %d; %v", code, ui.ErrorWriter.String()) + } + // Check to ensure we got the proper foo + out := ui.OutputWriter.String() + if !strings.Contains(out, "= foo\n") { + t.Fatalf("expected namespace foo, got: %s", out) + } +}