github.com/hernad/nomad@v1.6.112/command/var_get_test.go (about)

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