Merge pull request #14172 from hashicorp/cleanup-command-tests-wait-for-node

cleanup: first pass at fixing command package warnings
This commit is contained in:
Seth Hoenig
2022-08-18 08:04:27 -05:00
committed by GitHub
19 changed files with 205 additions and 295 deletions

View File

@@ -1,7 +1,6 @@
package command
import (
"io/ioutil"
"os"
"testing"
@@ -9,13 +8,11 @@ import (
"github.com/hashicorp/nomad/command/agent"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/mitchellh/cli"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/shoenig/test/must"
)
func TestACLBootstrapCommand(t *testing.T) {
ci.Parallel(t)
assert := assert.New(t)
// create a acl-enabled server without bootstrapping the token
config := func(c *agent.Config) {
@@ -24,61 +21,59 @@ func TestACLBootstrapCommand(t *testing.T) {
}
srv, _, url := testServer(t, true, config)
defer srv.Shutdown()
defer stopTestAgent(srv)
assert.Nil(srv.RootToken)
must.Nil(t, srv.RootToken)
ui := cli.NewMockUi()
cmd := &ACLBootstrapCommand{Meta: Meta{Ui: ui, flagAddress: url}}
code := cmd.Run([]string{"-address=" + url})
assert.Equal(0, code)
must.Zero(t, code)
out := ui.OutputWriter.String()
assert.Contains(out, "Secret ID")
must.StrContains(t, out, "Secret ID")
}
// If a bootstrap token has already been created, attempts to create more should
// fail.
func TestACLBootstrapCommand_ExistingBootstrapToken(t *testing.T) {
ci.Parallel(t)
assert := assert.New(t)
config := func(c *agent.Config) {
c.ACL.Enabled = true
}
srv, _, url := testServer(t, true, config)
defer srv.Shutdown()
defer stopTestAgent(srv)
assert.NotNil(srv.RootToken)
must.NotNil(t, srv.RootToken)
ui := cli.NewMockUi()
cmd := &ACLBootstrapCommand{Meta: Meta{Ui: ui, flagAddress: url}}
code := cmd.Run([]string{"-address=" + url})
assert.Equal(1, code)
must.One(t, code)
out := ui.OutputWriter.String()
assert.NotContains(out, "Secret ID")
must.StrNotContains(t, out, "Secret ID")
}
// Attempting to bootstrap a token on a non-ACL enabled server should fail.
func TestACLBootstrapCommand_NonACLServer(t *testing.T) {
ci.Parallel(t)
assert := assert.New(t)
srv, _, url := testServer(t, true, nil)
defer srv.Shutdown()
defer stopTestAgent(srv)
ui := cli.NewMockUi()
cmd := &ACLBootstrapCommand{Meta: Meta{Ui: ui, flagAddress: url}}
code := cmd.Run([]string{"-address=" + url})
assert.Equal(1, code)
must.One(t, code)
out := ui.OutputWriter.String()
assert.NotContains(out, "Secret ID")
must.StrNotContains(t, out, "Secret ID")
}
// Attempting to bootstrap the server with an operator provided token in a file should
@@ -95,27 +90,26 @@ func TestACLBootstrapCommand_WithOperatorFileBootstrapToken(t *testing.T) {
mockToken := mock.ACLToken()
// Create temp file
f, err := ioutil.TempFile("", "nomad-token.token")
assert.Nil(t, err)
defer os.Remove(f.Name())
file, rm := getTempFile(t, "nomad-token.token")
t.Cleanup(rm)
// Write the token to the file
err = ioutil.WriteFile(f.Name(), []byte(mockToken.SecretID), 0700)
assert.Nil(t, err)
err := os.WriteFile(file, []byte(mockToken.SecretID), 0700)
must.NoError(t, err)
srv, _, url := testServer(t, true, config)
defer srv.Shutdown()
defer stopTestAgent(srv)
require.Nil(t, srv.RootToken)
must.Nil(t, srv.RootToken)
ui := cli.NewMockUi()
cmd := &ACLBootstrapCommand{Meta: Meta{Ui: ui, flagAddress: url}}
code := cmd.Run([]string{"-address=" + url, f.Name()})
assert.Equal(t, 0, code)
code := cmd.Run([]string{"-address=" + url, file})
must.Zero(t, code)
out := ui.OutputWriter.String()
assert.Contains(t, out, mockToken.SecretID)
must.StrContains(t, out, mockToken.SecretID)
}
// Attempting to bootstrap the server with an invalid operator provided token in a file should
@@ -133,25 +127,24 @@ func TestACLBootstrapCommand_WithBadOperatorFileBootstrapToken(t *testing.T) {
invalidToken := "invalid-token"
// Create temp file
f, err := ioutil.TempFile("", "nomad-token.token")
assert.Nil(t, err)
defer os.Remove(f.Name())
file, cleanup := getTempFile(t, "nomad-token.token")
t.Cleanup(cleanup)
// Write the token to the file
err = ioutil.WriteFile(f.Name(), []byte(invalidToken), 0700)
assert.Nil(t, err)
err := os.WriteFile(file, []byte(invalidToken), 0700)
must.NoError(t, err)
srv, _, url := testServer(t, true, config)
defer srv.Shutdown()
defer stopTestAgent(srv)
assert.Nil(t, srv.RootToken)
must.Nil(t, srv.RootToken)
ui := cli.NewMockUi()
cmd := &ACLBootstrapCommand{Meta: Meta{Ui: ui, flagAddress: url}}
code := cmd.Run([]string{"-address=" + url, f.Name()})
assert.Equal(t, 1, code)
code := cmd.Run([]string{"-address=" + url, file})
must.One(t, code)
out := ui.OutputWriter.String()
assert.NotContains(t, out, invalidToken)
must.StrNotContains(t, out, invalidToken)
}

View File

@@ -1,31 +1,29 @@
package command
import (
"io/ioutil"
"os"
"strings"
"testing"
"github.com/hashicorp/nomad/ci"
"github.com/hashicorp/nomad/command/agent"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/mitchellh/cli"
"github.com/stretchr/testify/assert"
"github.com/shoenig/test/must"
)
func TestACLPolicyApplyCommand(t *testing.T) {
ci.Parallel(t)
assert := assert.New(t)
config := func(c *agent.Config) {
c.ACL.Enabled = true
}
srv, _, url := testServer(t, true, config)
defer srv.Shutdown()
defer stopTestAgent(srv)
// Bootstrap an initial ACL token
token := srv.RootToken
assert.NotNil(token, "failed to bootstrap ACL token")
must.NotNil(t, token)
ui := cli.NewMockUi()
cmd := &ACLPolicyApplyCommand{Meta: Meta{Ui: ui, flagAddress: url}}
@@ -34,25 +32,22 @@ func TestACLPolicyApplyCommand(t *testing.T) {
policy := mock.ACLPolicy()
// Get a file
f, err := ioutil.TempFile("", "nomad-test")
assert.Nil(err)
defer os.Remove(f.Name())
file, rm := getTempFile(t, "nomad-test")
t.Cleanup(rm)
// Write the policy to the file
err = ioutil.WriteFile(f.Name(), []byte(policy.Rules), 0700)
assert.Nil(err)
err := os.WriteFile(file, []byte(policy.Rules), 0700)
must.NoError(t, err)
// Attempt to apply a policy without a valid management token
code := cmd.Run([]string{"-address=" + url, "-token=foo", "test-policy", f.Name()})
assert.Equal(1, code)
code := cmd.Run([]string{"-address=" + url, "-token=foo", "test-policy", file})
must.One(t, code)
// Apply a policy with a valid management token
code = cmd.Run([]string{"-address=" + url, "-token=" + token.SecretID, "test-policy", f.Name()})
assert.Equal(0, code)
code = cmd.Run([]string{"-address=" + url, "-token=" + token.SecretID, "test-policy", file})
must.Zero(t, code)
// Check the output
out := ui.OutputWriter.String()
if !strings.Contains(out, "Successfully wrote") {
t.Fatalf("bad: %v", out)
}
must.StrContains(t, out, "Successfully wrote")
}

View File

@@ -2,7 +2,6 @@ package command
import (
"fmt"
"strings"
"testing"
"github.com/hashicorp/nomad/acl"
@@ -11,23 +10,23 @@ import (
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/mitchellh/cli"
"github.com/stretchr/testify/assert"
"github.com/shoenig/test/must"
)
func TestACLPolicyDeleteCommand(t *testing.T) {
ci.Parallel(t)
assert := assert.New(t)
config := func(c *agent.Config) {
c.ACL.Enabled = true
}
srv, _, url := testServer(t, true, config)
defer stopTestAgent(srv)
state := srv.Agent.Server().State()
defer srv.Shutdown()
// Bootstrap an initial ACL token
token := srv.RootToken
assert.NotNil(token, "failed to bootstrap ACL token")
must.NotNil(t, token)
// Create a test ACLPolicy
policy := &structs.ACLPolicy{
@@ -35,7 +34,7 @@ func TestACLPolicyDeleteCommand(t *testing.T) {
Rules: acl.PolicyWrite,
}
policy.SetHash()
assert.Nil(state.UpsertACLPolicies(structs.MsgTypeTestSetup, 1000, []*structs.ACLPolicy{policy}))
must.NoError(t, state.UpsertACLPolicies(structs.MsgTypeTestSetup, 1000, []*structs.ACLPolicy{policy}))
ui := cli.NewMockUi()
cmd := &ACLPolicyDeleteCommand{Meta: Meta{Ui: ui, flagAddress: url}}
@@ -43,15 +42,13 @@ func TestACLPolicyDeleteCommand(t *testing.T) {
// Delete the policy without a valid token fails
invalidToken := mock.ACLToken()
code := cmd.Run([]string{"-address=" + url, "-token=" + invalidToken.SecretID, policy.Name})
assert.Equal(1, code)
must.One(t, code)
// Delete the policy with a valid management token
code = cmd.Run([]string{"-address=" + url, "-token=" + token.SecretID, policy.Name})
assert.Equal(0, code)
must.Zero(t, code)
// Check the output
out := ui.OutputWriter.String()
if !strings.Contains(out, fmt.Sprintf("Successfully deleted %s policy", policy.Name)) {
t.Fatalf("bad: %v", out)
}
must.StrContains(t, out, fmt.Sprintf("Successfully deleted %s policy", policy.Name))
}

View File

@@ -1,7 +1,6 @@
package command
import (
"strings"
"testing"
"github.com/hashicorp/nomad/ci"
@@ -9,23 +8,23 @@ import (
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/mitchellh/cli"
"github.com/stretchr/testify/assert"
"github.com/shoenig/test/must"
)
func TestACLPolicyInfoCommand(t *testing.T) {
ci.Parallel(t)
assert := assert.New(t)
config := func(c *agent.Config) {
c.ACL.Enabled = true
}
srv, _, url := testServer(t, true, config)
state := srv.Agent.Server().State()
defer srv.Shutdown()
defer stopTestAgent(srv)
// Bootstrap an initial ACL token
token := srv.RootToken
assert.NotNil(token, "failed to bootstrap ACL token")
must.NotNil(t, token)
// Create a test ACLPolicy
policy := &structs.ACLPolicy{
@@ -33,7 +32,7 @@ func TestACLPolicyInfoCommand(t *testing.T) {
Rules: "node { policy = \"read\" }",
}
policy.SetHash()
assert.Nil(state.UpsertACLPolicies(structs.MsgTypeTestSetup, 1000, []*structs.ACLPolicy{policy}))
must.NoError(t, state.UpsertACLPolicies(structs.MsgTypeTestSetup, 1000, []*structs.ACLPolicy{policy}))
ui := cli.NewMockUi()
cmd := &ACLPolicyInfoCommand{Meta: Meta{Ui: ui, flagAddress: url}}
@@ -41,15 +40,13 @@ func TestACLPolicyInfoCommand(t *testing.T) {
// Attempt to apply a policy without a valid management token
invalidToken := mock.ACLToken()
code := cmd.Run([]string{"-address=" + url, "-token=" + invalidToken.SecretID, policy.Name})
assert.Equal(1, code)
must.One(t, code)
// Apply a policy with a valid management token
code = cmd.Run([]string{"-address=" + url, "-token=" + token.SecretID, policy.Name})
assert.Equal(0, code)
must.Zero(t, code)
// Check the output
out := ui.OutputWriter.String()
if !strings.Contains(out, policy.Name) {
t.Fatalf("bad: %v", out)
}
must.StrContains(t, out, policy.Name)
}

View File

@@ -1,7 +1,6 @@
package command
import (
"strings"
"testing"
"github.com/hashicorp/nomad/acl"
@@ -10,23 +9,23 @@ import (
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/mitchellh/cli"
"github.com/stretchr/testify/assert"
"github.com/shoenig/test/must"
)
func TestACLPolicyListCommand(t *testing.T) {
ci.Parallel(t)
assert := assert.New(t)
config := func(c *agent.Config) {
c.ACL.Enabled = true
}
srv, _, url := testServer(t, true, config)
state := srv.Agent.Server().State()
defer srv.Shutdown()
defer stopTestAgent(srv)
// Bootstrap an initial ACL token
token := srv.RootToken
assert.NotNil(token, "failed to bootstrap ACL token")
must.NotNil(t, token)
// Create a test ACLPolicy
policy := &structs.ACLPolicy{
@@ -34,7 +33,7 @@ func TestACLPolicyListCommand(t *testing.T) {
Rules: acl.PolicyWrite,
}
policy.SetHash()
assert.Nil(state.UpsertACLPolicies(structs.MsgTypeTestSetup, 1000, []*structs.ACLPolicy{policy}))
must.NoError(t, state.UpsertACLPolicies(structs.MsgTypeTestSetup, 1000, []*structs.ACLPolicy{policy}))
ui := cli.NewMockUi()
cmd := &ACLPolicyListCommand{Meta: Meta{Ui: ui, flagAddress: url}}
@@ -42,25 +41,20 @@ func TestACLPolicyListCommand(t *testing.T) {
// Attempt to list policies without a valid management token
invalidToken := mock.ACLToken()
code := cmd.Run([]string{"-address=" + url, "-token=" + invalidToken.SecretID})
assert.Equal(1, code)
must.One(t, code)
// Apply a policy with a valid management token
code = cmd.Run([]string{"-address=" + url, "-token=" + token.SecretID})
assert.Equal(0, code)
must.Zero(t, code)
// Check the output
out := ui.OutputWriter.String()
if !strings.Contains(out, policy.Name) {
t.Fatalf("bad: %v", out)
}
must.StrContains(t, out, policy.Name)
// List json
if code := cmd.Run([]string{"-address=" + url, "-token=" + token.SecretID, "-json"}); code != 0 {
t.Fatalf("expected exit 0, got: %d; %v", code, ui.ErrorWriter.String())
}
must.Zero(t, cmd.Run([]string{"-address=" + url, "-token=" + token.SecretID, "-json"}))
out = ui.OutputWriter.String()
if !strings.Contains(out, "CreateIndex") {
t.Fatalf("expected json output, got: %s", out)
}
must.StrContains(t, out, "CreateIndex")
ui.OutputWriter.Reset()
}

View File

@@ -1,43 +1,40 @@
package command
import (
"strings"
"testing"
"github.com/hashicorp/nomad/ci"
"github.com/hashicorp/nomad/command/agent"
"github.com/mitchellh/cli"
"github.com/stretchr/testify/assert"
"github.com/shoenig/test/must"
)
func TestACLTokenCreateCommand(t *testing.T) {
ci.Parallel(t)
assert := assert.New(t)
config := func(c *agent.Config) {
c.ACL.Enabled = true
}
srv, _, url := testServer(t, true, config)
defer srv.Shutdown()
defer stopTestAgent(srv)
// Bootstrap an initial ACL token
token := srv.RootToken
assert.NotNil(token, "failed to bootstrap ACL token")
must.NotNil(t, token)
ui := cli.NewMockUi()
cmd := &ACLTokenCreateCommand{Meta: Meta{Ui: ui, flagAddress: url}}
// Request to create a new token without providing a valid management token
code := cmd.Run([]string{"-address=" + url, "-token=foo", "-policy=foo", "-type=client"})
assert.Equal(1, code)
must.One(t, code)
// Request to create a new token with a valid management token
code = cmd.Run([]string{"-address=" + url, "-token=" + token.SecretID, "-policy=foo", "-type=client"})
assert.Equal(0, code)
must.Zero(t, code)
// Check the output
out := ui.OutputWriter.String()
if !strings.Contains(out, "[foo]") {
t.Fatalf("bad: %v", out)
}
must.StrContains(t, out, "[foo]")
}

View File

@@ -2,7 +2,6 @@ package command
import (
"fmt"
"strings"
"testing"
"github.com/hashicorp/nomad/acl"
@@ -11,22 +10,22 @@ import (
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/mitchellh/cli"
"github.com/stretchr/testify/assert"
"github.com/shoenig/test/must"
)
func TestACLTokenDeleteCommand_ViaEnvVariable(t *testing.T) {
ci.Parallel(t)
assert := assert.New(t)
config := func(c *agent.Config) {
c.ACL.Enabled = true
}
srv, _, url := testServer(t, true, config)
defer srv.Shutdown()
defer stopTestAgent(srv)
// Bootstrap an initial ACL token
token := srv.RootToken
assert.NotNil(token, "failed to bootstrap ACL token")
must.NotNil(t, token)
ui := cli.NewMockUi()
cmd := &ACLTokenDeleteCommand{Meta: Meta{Ui: ui, flagAddress: url}}
@@ -36,21 +35,19 @@ func TestACLTokenDeleteCommand_ViaEnvVariable(t *testing.T) {
mockToken := mock.ACLToken()
mockToken.Policies = []string{acl.PolicyWrite}
mockToken.SetHash()
assert.Nil(state.UpsertACLTokens(structs.MsgTypeTestSetup, 1000, []*structs.ACLToken{mockToken}))
must.NoError(t, state.UpsertACLTokens(structs.MsgTypeTestSetup, 1000, []*structs.ACLToken{mockToken}))
// Attempt to delete a token without providing a valid token with delete
// permissions
code := cmd.Run([]string{"-address=" + url, "-token=foo", mockToken.AccessorID})
assert.Equal(1, code)
must.One(t, code)
// Delete a token using a valid management token set via an environment
// variable
code = cmd.Run([]string{"-address=" + url, "-token=" + token.SecretID, mockToken.AccessorID})
assert.Equal(0, code)
must.Zero(t, code)
// Check the output
out := ui.OutputWriter.String()
if !strings.Contains(out, fmt.Sprintf("Token %s successfully deleted", mockToken.AccessorID)) {
t.Fatalf("bad: %v", out)
}
must.StrContains(t, out, fmt.Sprintf("Token %s successfully deleted", mockToken.AccessorID))
}

View File

@@ -1,35 +1,29 @@
package command
import (
"os"
"strings"
"testing"
"github.com/hashicorp/nomad/acl"
"github.com/hashicorp/nomad/ci"
"github.com/hashicorp/nomad/command/agent"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/mitchellh/cli"
"github.com/stretchr/testify/assert"
"github.com/shoenig/test/must"
)
func TestACLTokenInfoCommand_ViaEnvVar(t *testing.T) {
ci.Parallel(t)
defer os.Setenv("NOMAD_TOKEN", os.Getenv("NOMAD_TOKEN"))
assert := assert.New(t)
config := func(c *agent.Config) {
c.ACL.Enabled = true
}
srv, _, url := testServer(t, true, config)
defer srv.Shutdown()
defer stopTestAgent(srv)
state := srv.Agent.Server().State()
// Bootstrap an initial ACL token
token := srv.RootToken
assert.NotNil(token, "failed to bootstrap ACL token")
must.NotNil(t, token)
ui := cli.NewMockUi()
cmd := &ACLTokenInfoCommand{Meta: Meta{Ui: ui, flagAddress: url}}
@@ -38,28 +32,26 @@ func TestACLTokenInfoCommand_ViaEnvVar(t *testing.T) {
mockToken := mock.ACLToken()
mockToken.Policies = []string{acl.PolicyWrite}
mockToken.SetHash()
assert.Nil(state.UpsertACLTokens(structs.MsgTypeTestSetup, 1000, []*structs.ACLToken{mockToken}))
must.NoError(t, state.UpsertACLTokens(structs.MsgTypeTestSetup, 1000, []*structs.ACLToken{mockToken}))
// Attempt to fetch info on a token without providing a valid management
// token
invalidToken := mock.ACLToken()
os.Setenv("NOMAD_TOKEN", invalidToken.SecretID)
t.Setenv("NOMAD_TOKEN", invalidToken.SecretID)
code := cmd.Run([]string{"-address=" + url, mockToken.AccessorID})
assert.Equal(1, code)
must.One(t, code)
// Fetch info on a token with a valid management token
os.Setenv("NOMAD_TOKEN", token.SecretID)
t.Setenv("NOMAD_TOKEN", token.SecretID)
code = cmd.Run([]string{"-address=" + url, mockToken.AccessorID})
assert.Equal(0, code)
must.Zero(t, code)
// Fetch info on a token with a valid management token via a CLI option
os.Setenv("NOMAD_TOKEN", "")
t.Setenv("NOMAD_TOKEN", "")
code = cmd.Run([]string{"-address=" + url, "-token=" + token.SecretID, mockToken.AccessorID})
assert.Equal(0, code)
must.Zero(t, code)
// Check the output
out := ui.OutputWriter.String()
if !strings.Contains(out, mockToken.AccessorID) {
t.Fatalf("bad: %v", out)
}
must.StrContains(t, out, mockToken.AccessorID)
}

View File

@@ -1,7 +1,6 @@
package command
import (
"strings"
"testing"
"github.com/hashicorp/nomad/acl"
@@ -10,29 +9,30 @@ import (
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/mitchellh/cli"
"github.com/stretchr/testify/assert"
"github.com/shoenig/test/must"
)
func TestACLTokenListCommand(t *testing.T) {
ci.Parallel(t)
assert := assert.New(t)
config := func(c *agent.Config) {
c.ACL.Enabled = true
}
srv, _, url := testServer(t, true, config)
defer stopTestAgent(srv)
state := srv.Agent.Server().State()
defer srv.Shutdown()
// Bootstrap an initial ACL token
token := srv.RootToken
assert.NotNil(token, "failed to bootstrap ACL token")
must.NotNil(t, token)
// Create a valid token
mockToken := mock.ACLToken()
mockToken.Policies = []string{acl.PolicyWrite}
mockToken.SetHash()
assert.Nil(state.UpsertACLTokens(structs.MsgTypeTestSetup, 1000, []*structs.ACLToken{mockToken}))
must.NoError(t, state.UpsertACLTokens(structs.MsgTypeTestSetup, 1000, []*structs.ACLToken{mockToken}))
ui := cli.NewMockUi()
cmd := &ACLTokenListCommand{Meta: Meta{Ui: ui, flagAddress: url}}
@@ -40,25 +40,20 @@ func TestACLTokenListCommand(t *testing.T) {
// Attempt to list tokens without a valid management token
invalidToken := mock.ACLToken()
code := cmd.Run([]string{"-address=" + url, "-token=" + invalidToken.SecretID})
assert.Equal(1, code)
must.One(t, code)
// Apply a token with a valid management token
code = cmd.Run([]string{"-address=" + url, "-token=" + token.SecretID})
assert.Equal(0, code)
must.Zero(t, code)
// Check the output
out := ui.OutputWriter.String()
if !strings.Contains(out, mockToken.Name) {
t.Fatalf("bad: %v", out)
}
must.StrContains(t, out, mockToken.Name)
// List json
if code := cmd.Run([]string{"-address=" + url, "-token=" + token.SecretID, "-json"}); code != 0 {
t.Fatalf("expected exit 0, got: %d; %v", code, ui.ErrorWriter.String())
}
must.Zero(t, cmd.Run([]string{"-address=" + url, "-token=" + token.SecretID, "-json"}))
out = ui.OutputWriter.String()
if !strings.Contains(out, "CreateIndex") {
t.Fatalf("expected json output, got: %s", out)
}
must.StrContains(t, out, "CreateIndex")
ui.OutputWriter.Reset()
}

View File

@@ -1,35 +1,29 @@
package command
import (
"os"
"strings"
"testing"
"github.com/hashicorp/nomad/acl"
"github.com/hashicorp/nomad/ci"
"github.com/hashicorp/nomad/command/agent"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/mitchellh/cli"
"github.com/stretchr/testify/assert"
"github.com/shoenig/test/must"
)
func TestACLTokenSelfCommand_ViaEnvVar(t *testing.T) {
ci.Parallel(t)
defer os.Setenv("NOMAD_TOKEN", os.Getenv("NOMAD_TOKEN"))
assert := assert.New(t)
config := func(c *agent.Config) {
c.ACL.Enabled = true
}
srv, _, url := testServer(t, true, config)
defer srv.Shutdown()
defer stopTestAgent(srv)
state := srv.Agent.Server().State()
// Bootstrap an initial ACL token
token := srv.RootToken
assert.NotNil(token, "failed to bootstrap ACL token")
must.NotNil(t, token)
ui := cli.NewMockUi()
cmd := &ACLTokenSelfCommand{Meta: Meta{Ui: ui, flagAddress: url}}
@@ -38,23 +32,21 @@ func TestACLTokenSelfCommand_ViaEnvVar(t *testing.T) {
mockToken := mock.ACLToken()
mockToken.Policies = []string{acl.PolicyWrite}
mockToken.SetHash()
assert.Nil(state.UpsertACLTokens(structs.MsgTypeTestSetup, 1000, []*structs.ACLToken{mockToken}))
must.NoError(t, state.UpsertACLTokens(structs.MsgTypeTestSetup, 1000, []*structs.ACLToken{mockToken}))
// Attempt to fetch info on a token without providing a valid management
// token
invalidToken := mock.ACLToken()
os.Setenv("NOMAD_TOKEN", invalidToken.SecretID)
t.Setenv("NOMAD_TOKEN", invalidToken.SecretID)
code := cmd.Run([]string{"-address=" + url})
assert.Equal(1, code)
must.One(t, code)
// Fetch info on a token with a valid token
os.Setenv("NOMAD_TOKEN", mockToken.SecretID)
t.Setenv("NOMAD_TOKEN", mockToken.SecretID)
code = cmd.Run([]string{"-address=" + url})
assert.Equal(0, code)
must.Zero(t, code)
// Check the output
out := ui.OutputWriter.String()
if !strings.Contains(out, mockToken.AccessorID) {
t.Fatalf("bad: %v", out)
}
must.StrContains(t, out, mockToken.AccessorID)
}

View File

@@ -9,23 +9,22 @@ import (
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/mitchellh/cli"
"github.com/stretchr/testify/assert"
"github.com/shoenig/test/must"
)
func TestACLTokenUpdateCommand(t *testing.T) {
ci.Parallel(t)
assert := assert.New(t)
config := func(c *agent.Config) {
c.ACL.Enabled = true
}
srv, _, url := testServer(t, true, config)
defer srv.Shutdown()
defer stopTestAgent(srv)
// Bootstrap an initial ACL token
token := srv.RootToken
assert.NotNil(token, "failed to bootstrap ACL token")
must.NotNil(t, token)
ui := cli.NewMockUi()
cmd := &ACLTokenUpdateCommand{Meta: Meta{Ui: ui, flagAddress: url}}
@@ -35,19 +34,19 @@ func TestACLTokenUpdateCommand(t *testing.T) {
mockToken := mock.ACLToken()
mockToken.Policies = []string{acl.PolicyWrite}
mockToken.SetHash()
assert.Nil(state.UpsertACLTokens(structs.MsgTypeTestSetup, 1000, []*structs.ACLToken{mockToken}))
must.NoError(t, state.UpsertACLTokens(structs.MsgTypeTestSetup, 1000, []*structs.ACLToken{mockToken}))
// Request to update a new token without providing a valid management token
invalidToken := mock.ACLToken()
code := cmd.Run([]string{"--token=" + invalidToken.SecretID, "-address=" + url, "-name=bar", mockToken.AccessorID})
assert.Equal(1, code)
must.One(t, code)
// Request to update a new token with a valid management token
code = cmd.Run([]string{"--token=" + token.SecretID, "-address=" + url, "-name=bar", mockToken.AccessorID})
assert.Equal(0, code)
must.Zero(t, code)
// Check the output
out := ui.OutputWriter.String()
assert.Contains(out, mockToken.AccessorID)
assert.Contains(out, "bar")
must.StrContains(t, out, mockToken.AccessorID)
must.StrContains(t, out, "bar")
}

View File

@@ -8,7 +8,7 @@ import (
"strings"
"time"
humanize "github.com/dustin/go-humanize"
"github.com/dustin/go-humanize"
"github.com/posener/complete"
"github.com/hashicorp/nomad/api"

View File

@@ -12,10 +12,9 @@ import (
"github.com/hashicorp/nomad/helper/uuid"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/nomad/testutil"
"github.com/mitchellh/cli"
"github.com/posener/complete"
"github.com/stretchr/testify/assert"
"github.com/shoenig/test/must"
"github.com/stretchr/testify/require"
)
@@ -27,7 +26,7 @@ func TestAllocStatusCommand_Implements(t *testing.T) {
func TestAllocStatusCommand_Fails(t *testing.T) {
ci.Parallel(t)
srv, _, url := testServer(t, false, nil)
defer srv.Shutdown()
defer stopTestAgent(srv)
ui := cli.NewMockUi()
cmd := &AllocStatusCommand{Meta: Meta{Ui: ui}}
@@ -89,23 +88,9 @@ func TestAllocStatusCommand_Fails(t *testing.T) {
func TestAllocStatusCommand_LifecycleInfo(t *testing.T) {
ci.Parallel(t)
srv, client, url := testServer(t, true, nil)
defer srv.Shutdown()
defer stopTestAgent(srv)
// Wait for a node to be ready
testutil.WaitForResult(func() (bool, error) {
nodes, _, err := client.Nodes().List(nil)
if err != nil {
return false, err
}
for _, node := range nodes {
if node.Status == structs.NodeStatusReady {
return true, nil
}
}
return false, fmt.Errorf("no ready nodes")
}, func(err error) {
require.NoError(t, err)
})
waitForNodes(t, client)
ui := cli.NewMockUi()
cmd := &AllocStatusCommand{Meta: Meta{Ui: ui}}
@@ -152,24 +137,9 @@ func TestAllocStatusCommand_LifecycleInfo(t *testing.T) {
func TestAllocStatusCommand_Run(t *testing.T) {
ci.Parallel(t)
srv, client, url := testServer(t, true, nil)
defer srv.Shutdown()
defer stopTestAgent(srv)
// Wait for a node to be ready
testutil.WaitForResult(func() (bool, error) {
nodes, _, err := client.Nodes().List(nil)
if err != nil {
return false, err
}
for _, node := range nodes {
if _, ok := node.Drivers["mock_driver"]; ok &&
node.Status == structs.NodeStatusReady {
return true, nil
}
}
return false, fmt.Errorf("no ready nodes")
}, func(err error) {
t.Fatalf("err: %v", err)
})
waitForNodes(t, client)
ui := cli.NewMockUi()
cmd := &AllocStatusCommand{Meta: Meta{Ui: ui}}
@@ -249,28 +219,13 @@ func TestAllocStatusCommand_Run(t *testing.T) {
func TestAllocStatusCommand_RescheduleInfo(t *testing.T) {
ci.Parallel(t)
srv, client, url := testServer(t, true, nil)
defer srv.Shutdown()
defer stopTestAgent(srv)
// Wait for a node to be ready
testutil.WaitForResult(func() (bool, error) {
nodes, _, err := client.Nodes().List(nil)
if err != nil {
return false, err
}
for _, node := range nodes {
if node.Status == structs.NodeStatusReady {
return true, nil
}
}
return false, fmt.Errorf("no ready nodes")
}, func(err error) {
t.Fatalf("err: %v", err)
})
waitForNodes(t, client)
ui := cli.NewMockUi()
cmd := &AllocStatusCommand{Meta: Meta{Ui: ui}}
// Test reschedule attempt info
require := require.New(t)
state := srv.Agent.Server().State()
a := mock.Alloc()
a.Metrics = &structs.AllocMetric{}
@@ -285,41 +240,27 @@ func TestAllocStatusCommand_RescheduleInfo(t *testing.T) {
},
},
}
require.Nil(state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{a}))
require.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{a}))
if code := cmd.Run([]string{"-address=" + url, a.ID}); code != 0 {
t.Fatalf("expected exit 0, got: %d", code)
}
out := ui.OutputWriter.String()
require.Contains(out, "Replacement Alloc ID")
require.Regexp(regexp.MustCompile(".*Reschedule Attempts\\s*=\\s*1/2"), out)
require.Contains(t, out, "Replacement Alloc ID")
require.Regexp(t, regexp.MustCompile(".*Reschedule Attempts\\s*=\\s*1/2"), out)
}
func TestAllocStatusCommand_ScoreMetrics(t *testing.T) {
ci.Parallel(t)
srv, client, url := testServer(t, true, nil)
defer srv.Shutdown()
defer stopTestAgent(srv)
// Wait for a node to be ready
testutil.WaitForResult(func() (bool, error) {
nodes, _, err := client.Nodes().List(nil)
if err != nil {
return false, err
}
for _, node := range nodes {
if node.Status == structs.NodeStatusReady {
return true, nil
}
}
return false, fmt.Errorf("no ready nodes")
}, func(err error) {
t.Fatalf("err: %v", err)
})
waitForNodes(t, client)
ui := cli.NewMockUi()
cmd := &AllocStatusCommand{Meta: Meta{Ui: ui}}
// Test node metrics
require := require.New(t)
state := srv.Agent.Server().State()
a := mock.Alloc()
mockNode1 := mock.Node()
@@ -342,27 +283,26 @@ func TestAllocStatusCommand_ScoreMetrics(t *testing.T) {
},
},
}
require.Nil(state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{a}))
require.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{a}))
if code := cmd.Run([]string{"-address=" + url, "-verbose", a.ID}); code != 0 {
t.Fatalf("expected exit 0, got: %d", code)
}
out := ui.OutputWriter.String()
require.Contains(out, "Placement Metrics")
require.Contains(out, mockNode1.ID)
require.Contains(out, mockNode2.ID)
require.Contains(t, out, "Placement Metrics")
require.Contains(t, out, mockNode1.ID)
require.Contains(t, out, mockNode2.ID)
// assert we sort headers alphabetically
require.Contains(out, "binpack node-affinity")
require.Contains(out, "final score")
require.Contains(t, out, "binpack node-affinity")
require.Contains(t, out, "final score")
}
func TestAllocStatusCommand_AutocompleteArgs(t *testing.T) {
ci.Parallel(t)
assert := assert.New(t)
srv, _, url := testServer(t, true, nil)
defer srv.Shutdown()
defer stopTestAgent(srv)
ui := cli.NewMockUi()
cmd := &AllocStatusCommand{Meta: Meta{Ui: ui, flagAddress: url}}
@@ -370,15 +310,15 @@ func TestAllocStatusCommand_AutocompleteArgs(t *testing.T) {
// Create a fake alloc
state := srv.Agent.Server().State()
a := mock.Alloc()
assert.Nil(state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{a}))
must.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{a}))
prefix := a.ID[:5]
args := complete.Args{Last: prefix}
predictor := cmd.AutocompleteArgs()
res := predictor.Predict(args)
assert.Equal(1, len(res))
assert.Equal(a.ID, res[0])
must.Len(t, 1, res)
must.Eq(t, a.ID, res[0])
}
func TestAllocStatusCommand_HostVolumes(t *testing.T) {
@@ -397,7 +337,8 @@ func TestAllocStatusCommand_HostVolumes(t *testing.T) {
},
}
})
defer srv.Shutdown()
defer stopTestAgent(srv)
state := srv.Agent.Server().State()
// Upsert the job and alloc
@@ -448,7 +389,8 @@ func TestAllocStatusCommand_HostVolumes(t *testing.T) {
func TestAllocStatusCommand_CSIVolumes(t *testing.T) {
ci.Parallel(t)
srv, _, url := testServer(t, true, nil)
defer srv.Shutdown()
defer stopTestAgent(srv)
state := srv.Agent.Server().State()
// Upsert the node, plugin, and volume

View File

@@ -347,7 +347,7 @@ job "example" {
}
`
setEnv(t, "NOMAD_VAR_var4", "from-envvar")
t.Setenv("NOMAD_VAR_var4", "from-envvar")
cliArgs := []string{`var2=from-cli`}
fileVars := `var3 = "from-varfile"`

View File

@@ -92,7 +92,7 @@ func TestMeta_Colorize(t *testing.T) {
{
Name: "disable colors via env var",
SetupFn: func(t *testing.T, m *Meta) {
setEnv(t, EnvNomadCLINoColor, "1")
t.Setenv(EnvNomadCLINoColor, "1")
m.SetupUi([]string{})
},
ExpectColor: false,
@@ -107,7 +107,7 @@ func TestMeta_Colorize(t *testing.T) {
{
Name: "force colors via env var",
SetupFn: func(t *testing.T, m *Meta) {
setEnv(t, EnvNomadCLIForceColor, "1")
t.Setenv(EnvNomadCLIForceColor, "1")
m.SetupUi([]string{})
},
ExpectColor: true,
@@ -122,7 +122,7 @@ func TestMeta_Colorize(t *testing.T) {
{
Name: "no color take predecence over force color via env var",
SetupFn: func(t *testing.T, m *Meta) {
setEnv(t, EnvNomadCLINoColor, "1")
t.Setenv(EnvNomadCLINoColor, "1")
m.SetupUi([]string{"-force-color"})
},
ExpectColor: false,
@@ -141,8 +141,8 @@ func TestMeta_Colorize(t *testing.T) {
os.Stdout = tty
// Make sure color related environment variables are clean.
setEnv(t, EnvNomadCLIForceColor, "")
setEnv(t, EnvNomadCLINoColor, "")
t.Setenv(EnvNomadCLIForceColor, "")
t.Setenv(EnvNomadCLINoColor, "")
// Run test case.
m := &Meta{}

View File

@@ -1,13 +1,16 @@
package command
import (
"fmt"
"os"
"testing"
"github.com/hashicorp/nomad/api"
"github.com/hashicorp/nomad/command/agent"
"github.com/hashicorp/nomad/helper/pointer"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/nomad/testutil"
"github.com/shoenig/test/must"
)
func testServer(t *testing.T, runClient bool, cb func(*agent.Config)) (*agent.TestAgent, *api.Client, string) {
@@ -108,16 +111,33 @@ func testMultiRegionJob(jobID, region, datacenter string) *api.Job {
return job
}
// setEnv wraps os.Setenv(key, value) and restores the environment variable to initial value in test cleanup
func setEnv(t *testing.T, key, value string) {
initial, ok := os.LookupEnv(key)
os.Setenv(key, value)
t.Cleanup(func() {
if ok {
os.Setenv(key, initial)
} else {
os.Unsetenv(key)
func waitForNodes(t *testing.T, client *api.Client) {
testutil.WaitForResult(func() (bool, error) {
nodes, _, err := client.Nodes().List(nil)
if err != nil {
return false, err
}
for _, node := range nodes {
if _, ok := node.Drivers["mock_driver"]; ok &&
node.Status == structs.NodeStatusReady {
return true, nil
}
}
return false, fmt.Errorf("no ready nodes")
}, func(err error) {
must.NoError(t, err)
})
}
func stopTestAgent(a *agent.TestAgent) {
_ = a.Shutdown()
}
func getTempFile(t *testing.T, name string) (string, func()) {
f, err := os.CreateTemp("", name)
must.NoError(t, err)
must.NoError(t, f.Close())
return f.Name(), func() {
_ = os.Remove(f.Name())
}
}

View File

@@ -43,38 +43,38 @@ func TestCommand_Ui(t *testing.T) {
{
Name: "set namespace via env var",
SetupFn: func(t *testing.T) {
setEnv(t, "NOMAD_NAMESPACE", "dev")
t.Setenv("NOMAD_NAMESPACE", "dev")
},
ExpectedURL: "http://127.0.0.1:4646?namespace=dev",
},
{
Name: "set region via env var",
SetupFn: func(t *testing.T) {
setEnv(t, "NOMAD_REGION", "earth")
t.Setenv("NOMAD_REGION", "earth")
},
ExpectedURL: "http://127.0.0.1:4646?region=earth",
},
{
Name: "set region and namespace via env var",
SetupFn: func(t *testing.T) {
setEnv(t, "NOMAD_REGION", "earth")
setEnv(t, "NOMAD_NAMESPACE", "dev")
t.Setenv("NOMAD_REGION", "earth")
t.Setenv("NOMAD_NAMESPACE", "dev")
},
ExpectedURL: "http://127.0.0.1:4646?namespace=dev&region=earth",
},
{
Name: "set region and namespace via env var",
SetupFn: func(t *testing.T) {
setEnv(t, "NOMAD_REGION", "earth")
setEnv(t, "NOMAD_NAMESPACE", "dev")
t.Setenv("NOMAD_REGION", "earth")
t.Setenv("NOMAD_NAMESPACE", "dev")
},
ExpectedURL: "http://127.0.0.1:4646?namespace=dev&region=earth",
},
{
Name: "flags have higher precedence",
SetupFn: func(t *testing.T) {
setEnv(t, "NOMAD_REGION", "earth")
setEnv(t, "NOMAD_NAMESPACE", "dev")
t.Setenv("NOMAD_REGION", "earth")
t.Setenv("NOMAD_NAMESPACE", "dev")
},
Args: []string{
"-region=mars",
@@ -87,8 +87,8 @@ func TestCommand_Ui(t *testing.T) {
for _, tc := range cases {
t.Run(tc.Name, func(t *testing.T) {
// Make sure environment variables are clean.
setEnv(t, "NOMAD_NAMESPACE", "")
setEnv(t, "NOMAD_REGION", "")
t.Setenv("NOMAD_NAMESPACE", "")
t.Setenv("NOMAD_REGION", "")
// Setup fake CLI UI and test case
ui := cli.NewMockUi()

2
go.mod
View File

@@ -109,7 +109,7 @@ require (
github.com/ryanuber/go-glob v1.0.0
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529
github.com/shirou/gopsutil/v3 v3.21.12
github.com/shoenig/test v0.3.0
github.com/shoenig/test v0.3.1
github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c
github.com/stretchr/testify v1.8.0
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635

4
go.sum
View File

@@ -1199,8 +1199,8 @@ github.com/shirou/gopsutil v0.0.0-20181107111621-48177ef5f880/go.mod h1:5b4v6he4
github.com/shirou/gopsutil/v3 v3.21.12 h1:VoGxEW2hpmz0Vt3wUvHIl9fquzYLNpVpgNNB7pGJimA=
github.com/shirou/gopsutil/v3 v3.21.12/go.mod h1:BToYZVTlSVlfazpDDYFnsVZLaoRG+g8ufT6fPQLdJzA=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/shoenig/test v0.3.0 h1:H6tfSvgLrPHRR5NH9S40+lOfoyeH2PbswBr4twgn9Po=
github.com/shoenig/test v0.3.0/go.mod h1:xYtyGBC5Q3kzCNyJg/SjgNpfAa2kvmgA0i5+lQso8x0=
github.com/shoenig/test v0.3.1 h1:dhGZztS6nQuvJ0o0RtUiQHaEO4hhArh/WmWwik3Ols0=
github.com/shoenig/test v0.3.1/go.mod h1:xYtyGBC5Q3kzCNyJg/SjgNpfAa2kvmgA0i5+lQso8x0=
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=