github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/command/var_get_test.go (about)

     1  package command
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"testing"
     7  
     8  	"github.com/hashicorp/nomad/api"
     9  	"github.com/hashicorp/nomad/ci"
    10  	"github.com/mitchellh/cli"
    11  	"github.com/posener/complete"
    12  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  func TestVarGetCommand_Implements(t *testing.T) {
    16  	ci.Parallel(t)
    17  	var _ cli.Command = &VarGetCommand{}
    18  }
    19  
    20  func TestVarGetCommand_Fails(t *testing.T) {
    21  	ci.Parallel(t)
    22  	t.Run("bad_args", func(t *testing.T) {
    23  		ci.Parallel(t)
    24  		ui := cli.NewMockUi()
    25  		cmd := &VarGetCommand{Meta: Meta{Ui: ui}}
    26  		code := cmd.Run([]string{"some", "bad", "args"})
    27  		out := ui.ErrorWriter.String()
    28  		require.Equal(t, 1, code, "expected exit code 1, got: %d")
    29  		require.Contains(t, out, commandErrorText(cmd), "expected help output, got: %s", out)
    30  	})
    31  	t.Run("bad_address", func(t *testing.T) {
    32  		ci.Parallel(t)
    33  		ui := cli.NewMockUi()
    34  		cmd := &VarGetCommand{Meta: Meta{Ui: ui}}
    35  		code := cmd.Run([]string{"-address=nope", "foo"})
    36  		out := ui.ErrorWriter.String()
    37  		require.Equal(t, 1, code, "expected exit code 1, got: %d")
    38  		require.Contains(t, ui.ErrorWriter.String(), "retrieving variable", "connection error, got: %s", out)
    39  		require.Zero(t, ui.OutputWriter.String())
    40  	})
    41  	t.Run("missing_template", func(t *testing.T) {
    42  		ci.Parallel(t)
    43  		ui := cli.NewMockUi()
    44  		cmd := &VarGetCommand{Meta: Meta{Ui: ui}}
    45  		code := cmd.Run([]string{`-out=go-template`, "foo"})
    46  		out := strings.TrimSpace(ui.ErrorWriter.String())
    47  		require.Equal(t, 1, code, "expected exit code 1, got: %d", code)
    48  		require.Equal(t, errMissingTemplate+"\n"+commandErrorText(cmd), out)
    49  		require.Zero(t, ui.OutputWriter.String())
    50  	})
    51  	t.Run("unexpected_template", func(t *testing.T) {
    52  		ci.Parallel(t)
    53  		ui := cli.NewMockUi()
    54  		cmd := &VarGetCommand{Meta: Meta{Ui: ui}}
    55  		code := cmd.Run([]string{`-out=json`, `-template="bad"`, "foo"})
    56  		out := strings.TrimSpace(ui.ErrorWriter.String())
    57  		require.Equal(t, 1, code, "expected exit code 1, got: %d", code)
    58  		require.Equal(t, errUnexpectedTemplate+"\n"+commandErrorText(cmd), out)
    59  		require.Zero(t, ui.OutputWriter.String())
    60  	})
    61  }
    62  
    63  func TestVarGetCommand(t *testing.T) {
    64  	ci.Parallel(t)
    65  
    66  	// Create a server
    67  	srv, client, url := testServer(t, true, nil)
    68  	t.Cleanup(func() {
    69  		srv.Shutdown()
    70  	})
    71  
    72  	testCases := []struct {
    73  		name     string
    74  		format   string
    75  		template string
    76  		expected string
    77  		testPath string // defaulted to "test/var" in code; used for not-found
    78  		exitCode int
    79  		isError  bool
    80  	}{
    81  		{
    82  			name:   "json",
    83  			format: "json",
    84  		},
    85  		{
    86  			name:   "table",
    87  			format: "table",
    88  		},
    89  		{
    90  			name:     "go-template",
    91  			format:   "go-template",
    92  			template: `{{.Namespace}}.{{.Path}}`,
    93  			expected: "TestVarGetCommand-2-go-template.test/var",
    94  		},
    95  		{
    96  			name:     "not-found",
    97  			format:   "json",
    98  			expected: errVariableNotFound,
    99  			testPath: "not-found",
   100  			isError:  true,
   101  			exitCode: 1,
   102  		},
   103  	}
   104  	for i, tc := range testCases {
   105  		t.Run(fmt.Sprintf("%v_%s", i, tc.name), func(t *testing.T) {
   106  			tc := tc
   107  			ci.Parallel(t)
   108  			var err error
   109  			// Create a namespace for the test case
   110  			testNS := strings.Map(validNS, t.Name())
   111  			_, err = client.Namespaces().Register(&api.Namespace{Name: testNS}, nil)
   112  			require.NoError(t, err)
   113  			t.Cleanup(func() {
   114  				client.Namespaces().Delete(testNS, nil)
   115  			})
   116  
   117  			// Create a var to get
   118  			sv := testVariable()
   119  			sv.Namespace = testNS
   120  			sv, _, err = client.Variables().Create(sv, nil)
   121  			require.NoError(t, err)
   122  			t.Cleanup(func() {
   123  				_, _ = client.Variables().Delete(sv.Path, nil)
   124  			})
   125  
   126  			// Build and run the command
   127  			ui := cli.NewMockUi()
   128  			cmd := &VarGetCommand{Meta: Meta{Ui: ui}}
   129  			args := []string{
   130  				"-address=" + url,
   131  				"-namespace=" + testNS,
   132  				"-out=" + tc.format,
   133  			}
   134  			if tc.template != "" {
   135  				args = append(args, "-template="+tc.template)
   136  			}
   137  			args = append(args, sv.Path)
   138  			if tc.testPath != "" {
   139  				// replace path with test case override
   140  				args[len(args)-1] = tc.testPath
   141  			}
   142  			code := cmd.Run(args)
   143  
   144  			// Check the output
   145  			require.Equal(t, tc.exitCode, code, "expected exit %v, got: %d; %v", tc.exitCode, code, ui.ErrorWriter.String())
   146  			if tc.isError {
   147  				require.Equal(t, tc.expected, strings.TrimSpace(ui.ErrorWriter.String()))
   148  				return
   149  			}
   150  			switch tc.format {
   151  			case "json":
   152  				require.Equal(t, sv.AsPrettyJSON(), strings.TrimSpace(ui.OutputWriter.String()))
   153  			case "table":
   154  				out := ui.OutputWriter.String()
   155  				outs := strings.Split(out, "\n")
   156  				require.Len(t, outs, 9)
   157  				require.Equal(t, "Namespace   = "+testNS, outs[0])
   158  				require.Equal(t, "Path        = test/var", outs[1])
   159  			case "go-template":
   160  				require.Equal(t, tc.expected, strings.TrimSpace(ui.OutputWriter.String()))
   161  			default:
   162  				t.Fatalf("invalid format: %q", tc.format)
   163  			}
   164  		})
   165  	}
   166  	t.Run("Autocomplete", func(t *testing.T) {
   167  		ci.Parallel(t)
   168  		_, client, url, shutdownFn := testAPIClient(t)
   169  		defer shutdownFn()
   170  
   171  		ui := cli.NewMockUi()
   172  		cmd := &VarGetCommand{Meta: Meta{Ui: ui, flagAddress: url}}
   173  
   174  		// Create a var
   175  		testNS := strings.Map(validNS, t.Name())
   176  		_, err := client.Namespaces().Register(&api.Namespace{Name: testNS}, nil)
   177  		require.NoError(t, err)
   178  		t.Cleanup(func() { client.Namespaces().Delete(testNS, nil) })
   179  
   180  		sv := testVariable()
   181  		sv.Path = "special/variable"
   182  		sv.Namespace = testNS
   183  		sv, _, err = client.Variables().Create(sv, nil)
   184  		require.NoError(t, err)
   185  		t.Cleanup(func() { client.Variables().Delete(sv.Path, nil) })
   186  
   187  		args := complete.Args{Last: "s"}
   188  		predictor := cmd.AutocompleteArgs()
   189  
   190  		res := predictor.Predict(args)
   191  		require.Equal(t, 1, len(res))
   192  		require.Equal(t, sv.Path, res[0])
   193  	})
   194  }
   195  
   196  func validNS(r rune) rune {
   197  	if r == '/' || r == '_' {
   198  		return '-'
   199  	}
   200  	return r
   201  }