Files
nomad/command/var_lock_test.go
Juana De La Cuesta 72acaf6623 [17449] Introduces a locking mechanism over variables (#18207)
It includes the work over the state store, the PRC server, the HTTP server, the go API package and the CLI's  command. To read more on the actuall functionality, refer to the RFCs [NMD-178] Locking with Nomad Variables and [NMD-179] Leader election using locking mechanism for the Autoscaler.
2023-09-21 17:56:33 +02:00

153 lines
3.7 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package command
import (
"fmt"
"os"
"testing"
"time"
"github.com/hashicorp/nomad/ci"
"github.com/mitchellh/cli"
"github.com/shoenig/test/must"
"github.com/stretchr/testify/require"
)
func TestVarLockCommand_Implements(t *testing.T) {
ci.Parallel(t)
var _ cli.Command = &VarLockCommand{}
}
func TestVarLockCommand_Fails(t *testing.T) {
ci.Parallel(t)
t.Run("bad_args", func(t *testing.T) {
ci.Parallel(t)
ui := cli.NewMockUi()
cmd := &VarLockCommand{
varPutCommand: &VarPutCommand{Meta: Meta{Ui: ui}},
}
code := cmd.Run([]string{"-bad-flag"})
out := ui.ErrorWriter.String()
must.One(t, code)
must.StrContains(t, out, commandErrorText(cmd))
})
t.Run("bad_address", func(t *testing.T) {
ci.Parallel(t)
ui := cli.NewMockUi()
cmd := &VarLockCommand{
varPutCommand: &VarPutCommand{Meta: Meta{Ui: ui}},
}
code := cmd.Run([]string{"-address=nope", "foo", "-"})
out := ui.ErrorWriter.String()
must.One(t, code)
must.StrContains(t, out, "unsupported protocol scheme")
})
t.Run("missing_args", func(t *testing.T) {
ci.Parallel(t)
ui := cli.NewMockUi()
cmd := &VarLockCommand{
varPutCommand: &VarPutCommand{Meta: Meta{Ui: ui}},
}
code := cmd.Run([]string{"foo"})
out := ui.ErrorWriter.String()
must.One(t, code)
must.StrContains(t, out, "Not enough arguments (expected >2, got 1)")
})
t.Run("invalid_TTL", func(t *testing.T) {
ci.Parallel(t)
ui := cli.NewMockUi()
cmd := &VarLockCommand{
varPutCommand: &VarPutCommand{Meta: Meta{Ui: ui}},
}
code := cmd.Run([]string{"-ttl=2", "bar", "foo"})
out := ui.ErrorWriter.String()
must.One(t, code)
must.StrContains(t, out, "Invalid TTL: time")
})
t.Run("invalid_lock_delay", func(t *testing.T) {
ci.Parallel(t)
ui := cli.NewMockUi()
cmd := &VarLockCommand{
varPutCommand: &VarPutCommand{Meta: Meta{Ui: ui}},
}
code := cmd.Run([]string{"-delay=2", "bar", "foo"})
out := ui.ErrorWriter.String()
must.One(t, code)
must.StrContains(t, out, "Invalid Lock Delay: time")
})
}
func TestVarLockCommand_Good(t *testing.T) {
ci.Parallel(t)
// Create a server
srv, client, url := testServer(t, true, nil)
defer srv.Shutdown()
ui := cli.NewMockUi()
cmd := &VarLockCommand{
varPutCommand: &VarPutCommand{Meta: Meta{Ui: ui}},
}
filePath := fmt.Sprintf("%v.txt", time.Now().Unix())
// Get the variable
code := cmd.Run([]string{"-address=" + url, "test/var/shell", "touch ", filePath})
require.Equal(t, 0, code, "expected exit 0, got: %d; %v", code, ui.ErrorWriter.String())
sv, _, err := srv.Client().Variables().Peek("test/var/shell", nil)
must.NoError(t, err)
must.NotNil(t, sv)
must.Eq(t, "test/var/shell", sv.Path)
// Check for the file
_, err = os.ReadFile(filePath)
must.NoError(t, err)
t.Cleanup(func() {
os.Remove(filePath)
_, _ = client.Variables().Delete("test/var/shell", nil)
})
}
func TestVarLockCommand_Good_NoShell(t *testing.T) {
ci.Parallel(t)
// Create a server
srv, client, url := testServer(t, true, nil)
defer srv.Shutdown()
ui := cli.NewMockUi()
cmd := &VarLockCommand{
varPutCommand: &VarPutCommand{Meta: Meta{Ui: ui}},
}
filePath := fmt.Sprintf("%v.txt", time.Now().Unix())
// Get the variable
code := cmd.Run([]string{"-address=" + url, "-shell=false", "test/var/noShell", "touch", filePath})
require.Zero(t, 0, code)
sv, _, err := srv.Client().Variables().Peek("test/var/noShell", nil)
must.NoError(t, err)
must.NotNil(t, sv)
must.Eq(t, "test/var/noShell", sv.Path)
// Check for the file
_, err = os.ReadFile(filePath)
must.NoError(t, err)
t.Cleanup(func() {
os.Remove(filePath)
_, _ = client.Variables().Delete("test/var/noShell", nil)
})
}