1package api
2
3import (
4	"testing"
5	"time"
6
7	"github.com/hashicorp/consul/sdk/testutil"
8	"github.com/hashicorp/consul/sdk/testutil/retry"
9	"github.com/stretchr/testify/require"
10)
11
12func TestAPI_OperatorAutopilotGetSetConfiguration(t *testing.T) {
13	t.Parallel()
14	c, s := makeClient(t)
15	defer s.Stop()
16	s.WaitForSerfCheck(t)
17
18	operator := c.Operator()
19	config, err := operator.AutopilotGetConfiguration(nil)
20	if err != nil {
21		t.Fatalf("err: %v", err)
22	}
23	if !config.CleanupDeadServers {
24		t.Fatalf("bad: %v", config)
25	}
26
27	// Change a config setting
28	newConf := &AutopilotConfiguration{CleanupDeadServers: false}
29	if err := operator.AutopilotSetConfiguration(newConf, nil); err != nil {
30		t.Fatalf("err: %v", err)
31	}
32
33	config, err = operator.AutopilotGetConfiguration(nil)
34	if err != nil {
35		t.Fatalf("err: %v", err)
36	}
37	if config.CleanupDeadServers {
38		t.Fatalf("bad: %v", config)
39	}
40}
41
42func TestAPI_OperatorAutopilotCASConfiguration(t *testing.T) {
43	t.Parallel()
44	c, s := makeClient(t)
45	defer s.Stop()
46
47	retry.Run(t, func(r *retry.R) {
48		operator := c.Operator()
49		config, err := operator.AutopilotGetConfiguration(nil)
50		if err != nil {
51			r.Fatalf("err: %v", err)
52		}
53		if !config.CleanupDeadServers {
54			r.Fatalf("bad: %v", config)
55		}
56
57		// Pass an invalid ModifyIndex
58		{
59			newConf := &AutopilotConfiguration{
60				CleanupDeadServers: false,
61				ModifyIndex:        config.ModifyIndex - 1,
62			}
63			resp, err := operator.AutopilotCASConfiguration(newConf, nil)
64			if err != nil {
65				r.Fatalf("err: %v", err)
66			}
67			if resp {
68				r.Fatalf("bad: %v", resp)
69			}
70		}
71
72		// Pass a valid ModifyIndex
73		{
74			newConf := &AutopilotConfiguration{
75				CleanupDeadServers: false,
76				ModifyIndex:        config.ModifyIndex,
77			}
78			resp, err := operator.AutopilotCASConfiguration(newConf, nil)
79			if err != nil {
80				r.Fatalf("err: %v", err)
81			}
82			if !resp {
83				r.Fatalf("bad: %v", resp)
84			}
85		}
86	})
87}
88
89func TestAPI_OperatorAutopilotServerHealth(t *testing.T) {
90	t.Parallel()
91	c, s := makeClientWithConfig(t, nil, func(c *testutil.TestServerConfig) {
92		c.RaftProtocol = 3
93	})
94	defer s.Stop()
95
96	operator := c.Operator()
97	retry.Run(t, func(r *retry.R) {
98		out, err := operator.AutopilotServerHealth(nil)
99		if err != nil {
100			r.Fatalf("err: %v", err)
101		}
102
103		if len(out.Servers) != 1 ||
104			!out.Servers[0].Healthy ||
105			out.Servers[0].Name != s.Config.NodeName {
106			r.Fatalf("bad: %v", out)
107		}
108	})
109}
110
111func TestAPI_OperatorAutopilotState(t *testing.T) {
112	c, s := makeClient(t)
113	defer s.Stop()
114
115	operator := c.Operator()
116	retry.Run(t, func(r *retry.R) {
117		out, err := operator.AutopilotState(nil)
118		if err != nil {
119			r.Fatalf("err: %v", err)
120		}
121
122		srv, ok := out.Servers[s.Config.NodeID]
123		if !ok || !srv.Healthy || srv.Name != s.Config.NodeName {
124			r.Fatalf("bad: %v", out)
125		}
126	})
127}
128
129func TestAPI_OperatorAutopilotServerHealth_429(t *testing.T) {
130	mapi, client := setupMockAPI(t)
131
132	reply := OperatorHealthReply{
133		Healthy:          false,
134		FailureTolerance: 0,
135		Servers: []ServerHealth{
136			{
137				ID:          "d9fdded2-27ae-4db2-9232-9d8d0114ac98",
138				Name:        "foo",
139				Address:     "198.18.0.1:8300",
140				SerfStatus:  "alive",
141				Version:     "1.8.3",
142				Leader:      true,
143				LastContact: NewReadableDuration(0),
144				LastTerm:    4,
145				LastIndex:   99,
146				Healthy:     true,
147				Voter:       true,
148				StableSince: time.Date(2020, 9, 2, 12, 0, 0, 0, time.UTC),
149			},
150			{
151				ID:          "1bcdda01-b896-41bc-a763-1a62b4260777",
152				Name:        "bar",
153				Address:     "198.18.0.2:8300",
154				SerfStatus:  "alive",
155				Version:     "1.8.3",
156				Leader:      false,
157				LastContact: NewReadableDuration(10 * time.Millisecond),
158				LastTerm:    4,
159				LastIndex:   99,
160				Healthy:     true,
161				Voter:       true,
162				StableSince: time.Date(2020, 9, 2, 12, 0, 0, 0, time.UTC),
163			},
164			{
165				ID:          "661d1eac-81be-436b-bfe1-d51ffd665b9d",
166				Name:        "baz",
167				Address:     "198.18.0.3:8300",
168				SerfStatus:  "failed",
169				Version:     "1.8.3",
170				Leader:      false,
171				LastContact: NewReadableDuration(10 * time.Millisecond),
172				LastTerm:    4,
173				LastIndex:   99,
174				Healthy:     false,
175				Voter:       true,
176			},
177		},
178	}
179	mapi.withReply("GET", "/v1/operator/autopilot/health", nil, 429, reply).Once()
180
181	out, err := client.Operator().AutopilotServerHealth(nil)
182	require.NoError(t, err)
183	require.Equal(t, &reply, out)
184}
185