New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Show server statuses only when they are deployed into the Kubernetes cluster #1603
Changes from 8 commits
3eb5beb
114ee60
3ef6e26
aa9ebcd
68c3636
c7c87e6
f7c1a7d
76fa1e9
c978a87
cb169d1
e4eadae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,39 +28,51 @@ import ( | |
"k8s.io/client-go/kubernetes/fake" | ||
) | ||
|
||
// TestCheckConsulServers creates a fake stateful set and tests the checkConsulServers function. | ||
func TestCheckConsulServers(t *testing.T) { | ||
c := getInitializedCommand(t, nil) | ||
c.kubernetes = fake.NewSimpleClientset() | ||
|
||
// First check that no stateful sets causes an error. | ||
_, err := c.checkConsulServers("default") | ||
require.Error(t, err) | ||
require.Contains(t, err.Error(), "no server stateful set found") | ||
|
||
// Next create a stateful set with 3 desired replicas and 3 ready replicas. | ||
var replicas int32 = 3 | ||
func TestCheckConsulAgents(t *testing.T) { | ||
namespace := "default" | ||
cases := map[string]struct { | ||
desiredClients int | ||
healthyClients int | ||
desiredServers int | ||
healthyServers int | ||
}{ | ||
"No clients, no agents": {0, 0, 0, 0}, | ||
"3 clients - 1 healthy, no agents": {3, 1, 0, 0}, | ||
"3 clients - 3 healthy, no agents": {3, 3, 0, 0}, | ||
"3 clients - 1 healthy, 3 agents - 1 healthy": {3, 1, 3, 1}, | ||
"3 clients - 3 healthy, 3 agents - 3 healthy": {3, 3, 3, 3}, | ||
"No clients, 3 agents - 1 healthy": {0, 0, 3, 1}, | ||
"No clients, 3 agents - 3 healthy": {0, 0, 3, 3}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we're using confusing terminology here, it should be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great feedback. I fixed this when removing clients. |
||
} | ||
|
||
createStatefulSet("consul-server-test1", "default", replicas, replicas, c.kubernetes) | ||
for name, tc := range cases { | ||
t.Run(name, func(t *testing.T) { | ||
buf := new(bytes.Buffer) | ||
c := setupCommand(buf) | ||
c.kubernetes = fake.NewSimpleClientset() | ||
|
||
// Now we run the checkConsulServers() function and it should succeed. | ||
s, err := c.checkConsulServers("default") | ||
require.NoError(t, err) | ||
require.Equal(t, "Consul servers healthy (3/3)", s) | ||
// Deploy clients | ||
err := createClients("consul-clients", namespace, int32(tc.desiredClients), int32(tc.healthyClients), c.kubernetes) | ||
require.NoError(t, err) | ||
|
||
// If you then create another stateful set it should error. | ||
createStatefulSet("consul-server-test2", "default", replicas, replicas, c.kubernetes) | ||
_, err = c.checkConsulServers("default") | ||
require.Error(t, err) | ||
require.Contains(t, err.Error(), "found multiple server stateful sets") | ||
// Deploy servers | ||
err = createServers("consul-servers", namespace, int32(tc.desiredServers), int32(tc.healthyServers), c.kubernetes) | ||
require.NoError(t, err) | ||
|
||
// Clear out the client and now run a test where the stateful set isn't ready. | ||
c.kubernetes = fake.NewSimpleClientset() | ||
createStatefulSet("consul-server-test2", "default", replicas, replicas-1, c.kubernetes) | ||
// Verify that the correct clients and server statuses are seen. | ||
err = c.checkConsulAgents(namespace) | ||
require.NoError(t, err) | ||
|
||
_, err = c.checkConsulServers("default") | ||
require.Error(t, err) | ||
require.Contains(t, err.Error(), fmt.Sprintf("%d/%d Consul servers unhealthy", 1, replicas)) | ||
actual := buf.String() | ||
if tc.desiredClients != 0 { | ||
require.Contains(t, actual, fmt.Sprintf("Consul Clients Healthy %d/%d", tc.healthyClients, tc.desiredClients)) | ||
} | ||
if tc.desiredServers != 0 { | ||
require.Contains(t, actual, fmt.Sprintf("Consul Servers Healthy %d/%d", tc.healthyServers, tc.desiredServers)) | ||
} | ||
buf.Reset() | ||
}) | ||
} | ||
} | ||
|
||
// TestStatus creates a fake stateful set and tests the checkConsulServers function. | ||
|
@@ -79,11 +91,11 @@ func TestStatus(t *testing.T) { | |
input: []string{}, | ||
messages: []string{ | ||
fmt.Sprintf("\n==> Consul Status Summary\nName\tNamespace\tStatus\tChart Version\tAppVersion\tRevision\tLast Updated \n \t \tREADY \t1.0.0 \t \t0 \t%s\t\n", notImeStr), | ||
"\n==> Config:\n {}\n \n ✓ Consul servers healthy (3/3)\n", | ||
"\n==> Config:\n {}\n \nConsul Clients Healthy 3/3\nConsul Servers Healthy 3/3\n", | ||
}, | ||
preProcessingFunc: func(k8s kubernetes.Interface) { | ||
createDaemonset("consul-client-test1", "consul", 3, 3, k8s) | ||
createStatefulSet("consul-server-test1", "consul", 3, 3, k8s) | ||
createClients("consul-client-test1", "consul", 3, 3, k8s) | ||
createServers("consul-server-test1", "consul", 3, 3, k8s) | ||
}, | ||
|
||
helmActionsRunner: &helm.MockActionRunner{ | ||
|
@@ -101,40 +113,15 @@ func TestStatus(t *testing.T) { | |
}, | ||
expectedReturnCode: 0, | ||
}, | ||
"status with no servers returns error": { | ||
input: []string{}, | ||
messages: []string{ | ||
fmt.Sprintf("\n==> Consul Status Summary\nName\tNamespace\tStatus\tChart Version\tAppVersion\tRevision\tLast Updated \n \t \tREADY \t1.0.0 \t \t0 \t%s\t\n", notImeStr), | ||
"\n==> Config:\n {}\n \n ! no server stateful set found\n", | ||
}, | ||
preProcessingFunc: func(k8s kubernetes.Interface) { | ||
createDaemonset("consul-client-test1", "consul", 3, 3, k8s) | ||
}, | ||
helmActionsRunner: &helm.MockActionRunner{ | ||
GetStatusFunc: func(status *action.Status, name string) (*helmRelease.Release, error) { | ||
return &helmRelease.Release{ | ||
Name: "consul", Namespace: "consul", | ||
Info: &helmRelease.Info{LastDeployed: nowTime, Status: "READY"}, | ||
Chart: &chart.Chart{ | ||
Metadata: &chart.Metadata{ | ||
Version: "1.0.0", | ||
}, | ||
}, | ||
Config: make(map[string]interface{})}, nil | ||
}, | ||
}, | ||
expectedReturnCode: 1, | ||
}, | ||
"status with pre-install and pre-upgrade hooks returns success and outputs hook status": { | ||
input: []string{}, | ||
messages: []string{ | ||
fmt.Sprintf("\n==> Consul Status Summary\nName\tNamespace\tStatus\tChart Version\tAppVersion\tRevision\tLast Updated \n \t \tREADY \t1.0.0 \t \t0 \t%s\t\n", notImeStr), | ||
"\n==> Config:\n {}\n \n", | ||
"\n==> Status Of Helm Hooks:\npre-install-hook pre-install: Succeeded\npre-upgrade-hook pre-upgrade: Succeeded\n ✓ Consul servers healthy (3/3)\n", | ||
"\n==> Status Of Helm Hooks:\npre-install-hook pre-install: Succeeded\npre-upgrade-hook pre-upgrade: Succeeded\nConsul Servers Healthy 3/3\n", | ||
}, | ||
preProcessingFunc: func(k8s kubernetes.Interface) { | ||
createDaemonset("consul-client-test1", "consul", 3, 3, k8s) | ||
createStatefulSet("consul-server-test1", "consul", 3, 3, k8s) | ||
createServers("consul-server-test1", "consul", 3, 3, k8s) | ||
}, | ||
|
||
helmActionsRunner: &helm.MockActionRunner{ | ||
|
@@ -187,8 +174,8 @@ func TestStatus(t *testing.T) { | |
"\n==> Consul Status Summary\n ! kaboom!\n", | ||
}, | ||
preProcessingFunc: func(k8s kubernetes.Interface) { | ||
createDaemonset("consul-client-test1", "consul", 3, 3, k8s) | ||
createStatefulSet("consul-server-test1", "consul", 3, 3, k8s) | ||
createClients("consul-client-test1", "consul", 3, 3, k8s) | ||
createServers("consul-server-test1", "consul", 3, 3, k8s) | ||
}, | ||
|
||
helmActionsRunner: &helm.MockActionRunner{ | ||
|
@@ -204,8 +191,8 @@ func TestStatus(t *testing.T) { | |
"\n==> Consul Status Summary\n ! couldn't check for installations: kaboom!\n", | ||
}, | ||
preProcessingFunc: func(k8s kubernetes.Interface) { | ||
createDaemonset("consul-client-test1", "consul", 3, 3, k8s) | ||
createStatefulSet("consul-server-test1", "consul", 3, 3, k8s) | ||
createClients("consul-client-test1", "consul", 3, 3, k8s) | ||
createServers("consul-server-test1", "consul", 3, 3, k8s) | ||
}, | ||
|
||
helmActionsRunner: &helm.MockActionRunner{ | ||
|
@@ -291,8 +278,8 @@ func TestTaskCreateCommand_AutocompleteArgs(t *testing.T) { | |
assert.Equal(t, complete.PredictNothing, c) | ||
} | ||
|
||
func createStatefulSet(name, namespace string, replicas, readyReplicas int32, k8s kubernetes.Interface) { | ||
ss := &appsv1.StatefulSet{ | ||
func createServers(name, namespace string, replicas, readyReplicas int32, k8s kubernetes.Interface) error { | ||
servers := appsv1.StatefulSet{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: name, | ||
Namespace: namespace, | ||
|
@@ -306,12 +293,12 @@ func createStatefulSet(name, namespace string, replicas, readyReplicas int32, k8 | |
ReadyReplicas: readyReplicas, | ||
}, | ||
} | ||
|
||
k8s.AppsV1().StatefulSets(namespace).Create(context.Background(), ss, metav1.CreateOptions{}) | ||
_, err := k8s.AppsV1().StatefulSets(namespace).Create(context.Background(), &servers, metav1.CreateOptions{}) | ||
return err | ||
} | ||
|
||
func createDaemonset(name, namespace string, replicas, readyReplicas int32, k8s kubernetes.Interface) { | ||
ds := &appsv1.DaemonSet{ | ||
func createClients(name, namespace string, replicas, readyReplicas int32, k8s kubernetes.Interface) error { | ||
clients := appsv1.DaemonSet{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: name, | ||
Namespace: namespace, | ||
|
@@ -322,6 +309,26 @@ func createDaemonset(name, namespace string, replicas, readyReplicas int32, k8s | |
NumberReady: readyReplicas, | ||
}, | ||
} | ||
_, err := k8s.AppsV1().DaemonSets(namespace).Create(context.Background(), &clients, metav1.CreateOptions{}) | ||
return err | ||
} | ||
|
||
func setupCommand(buf io.Writer) *Command { | ||
// Log at a test level to standard out. | ||
log := hclog.New(&hclog.LoggerOptions{ | ||
Name: "test", | ||
Level: hclog.Debug, | ||
Output: os.Stdout, | ||
}) | ||
|
||
// Setup and initialize the command struct | ||
command := &Command{ | ||
BaseCommand: &common.BaseCommand{ | ||
Log: log, | ||
UI: terminal.NewUI(context.Background(), buf), | ||
}, | ||
} | ||
command.init() | ||
|
||
k8s.AppsV1().DaemonSets(namespace).Create(context.Background(), ds, metav1.CreateOptions{}) | ||
return command | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor nit. you could make this a shared func for this and below and pass in:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I appreciate this feedback! I did think about doing that to "DRY" out this function. My thinking with the current way it is written is that one day we will nix the clients check and I don't want an extra function floating around. I think it's nice to just delete the specific lines and not have to change anything else. Once those lines are gone, there won't be any more deduping.
What do you think of that? Am I overthinking it?