1package command
2
3import (
4	"fmt"
5	"testing"
6
7	"github.com/hashicorp/nomad/api"
8	"github.com/hashicorp/nomad/nomad/mock"
9	"github.com/hashicorp/nomad/nomad/structs"
10	"github.com/hashicorp/nomad/testutil"
11	"github.com/mitchellh/cli"
12	"github.com/posener/complete"
13	"github.com/stretchr/testify/assert"
14	"github.com/stretchr/testify/require"
15)
16
17func TestAllocSignalCommand_Implements(t *testing.T) {
18	t.Parallel()
19	var _ cli.Command = &AllocSignalCommand{}
20}
21
22func TestAllocSignalCommand_Fails(t *testing.T) {
23	t.Parallel()
24	srv, _, url := testServer(t, false, nil)
25	defer srv.Shutdown()
26
27	require := require.New(t)
28
29	ui := new(cli.MockUi)
30	cmd := &AllocSignalCommand{Meta: Meta{Ui: ui}}
31
32	// Fails on lack of alloc ID
33	require.Equal(1, cmd.Run([]string{}))
34	require.Contains(ui.ErrorWriter.String(), "This command takes up to two arguments")
35	ui.ErrorWriter.Reset()
36
37	// Fails on misuse
38	require.Equal(1, cmd.Run([]string{"some", "bad", "args"}))
39	require.Contains(ui.ErrorWriter.String(), "This command takes up to two arguments")
40	ui.ErrorWriter.Reset()
41
42	// Fails on connection failure
43	require.Equal(1, cmd.Run([]string{"-address=nope", "foobar"}))
44	require.Contains(ui.ErrorWriter.String(), "Error querying allocation")
45	ui.ErrorWriter.Reset()
46
47	// Fails on missing alloc
48	code := cmd.Run([]string{"-address=" + url, "26470238-5CF2-438F-8772-DC67CFB0705C"})
49	require.Equal(1, code)
50	require.Contains(ui.ErrorWriter.String(), "No allocation(s) with prefix or id")
51	ui.ErrorWriter.Reset()
52
53	// Fail on identifier with too few characters
54	require.Equal(1, cmd.Run([]string{"-address=" + url, "2"}))
55	require.Contains(ui.ErrorWriter.String(), "must contain at least two characters.")
56	ui.ErrorWriter.Reset()
57}
58
59func TestAllocSignalCommand_AutocompleteArgs(t *testing.T) {
60	assert := assert.New(t)
61
62	srv, _, url := testServer(t, true, nil)
63	defer srv.Shutdown()
64
65	ui := new(cli.MockUi)
66	cmd := &AllocSignalCommand{Meta: Meta{Ui: ui, flagAddress: url}}
67
68	// Create a fake alloc
69	state := srv.Agent.Server().State()
70	a := mock.Alloc()
71	assert.Nil(state.UpsertAllocs(1000, []*structs.Allocation{a}))
72
73	prefix := a.ID[:5]
74	args := complete.Args{All: []string{"signal", prefix}, Last: prefix}
75	predictor := cmd.AutocompleteArgs()
76
77	// Match Allocs
78	res := predictor.Predict(args)
79	assert.Equal(1, len(res))
80	assert.Equal(a.ID, res[0])
81}
82
83func TestAllocSignalCommand_Run(t *testing.T) {
84	srv, client, url := testServer(t, true, nil)
85	defer srv.Shutdown()
86
87	require := require.New(t)
88
89	// Wait for a node to be ready
90	testutil.WaitForResult(func() (bool, error) {
91		nodes, _, err := client.Nodes().List(nil)
92		if err != nil {
93			return false, err
94		}
95		for _, node := range nodes {
96			if _, ok := node.Drivers["mock_driver"]; ok &&
97				node.Status == structs.NodeStatusReady {
98				return true, nil
99			}
100		}
101		return false, fmt.Errorf("no ready nodes")
102	}, func(err error) {
103		t.Fatalf("err: %v", err)
104	})
105
106	ui := new(cli.MockUi)
107	cmd := &AllocSignalCommand{Meta: Meta{Ui: ui}}
108
109	jobID := "job1_sfx"
110	job1 := testJob(jobID)
111	resp, _, err := client.Jobs().Register(job1, nil)
112	require.NoError(err)
113	if code := waitForSuccess(ui, client, fullId, t, resp.EvalID); code != 0 {
114		t.Fatalf("status code non zero saw %d", code)
115	}
116	// get an alloc id
117	allocId1 := ""
118	if allocs, _, err := client.Jobs().Allocations(jobID, false, nil); err == nil {
119		if len(allocs) > 0 {
120			allocId1 = allocs[0].ID
121		}
122	}
123	require.NotEmpty(allocId1, "unable to find allocation")
124
125	// Wait for alloc to be running
126	testutil.WaitForResult(func() (bool, error) {
127		alloc, _, err := client.Allocations().Info(allocId1, nil)
128		if err != nil {
129			return false, err
130		}
131		if alloc.ClientStatus == api.AllocClientStatusRunning {
132			return true, nil
133		}
134		return false, fmt.Errorf("alloc is not running, is: %s", alloc.ClientStatus)
135	}, func(err error) {
136		t.Fatalf("err: %v", err)
137	})
138
139	require.Equal(cmd.Run([]string{"-address=" + url, allocId1}), 0, "expected successful exit code")
140
141	ui.OutputWriter.Reset()
142}
143