1package command
2
3import (
4	"fmt"
5	"testing"
6
7	"github.com/hashicorp/nomad/api"
8	"github.com/hashicorp/nomad/nomad/structs"
9	"github.com/hashicorp/nomad/testutil"
10	"github.com/mitchellh/cli"
11	"github.com/stretchr/testify/require"
12)
13
14func TestAllocStopCommand_Implements(t *testing.T) {
15	t.Parallel()
16	var _ cli.Command = &AllocStopCommand{}
17}
18
19func TestAllocStop_Fails(t *testing.T) {
20	srv, _, url := testServer(t, false, nil)
21	defer srv.Shutdown()
22
23	require := require.New(t)
24	ui := new(cli.MockUi)
25	cmd := &AllocStopCommand{Meta: Meta{Ui: ui}}
26
27	// Fails on misuse
28	require.Equal(cmd.Run([]string{"some", "garbage", "args"}), 1, "Expected failure")
29	require.Contains(ui.ErrorWriter.String(), commandErrorText(cmd), "Expected help output")
30	ui.ErrorWriter.Reset()
31
32	// Fails on connection failure
33	require.Equal(cmd.Run([]string{"-address=nope", "foobar"}), 1, "expected failure")
34	require.Contains(ui.ErrorWriter.String(), "Error querying allocation")
35	ui.ErrorWriter.Reset()
36
37	// Fails on missing alloc
38	require.Equal(cmd.Run([]string{"-address=" + url, "26470238-5CF2-438F-8772-DC67CFB0705C"}), 1)
39	require.Contains(ui.ErrorWriter.String(), "No allocation(s) with prefix or id")
40	ui.ErrorWriter.Reset()
41
42	// Fail on identifier with too few characters
43	require.Equal(cmd.Run([]string{"-address=" + url, "2"}), 1)
44	require.Contains(ui.ErrorWriter.String(), "must contain at least two characters")
45	ui.ErrorWriter.Reset()
46
47	// Identifiers with uneven length should produce a query result
48	require.Equal(cmd.Run([]string{"-address=" + url, "123"}), 1)
49	require.Contains(ui.ErrorWriter.String(), "No allocation(s) with prefix or id")
50	ui.ErrorWriter.Reset()
51}
52
53func TestAllocStop_Run(t *testing.T) {
54	srv, client, url := testServer(t, true, nil)
55	defer srv.Shutdown()
56
57	require := require.New(t)
58
59	// Wait for a node to be ready
60	testutil.WaitForResult(func() (bool, error) {
61		nodes, _, err := client.Nodes().List(nil)
62		if err != nil {
63			return false, err
64		}
65		for _, node := range nodes {
66			if _, ok := node.Drivers["mock_driver"]; ok &&
67				node.Status == structs.NodeStatusReady {
68				return true, nil
69			}
70		}
71		return false, fmt.Errorf("no ready nodes")
72	}, func(err error) {
73		t.Fatalf("err: %v", err)
74	})
75
76	ui := new(cli.MockUi)
77	cmd := &AllocStopCommand{Meta: Meta{Ui: ui}}
78
79	jobID := "job1_sfx"
80	job1 := testJob(jobID)
81	resp, _, err := client.Jobs().Register(job1, nil)
82	require.NoError(err)
83	if code := waitForSuccess(ui, client, fullId, t, resp.EvalID); code != 0 {
84		t.Fatalf("status code non zero saw %d", code)
85	}
86	// get an alloc id
87	allocId1 := ""
88	if allocs, _, err := client.Jobs().Allocations(jobID, false, nil); err == nil {
89		if len(allocs) > 0 {
90			allocId1 = allocs[0].ID
91		}
92	}
93	require.NotEmpty(allocId1, "unable to find allocation")
94
95	// Wait for alloc to be running
96	testutil.WaitForResult(func() (bool, error) {
97		alloc, _, err := client.Allocations().Info(allocId1, nil)
98		if err != nil {
99			return false, err
100		}
101		if alloc.ClientStatus == api.AllocClientStatusRunning {
102			return true, nil
103		}
104		return false, fmt.Errorf("alloc is not running, is: %s", alloc.ClientStatus)
105	}, func(err error) {
106		t.Fatalf("err: %v", err)
107	})
108
109	require.Equal(cmd.Run([]string{"-address=" + url, allocId1}), 0, "expected successful exit code")
110
111	ui.OutputWriter.Reset()
112}
113