From 1c3effafbad1a252770b6e7762442a08c9ad9c7a Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Thu, 23 May 2024 19:04:36 +0200 Subject: [PATCH 01/11] test(e2e): add end to end testing --- e2e_test/combined_test.go | 81 +++++++++ e2e_test/config.toml | 1 + e2e_test/datacenter_test.go | 41 +++++ e2e_test/e2e_test.go | 47 ++++++ e2e_test/firewall_test.go | 278 +++++++++++++++++++++++++++++++ e2e_test/floatingip_test.go | 251 ++++++++++++++++++++++++++++ e2e_test/network_test.go | 220 ++++++++++++++++++++++++ e2e_test/placement_group_test.go | 86 ++++++++++ e2e_test/rules_file.json | 34 ++++ e2e_test/server_test.go | 27 +++ go.mod | 7 + go.sum | 35 ++++ 12 files changed, 1108 insertions(+) create mode 100644 e2e_test/combined_test.go create mode 100644 e2e_test/config.toml create mode 100644 e2e_test/datacenter_test.go create mode 100644 e2e_test/e2e_test.go create mode 100644 e2e_test/firewall_test.go create mode 100644 e2e_test/floatingip_test.go create mode 100644 e2e_test/network_test.go create mode 100644 e2e_test/placement_group_test.go create mode 100644 e2e_test/rules_file.json create mode 100644 e2e_test/server_test.go diff --git a/e2e_test/combined_test.go b/e2e_test/combined_test.go new file mode 100644 index 00000000..55dd16f5 --- /dev/null +++ b/e2e_test/combined_test.go @@ -0,0 +1,81 @@ +package e2e_test + +import ( + "fmt" + "strconv" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCombined(t *testing.T) { + // combined tests combine multiple resources and can thus not be run in parallel + serverID := createServer(t, "test-server", "cpx11", "ubuntu-24.04") + + firewallID, err := createFirewall(t, "test-firewall") + if err != nil { + t.Fatal(err) + } + + out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "server", "--server", "test-server", strconv.Itoa(firewallID)) + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Firewall %d applied to resource\n", firewallID), out) + + out, err = runCommand(t, "firewall", "delete", strconv.Itoa(firewallID)) + assert.Regexp(t, `^firewall with ID [0-9]+ is still in use \(resource_in_use, [0-9a-f]+\)$`, err.Error()) + assert.Empty(t, out) + + out, err = runCommand(t, "firewall", "remove-from-resource", "--type", "server", "--server", "test-server", strconv.Itoa(firewallID)) + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Firewall %d removed from resource\n", firewallID), out) + + out, err = runCommand(t, "firewall", "delete", strconv.Itoa(firewallID)) + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("firewall %d deleted\n", firewallID), out) + + floatingIP, err := createFloatingIP(t, "ipv4", "--server", strconv.Itoa(serverID)) + if err != nil { + t.Fatal(err) + } + + out, err = runCommand(t, "floating-ip", "unassign", strconv.Itoa(floatingIP)) + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Floating IP %d unassigned\n", floatingIP), out) + + out, err = runCommand(t, "floating-ip", "assign", strconv.Itoa(floatingIP), strconv.Itoa(serverID)) + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Floating IP %d assigned to server %d\n", floatingIP, serverID), out) + + out, err = runCommand(t, "floating-ip", "describe", strconv.Itoa(floatingIP)) + assert.NoError(t, err) + assert.Regexp(t, `ID:\s+[0-9]+ +Type:\s+ipv4 +Name:\s+test-floating-ip +Description:\s+- +Created:.*? +IP:\s+(?:[0-9]{1,3}\.){3}[0-9]{1,3} +Blocked:\s+no +Home Location:\s+[a-z]{3}[0-9]+ +Server: +\s+ID:\s+[0-9]+ +\s+Name:\s+test-server +DNS: +.*? +Protection: +\s+Delete:\s+no +Labels: +\s+No labels +`, out) + + out, err = runCommand(t, "floating-ip", "list", "-o", "columns=server", "-o", "noheader") + assert.NoError(t, err) + assert.Equal(t, "test-server\n", out) + + out, err = runCommand(t, "floating-ip", "delete", strconv.Itoa(floatingIP)) + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Floating IP %d deleted\n", floatingIP), out) + + out, err = runCommand(t, "server", "delete", strconv.Itoa(serverID)) + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Server %d deleted\n", serverID), out) +} diff --git a/e2e_test/config.toml b/e2e_test/config.toml new file mode 100644 index 00000000..22c25af7 --- /dev/null +++ b/e2e_test/config.toml @@ -0,0 +1 @@ +# config for tests goes here diff --git a/e2e_test/datacenter_test.go b/e2e_test/datacenter_test.go new file mode 100644 index 00000000..04f6bbe6 --- /dev/null +++ b/e2e_test/datacenter_test.go @@ -0,0 +1,41 @@ +package e2e_test + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestDatacenter(t *testing.T) { + t.Parallel() + + out, err := runCommand(t, "datacenter", "list") + assert.NoError(t, err) + assert.Regexp(t, `ID +NAME +DESCRIPTION +LOCATION +([0-9]+ +[a-z0-9\-]+ +[a-zA-Z0-9\- ]+ +[a-z0-9\-]+\n)+`, out) + + out, err = runCommand(t, "datacenter", "list", "-o=json") + assert.NoError(t, err) + assert.NoError(t, json.Unmarshal([]byte(out), new([]any))) + + out, err = runCommand(t, "datacenter", "describe", "123456") + assert.EqualError(t, err, "datacenter not found: 123456") + assert.Empty(t, out) + + out, err = runCommand(t, "datacenter", "describe", "2") + assert.NoError(t, err) + assert.Regexp(t, `ID:\s+[0-9]+ +Name:\s+[a-z0-9\-]+ +Description:\s+[a-zA-Z0-9\- ]+ +Location: + +Name:\s+[a-z0-9]+ + +Description:\s+[a-zA-Z0-9\- ]+ + +Country:\s+[A-Z]{2} + +City:\s+[A-Za-z]+ + +Latitude:\s+[0-9\.]+ + +Longitude:\s+[0-9\.]+ +Server Types: +(\s+- ID: [0-9]+\s+Name: [a-z0-9]+\s+Supported: (true|false)\s+Available: (true|false))+ +`, out) +} diff --git a/e2e_test/e2e_test.go b/e2e_test/e2e_test.go new file mode 100644 index 00000000..34ce59ca --- /dev/null +++ b/e2e_test/e2e_test.go @@ -0,0 +1,47 @@ +package e2e_test + +import ( + "bytes" + "fmt" + "os" + "testing" + + "github.com/spf13/cobra" + + "github.com/hetznercloud/cli/internal/cli" + "github.com/hetznercloud/cli/internal/state" + "github.com/hetznercloud/cli/internal/state/config" +) + +func TestMain(m *testing.M) { + tok := os.Getenv("HCLOUD_TOKEN") + if tok == "" { + fmt.Println("HCLOUD_TOKEN is not set") + os.Exit(1) + return + } + os.Exit(m.Run()) +} + +func newRootCommand(t *testing.T) *cobra.Command { + cfg := config.New() + if err := cfg.Read("config.toml"); err != nil { + t.Fatalf("unable to read config file \"%s\": %s\n", cfg.Path(), err) + } + + s, err := state.New(cfg) + if err != nil { + t.Fatal(err) + } + + return cli.NewRootCommand(s) +} + +func runCommand(t *testing.T, args ...string) (string, error) { + cmd := newRootCommand(t) + var buf bytes.Buffer + cmd.SetArgs(args) + cmd.SetOut(&buf) + err := cmd.Execute() + return buf.String(), err +} diff --git a/e2e_test/firewall_test.go b/e2e_test/firewall_test.go new file mode 100644 index 00000000..f3239677 --- /dev/null +++ b/e2e_test/firewall_test.go @@ -0,0 +1,278 @@ +package e2e_test + +import ( + "fmt" + "strconv" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFirewall(t *testing.T) { + t.Parallel() + + firewallID, err := createFirewall(t, "test-firewall", "--rules-file", "rules_file.json") + if err != nil { + t.Fatal(err) + } + + out, err := runCommand(t, "firewall", "add-label", "non-existing-firewall", "foo=bar") + assert.EqualError(t, err, "firewall not found: non-existing-firewall") + assert.Empty(t, out) + + out, err = runCommand(t, "firewall", "add-label", strconv.Itoa(firewallID), "foo=bar") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Label(s) foo added to firewall %d\n", firewallID), out) + + out, err = runCommand(t, "firewall", "add-label", strconv.Itoa(firewallID), "baz=qux") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Label(s) baz added to firewall %d\n", firewallID), out) + + out, err = runCommand(t, "firewall", "update", strconv.Itoa(firewallID), "--name", "new-test-firewall") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Firewall %d updated\n", firewallID), out) + + out, err = runCommand(t, "firewall", "remove-label", "new-test-firewall", "baz") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Label(s) baz removed from firewall %d\n", firewallID), out) + + t.Run("add-rule", func(t *testing.T) { + t.Run("missing-args", func(t *testing.T) { + out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID)) + assert.EqualError(t, err, `required flag(s) "direction", "protocol" not set`) + assert.Empty(t, out) + }) + + t.Run("unknown-firewall", func(t *testing.T) { + out, err := runCommand(t, "firewall", "add-rule", "non-existing-firewall", "--direction", "in", "--source-ips", "10.0.0.0/24", "--protocol", "tcp", "--port", "9100") + assert.EqualError(t, err, "Firewall not found: non-existing-firewall") + assert.Empty(t, out) + }) + + t.Run("missing-port", func(t *testing.T) { + out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "in", "--source-ips", "10.0.0.0/24", "--protocol", "tcp", "--description", "Some random description") + assert.EqualError(t, err, "port is required (--port)") + assert.Empty(t, out) + }) + + t.Run("port-not-allowed", func(t *testing.T) { + out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "out", "--destination-ips", "192.168.1.0/24", "--protocol", "icmp", "--port", "12345") + assert.EqualError(t, err, "port is not allowed for this protocol") + assert.Empty(t, out) + }) + + t.Run("invalid-direction", func(t *testing.T) { + out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "foo", "--destination-ips", "192.168.1.0/24", "--protocol", "tcp", "--port", "12345") + assert.EqualError(t, err, "invalid direction: foo") + assert.Empty(t, out) + }) + + t.Run("invalid-protocol", func(t *testing.T) { + out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "out", "--destination-ips", "192.168.1.0/24", "--protocol", "abc", "--port", "12345") + assert.EqualError(t, err, "invalid protocol: abc") + assert.Empty(t, out) + }) + + t.Run("tcp-in", func(t *testing.T) { + out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "in", "--source-ips", "10.0.0.0/24", "--protocol", "tcp", "--port", "9100", "--description", "Some random description") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Firewall Rules for Firewall %d updated\n", firewallID), out) + }) + + t.Run("icmp-out", func(t *testing.T) { + out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "out", "--destination-ips", "192.168.1.0/24", "--protocol", "icmp") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Firewall Rules for Firewall %d updated\n", firewallID), out) + }) + + t.Run("invalid-ip-out", func(t *testing.T) { + out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "out", "--destination-ips", "invalid-ip", "--protocol", "tcp", "--port", "9100") + assert.EqualError(t, err, "destination error on index 0: invalid CIDR address: invalid-ip") + assert.Empty(t, out) + }) + + t.Run("invalid-ip-range-out", func(t *testing.T) { + out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "in", "--source-ips", "10.1.2.3/8", "--protocol", "tcp", "--port", "9100") + assert.EqualError(t, err, "source ips error on index 0: 10.1.2.3/8 is not the start of the cidr block 10.0.0.0/8") + assert.Empty(t, out) + }) + }) + + t.Run("apply-to-resource", func(t *testing.T) { + t.Run("unknown-type", func(t *testing.T) { + out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "non-existing-type", strconv.Itoa(firewallID)) + assert.EqualError(t, err, "unknown type non-existing-type") + assert.Empty(t, out) + }) + t.Run("missing-server", func(t *testing.T) { + out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "server", strconv.Itoa(firewallID)) + assert.EqualError(t, err, "type server need a --server specific") + assert.Empty(t, out) + }) + t.Run("missing-label-selector", func(t *testing.T) { + out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "label_selector", strconv.Itoa(firewallID)) + assert.EqualError(t, err, "type label_selector need a --label-selector specific") + assert.Empty(t, out) + }) + t.Run("unknown-firewall", func(t *testing.T) { + out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "server", "--server", "non-existing-server", "non-existing-firewall") + assert.EqualError(t, err, "Firewall not found: non-existing-firewall") + assert.Empty(t, out) + }) + t.Run("unknown-server", func(t *testing.T) { + out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "server", "--server", "non-existing-server", strconv.Itoa(firewallID)) + assert.EqualError(t, err, "Server not found: non-existing-server") + assert.Empty(t, out) + }) + t.Run("label-selector", func(t *testing.T) { + out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "label_selector", "--label-selector", "foo=bar", strconv.Itoa(firewallID)) + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Firewall %d applied to resource\n", firewallID), out) + }) + }) + + out, err = runCommand(t, "firewall", "describe", strconv.Itoa(firewallID)) + assert.NoError(t, err) + assert.Regexp(t, `ID:\s+[0-9]+ +Name:\s+new-test-firewall +Created:\s+.*? +Labels: +\s+foo: bar +Rules: +\s+- Direction:\s+in +\s+Description:\s+Allow port 80 +\s+Protocol:\s+tcp +\s+Port:\s+80 +\s+Source IPs: +\s+28\.239\.13\.1\/32 +\s+28\.239\.14\.0\/24 +\s+ff21:1eac:9a3b:ee58:5ca:990c:8bc9:c03b\/128 +\s+- Direction:\s+in +\s+Description:\s+Allow port 443 +\s+Protocol:\s+tcp +\s+Port:\s+443 +\s+Source IPs: +\s+0\.0\.0\.0\/0 +\s+::\/0 +\s+- Direction:\s+out +\s+Protocol:\s+tcp +\s+Port:\s+80 +\s+Destination IPs: +\s+28\.239\.13\.1\/32 +\s+28\.239\.14\.0\/24 +\s+ff21:1eac:9a3b:ee58:5ca:990c:8bc9:c03b\/128 +\s+- Direction:\s+in +\s+Description:\s+Some random description +\s+Protocol:\s+tcp +\s+Port:\s+9100 +\s+Source IPs: +\s+10\.0\.0\.0\/24 +\s+- Direction:\s+out +\s+Protocol:\s+icmp +\s+Destination IPs: +\s+192\.168\.1\.0\/24 +Applied To: +\s+- Type:\s+label_selector +\s+Label Selector:\s+foo=bar +`, out) + + t.Run("remove-from-resource", func(t *testing.T) { + t.Run("unknown-type", func(t *testing.T) { + out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "non-existing-type", strconv.Itoa(firewallID)) + assert.EqualError(t, err, "unknown type non-existing-type") + assert.Empty(t, out) + }) + t.Run("missing-server", func(t *testing.T) { + out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "server", strconv.Itoa(firewallID)) + assert.EqualError(t, err, "type server need a --server specific") + assert.Empty(t, out) + }) + t.Run("missing-label-selector", func(t *testing.T) { + out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "label_selector", strconv.Itoa(firewallID)) + assert.EqualError(t, err, "type label_selector need a --label-selector specific") + assert.Empty(t, out) + }) + t.Run("unknown-firewall", func(t *testing.T) { + out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "server", "--server", "non-existing-server", "non-existing-firewall") + assert.EqualError(t, err, "Firewall not found: non-existing-firewall") + assert.Empty(t, out) + }) + t.Run("unknown-server", func(t *testing.T) { + out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "server", "--server", "non-existing-server", strconv.Itoa(firewallID)) + assert.EqualError(t, err, "Server not found: non-existing-server") + assert.Empty(t, out) + }) + t.Run("label-selector", func(t *testing.T) { + out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "label_selector", "--label-selector", "foo=bar", strconv.Itoa(firewallID)) + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Firewall %d removed from resource\n", firewallID), out) + }) + }) + + t.Run("delete-rule", func(t *testing.T) { + t.Run("unknown-firewall", func(t *testing.T) { + out, err := runCommand(t, "firewall", "delete-rule", "non-existing-firewall", "--direction", "in", "--source-ips", "10.0.0.0/24", "--protocol", "tcp", "--port", "9100") + assert.EqualError(t, err, "Firewall not found: non-existing-firewall") + assert.Empty(t, out) + }) + + t.Run("missing-port", func(t *testing.T) { + out, err := runCommand(t, "firewall", "delete-rule", strconv.Itoa(firewallID), "--direction", "in", "--source-ips", "10.0.0.0/24", "--protocol", "tcp") + assert.EqualError(t, err, "port is required (--port)") + assert.Empty(t, out) + }) + + t.Run("port-not-allowed", func(t *testing.T) { + out, err := runCommand(t, "firewall", "delete-rule", strconv.Itoa(firewallID), "--direction", "out", "--destination-ips", "192.168.1.0/24", "--protocol", "icmp", "--port", "12345") + assert.EqualError(t, err, "port is not allowed for this protocol") + assert.Empty(t, out) + }) + + t.Run("tcp-in", func(t *testing.T) { + out, err := runCommand(t, "firewall", "delete-rule", strconv.Itoa(firewallID), "--direction", "in", "--source-ips", "10.0.0.0/24", "--protocol", "tcp", "--port", "9100", "--description", "Some random description") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Firewall Rules for Firewall %d updated\n", firewallID), out) + }) + + t.Run("icmp-out", func(t *testing.T) { + out, err := runCommand(t, "firewall", "delete-rule", strconv.Itoa(firewallID), "--direction", "out", "--destination-ips", "192.168.1.0/24", "--protocol", "icmp") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Firewall Rules for Firewall %d updated\n", firewallID), out) + }) + + t.Run("non-existing-rule", func(t *testing.T) { + out, err := runCommand(t, "firewall", "delete-rule", strconv.Itoa(firewallID), "--direction", "in", "--source-ips", "123.123.123.123/32", "--port", "1234", "--protocol", "tcp") + assert.EqualError(t, err, fmt.Sprintf("the specified rule was not found in the ruleset of Firewall %d", firewallID)) + assert.Empty(t, out) + }) + }) + + out, err = runCommand(t, "firewall", "replace-rules", "non-existing-firewall", "--rules-file", "rules_file.json") + assert.EqualError(t, err, "Firewall not found: non-existing-firewall") + assert.Empty(t, out) + + out, err = runCommand(t, "firewall", "replace-rules", strconv.Itoa(firewallID), "--rules-file", "rules_file.json") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Firewall Rules for Firewall %d updated\n", firewallID), out) + + out, err = runCommand(t, "firewall", "delete", strconv.Itoa(firewallID)) + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("firewall %d deleted\n", firewallID), out) +} + +func createFirewall(t *testing.T, name string, args ...string) (int, error) { + out, err := runCommand(t, append([]string{"firewall", "create", "--name", name}, args...)...) + if err != nil { + return 0, err + } + + if !assert.Regexp(t, `^Firewall [0-9]+ created\n$`, out) { + return 0, fmt.Errorf("invalid response: %s", out) + } + + firewallID, err := strconv.Atoi(out[9 : len(out)-9]) + if err != nil { + return 0, err + } + return firewallID, nil +} diff --git a/e2e_test/floatingip_test.go b/e2e_test/floatingip_test.go new file mode 100644 index 00000000..429720a1 --- /dev/null +++ b/e2e_test/floatingip_test.go @@ -0,0 +1,251 @@ +package e2e_test + +import ( + "fmt" + "net" + "strconv" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/swaggest/assertjson" +) + +func TestFloatingIP(t *testing.T) { + t.Parallel() + + _, err := createFloatingIP(t, "") + assert.EqualError(t, err, "type is required") + + _, err = createFloatingIP(t, "ipv4") + assert.EqualError(t, err, "one of --home-location or --server is required") + + _, err = createFloatingIP(t, "ipv4", "--server", "non-existing-server") + assert.EqualError(t, err, "server not found: non-existing-server") + + floatingIPId, err := createFloatingIP(t, "ipv4", "--home-location", "fsn1") + if err != nil { + t.Fatal(err) + } + + t.Run("labels", func(t *testing.T) { + t.Run("add-label-non-existing-floating-ip", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "add-label", "non-existing-floating-ip", "foo=bar") + assert.EqualError(t, err, "floating IP not found: non-existing-floating-ip") + assert.Empty(t, out) + }) + + t.Run("add-label", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "add-label", strconv.Itoa(floatingIPId), "foo=bar") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Label(s) foo added to Floating IP %d\n", floatingIPId), out) + }) + }) + + out, err := runCommand(t, "floating-ip", "update", strconv.Itoa(floatingIPId), "--name", "new-test-floating-ip", "--description", "Some description") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Floating IP %d updated\n", floatingIPId), out) + + out, err = runCommand(t, "floating-ip", "set-rdns", strconv.Itoa(floatingIPId), "--hostname", "s1.example.com") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Reverse DNS of Floating IP %d changed\n", floatingIPId), out) + + out, err = runCommand(t, "floating-ip", "unassign", "non-existing-floating-ip") + assert.EqualError(t, err, "Floating IP not found: non-existing-floating-ip") + assert.Empty(t, out) + + out, err = runCommand(t, "floating-ip", "assign", "non-existing-floating-ip", "non-existing-server") + assert.EqualError(t, err, "Floating IP not found: non-existing-floating-ip") + assert.Empty(t, out) + + out, err = runCommand(t, "floating-ip", "assign", strconv.Itoa(floatingIPId), "non-existing-server") + assert.EqualError(t, err, "server not found: non-existing-server") + assert.Empty(t, out) + + t.Run("enable-protection", func(t *testing.T) { + t.Run("unknown-protection-level", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "enable-protection", strconv.Itoa(floatingIPId), "unknown-protection-level") + assert.EqualError(t, err, "unknown protection level: unknown-protection-level") + assert.Empty(t, out) + }) + + t.Run("non-existing-floating-ip", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "enable-protection", "non-existing-floating-ip", "delete") + assert.EqualError(t, err, "Floating IP not found: non-existing-floating-ip") + assert.Empty(t, out) + }) + + t.Run("enable-delete-protection", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "enable-protection", strconv.Itoa(floatingIPId), "delete") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Resource protection enabled for floating IP %d\n", floatingIPId), out) + }) + }) + + ipStr, err := runCommand(t, "floating-ip", "describe", strconv.Itoa(floatingIPId), "--output", "format={{.IP}}") + assert.NoError(t, err) + ipStr = strings.TrimSpace(ipStr) + assert.Regexp(t, `^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$`, ipStr) + + out, err = runCommand(t, "floating-ip", "describe", strconv.Itoa(floatingIPId)) + assert.NoError(t, err) + assert.Regexp(t, `ID:\s+[0-9]+ +Type:\s+ipv4 +Name:\s+new-test-floating-ip +Description:\s+Some description +Created:.*? +IP:\s+(?:[0-9]{1,3}\.){3}[0-9]{1,3} +Blocked:\s+no +Home Location:\s+fsn1 +Server: +\s+Not assigned +DNS: +\s+(?:[0-9]{1,3}\.){3}[0-9]{1,3}: s1\.example\.com +Protection: +\s+Delete:\s+yes +Labels: +\s+foo: bar +`, out) + + out, err = runCommand(t, "floating-ip", "list", "--output", "columns=id,name,type,ip,dns,server,home,blocked,protection,labels,created,age") + assert.NoError(t, err) + assert.Regexp(t, `^ID +NAME +TYPE +IP +DNS +SERVER +HOME +BLOCKED +PROTECTION +LABELS +CREATED +AGE +[0-9]+ +new-test-floating-ip +ipv4 +(?:[0-9]{1,3}\.){3}[0-9]{1,3} +s1\.example\.com +- +fsn1 +no +delete +foo=bar.*? +$`, out) + + out, err = runCommand(t, "floating-ip", "list", "-o=json") + assert.NoError(t, err) + assertjson.Equal(t, []byte(fmt.Sprintf(` +[ + { + "id": %d, + "description": "Some description", + "created": "", + "ip": "%s", + "type": "ipv4", + "server": null, + "dns_ptr": [ + { + "ip": "%s", + "dns_ptr": "s1.example.com" + } + ], + "home_location": { + "id": 1, + "name": "fsn1", + "description": "Falkenstein DC Park 1", + "country": "DE", + "city": "Falkenstein", + "latitude": 50.47612, + "longitude": 12.370071, + "network_zone": "eu-central" + }, + "blocked": false, + "protection": { + "delete": true + }, + "labels": { + "foo": "bar" + }, + "name": "new-test-floating-ip" + } +] +`, floatingIPId, ipStr, ipStr)), []byte(out)) + + out, err = runCommand(t, "floating-ip", "delete", strconv.Itoa(floatingIPId)) + assert.Regexp(t, `^Floating IP deletion is protected \(protected, [0-9a-f]+\)$`, err.Error()) + assert.Empty(t, out) + + t.Run("disable-protection", func(t *testing.T) { + t.Run("non-existing-floating-ip", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "disable-protection", "non-existing-floating-ip", "delete") + assert.EqualError(t, err, "Floating IP not found: non-existing-floating-ip") + assert.Empty(t, out) + }) + + t.Run("unknown-protection-level", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "disable-protection", strconv.Itoa(floatingIPId), "unknown-protection-level") + assert.EqualError(t, err, "unknown protection level: unknown-protection-level") + assert.Empty(t, out) + }) + + t.Run("disable-delete-protection", func(t *testing.T) { + out, err = runCommand(t, "floating-ip", "disable-protection", strconv.Itoa(floatingIPId), "delete") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Resource protection disabled for floating IP %d\n", floatingIPId), out) + }) + }) + + out, err = runCommand(t, "floating-ip", "delete", strconv.Itoa(floatingIPId)) + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Floating IP %d deleted\n", floatingIPId), out) + + floatingIPId, err = createFloatingIP(t, "ipv6", "--home-location", "fsn1") + if err != nil { + t.Fatal(err) + } + + out, err = runCommand(t, "floating-ip", "describe", strconv.Itoa(floatingIPId)) + assert.NoError(t, err) + assert.Regexp(t, `ID:\s+[0-9]+ +Type:\s+ipv6 +Name:\s+test-floating-ip +Description:\s+- +Created:.*? +IP:\s+[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+::\/64 +Blocked:\s+no +Home Location:\s+fsn1 +Server: +\s+Not assigned +DNS: +\s+No reverse DNS entries +Protection: +\s+Delete:\s+no +Labels: +\s+No labels +`, out) + + out, err = runCommand(t, "floating-ip", "describe", strconv.Itoa(floatingIPId), "--output", "format={{.IP}}") + assert.NoError(t, err) + out = strings.TrimSpace(out) + ipv6 := net.ParseIP(out) + if ipv6 != nil { + out, err = runCommand(t, "floating-ip", "set-rdns", strconv.Itoa(floatingIPId), "--ip", ipv6.String()+"1", "--hostname", "s1.example.com") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Reverse DNS of Floating IP %d changed\n", floatingIPId), out) + + out, err = runCommand(t, "floating-ip", "set-rdns", strconv.Itoa(floatingIPId), "--ip", ipv6.String()+"2", "--hostname", "s2.example.com") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Reverse DNS of Floating IP %d changed\n", floatingIPId), out) + } else { + t.Errorf("invalid IPv6 address: %s", out) + } + + out, err = runCommand(t, "floating-ip", "list", "-o", "columns=ip,dns") + assert.NoError(t, err) + assert.Regexp(t, fmt.Sprintf(`^IP +DNS +%s\/64 +2 entries +`, ipv6), out) + + out, err = runCommand(t, "floating-ip", "delete", strconv.Itoa(floatingIPId)) + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Floating IP %d deleted\n", floatingIPId), out) +} + +func createFloatingIP(t *testing.T, ipType string, args ...string) (int, error) { + out, err := runCommand(t, append([]string{"floating-ip", "create", "--name", "test-floating-ip", "--type", ipType}, args...)...) + if err != nil { + return 0, err + } + + firstLine := strings.Split(out, "\n")[0] + if !assert.Regexp(t, `^Floating IP [0-9]+ created$`, firstLine) { + return 0, fmt.Errorf("invalid response: %s", out) + } + + id, err := strconv.Atoi(out[12 : len(firstLine)-8]) + if err != nil { + return 0, err + } + return id, nil +} diff --git a/e2e_test/network_test.go b/e2e_test/network_test.go new file mode 100644 index 00000000..b47f21d7 --- /dev/null +++ b/e2e_test/network_test.go @@ -0,0 +1,220 @@ +package e2e_test + +import ( + "fmt" + "strconv" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/swaggest/assertjson" +) + +func TestNetwork(t *testing.T) { + t.Parallel() + + out, err := runCommand(t, "network", "create") + assert.Empty(t, out) + assert.EqualError(t, err, `required flag(s) "ip-range", "name" not set`) + + out, err = runCommand(t, "network", "create", "--name", "test-network", "--ip-range", "10.0.0.0/24") + assert.NoError(t, err) + if !assert.Regexp(t, `^Network [0-9]+ created\n$`, out) { + // network was not created (properly), so there's no need to test it + return + } + + networkID, err := strconv.Atoi(out[8 : len(out)-9]) + assert.NoError(t, err) + + out, err = runCommand(t, "network", "create", "--name", "test-network", "--ip-range", "10.0.1.0/24") + assert.Empty(t, out) + assert.Error(t, err) + assert.Regexp(t, `^name is already used \(uniqueness_error, [0-9a-f]+\)$`, err.Error()) + + out, err = runCommand(t, "network", "enable-protection", strconv.Itoa(networkID), "non-existing-protection") + assert.EqualError(t, err, "unknown protection level: non-existing-protection") + assert.Empty(t, out) + + out, err = runCommand(t, "network", "enable-protection", "non-existing-network", "delete") + assert.EqualError(t, err, "network not found: non-existing-network") + assert.Empty(t, out) + + out, err = runCommand(t, "network", "enable-protection", strconv.Itoa(networkID), "delete") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Resource protection enabled for network %d\n", networkID), out) + + out, err = runCommand(t, "network", "list", "-o=columns=servers,ip_range,labels,protection,created,age") + assert.NoError(t, err) + assert.Regexp(t, `SERVERS +IP RANGE +LABELS +PROTECTION +CREATED +AGE +0 servers +10\.0\.0\.0/24 +delete .*? (?:just now|[0-9]+s) +`, out) + + out, err = runCommand(t, "network", "change-ip-range", "--ip-range", "10.0.2.0/16", "non-existing-network") + assert.EqualError(t, err, "network not found: non-existing-network") + assert.Empty(t, out) + + out, err = runCommand(t, "network", "change-ip-range", "--ip-range", "10.0.2.0/16", "test-network") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("IP range of network %d changed\n", networkID), out) + + out, err = runCommand(t, "network", "add-label", "non-existing-network", "foo=bar") + assert.EqualError(t, err, "network not found: non-existing-network") + assert.Empty(t, out) + + out, err = runCommand(t, "network", "add-label", "test-network", "foo=bar") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Label(s) foo added to Network %d\n", networkID), out) + + out, err = runCommand(t, "network", "add-label", "test-network", "baz=qux") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Label(s) baz added to Network %d\n", networkID), out) + + out, err = runCommand(t, "network", "remove-label", "test-network", "baz") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Label(s) baz removed from Network %d\n", networkID), out) + + out, err = runCommand(t, "network", "update", "test-network", "--name", "new-test-network") + assert.NoError(t, err) + assert.Equal(t, "Network test-network updated\n", out) + + out, err = runCommand(t, "network", "delete", strconv.Itoa(networkID)) + assert.Empty(t, out) + assert.Regexp(t, `^network is delete protected \(protected, [0-9a-f]+\)$`, err.Error()) + + out, err = runCommand(t, "network", "add-subnet", "--type", "cloud", "--network-zone", "eu-central", "--ip-range", "10.0.16.0/24", "non-existing-network") + assert.EqualError(t, err, "network not found: non-existing-network") + assert.Empty(t, out) + + out, err = runCommand(t, "network", "add-subnet", "--type", "vswitch", "--vswitch-id", "42", "--network-zone", "eu-central", "--ip-range", "10.0.17.0/24", strconv.Itoa(networkID)) + assert.Empty(t, out) + assert.Regexp(t, `^vswitch not found \(service_error, [0-9a-f]+\)$`, err.Error()) + + out, err = runCommand(t, "network", "add-subnet", "--type", "cloud", "--network-zone", "eu-central", "--ip-range", "10.0.16.0/24", strconv.Itoa(networkID)) + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Subnet added to network %d\n", networkID), out) + + out, err = runCommand(t, "network", "add-route", "--destination", "10.100.1.0/24", "--gateway", "10.0.1.1", "non-existing-network") + assert.EqualError(t, err, "network not found: non-existing-network") + assert.Empty(t, out) + + out, err = runCommand(t, "network", "add-route", "--destination", "10.100.1.0/24", "--gateway", "10.0.1.1", strconv.Itoa(networkID)) + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Route added to network %d\n", networkID), out) + + out, err = runCommand(t, "network", "expose-routes-to-vswitch", "non-existing-network") + assert.EqualError(t, err, "network not found: non-existing-network") + assert.Empty(t, out) + + out, err = runCommand(t, "network", "expose-routes-to-vswitch", strconv.Itoa(networkID)) + assert.NoError(t, err) + assert.Equal(t, "Exposing routes to connected vSwitch of network new-test-network enabled\n", out) + + out, err = runCommand(t, "network", "describe", strconv.Itoa(networkID)) + assert.NoError(t, err) + assert.Regexp(t, `^ID:\s+[0-9]+ +Name:\s+new-test-network +Created:\s+.*? +IP Range:\s+10\.0\.0\.0\/16 +Expose Routes to vSwitch: yes +Subnets: +\s+- Type:\s+cloud +\s+Network Zone:\s+eu-central +\s+IP Range:\s+10\.0\.16\.0\/24 +\s+Gateway:\s+10\.0\.0\.1 +Routes: +\s+- Destination:\s+10\.100\.1\.0\/24 +\s+Gateway:\s+10\.0\.1\.1 +Protection: +\s+Delete:\s+yes +Labels: +\s+foo: bar +$`, out) + + out, err = runCommand(t, "network", "list", "-o=json") + assert.NoError(t, err) + assertjson.Equal(t, []byte(fmt.Sprintf(` +[ + { + "id": %d, + "name": "new-test-network", + "created": "", + "ip_range": "10.0.0.0/16", + "subnets": [ + { + "type": "cloud", + "ip_range": "10.0.16.0/24", + "network_zone": "eu-central", + "gateway": "10.0.0.1" + } + ], + "routes": [ + { + "destination": "10.100.1.0/24", + "gateway": "10.0.1.1" + } + ], + "servers": [], + "protection": { + "delete": true + }, + "labels": { + "foo": "bar" + }, + "expose_routes_to_vswitch": true + } +] +`, networkID)), []byte(out)) + + out, err = runCommand(t, "network", "remove-route", "--destination", "10.100.1.0/24", "--gateway", "10.0.1.1", "non-existing-network") + assert.EqualError(t, err, "network not found: non-existing-network") + assert.Empty(t, out) + + out, err = runCommand(t, "network", "remove-route", "--destination", "10.100.1.0/24", "--gateway", "10.0.1.1", strconv.Itoa(networkID)) + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Route removed from network %d\n", networkID), out) + + out, err = runCommand(t, "network", "remove-subnet", "--ip-range", "10.0.16.0/24", "non-existing-network") + assert.EqualError(t, err, "network not found: non-existing-network") + assert.Empty(t, out) + + out, err = runCommand(t, "network", "remove-subnet", "--ip-range", "10.0.16.0/24", strconv.Itoa(networkID)) + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Subnet 10.0.16.0/24 removed from network %d\n", networkID), out) + + out, err = runCommand(t, "network", "disable-protection", "non-existing-network", "delete") + assert.EqualError(t, err, "network not found: non-existing-network") + assert.Empty(t, out) + + out, err = runCommand(t, "network", "disable-protection", strconv.Itoa(networkID), "delete") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Resource protection disabled for network %d\n", networkID), out) + + out, err = runCommand(t, "network", "remove-label", strconv.Itoa(networkID), "foo") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Label(s) foo removed from Network %d\n", networkID), out) + + out, err = runCommand(t, "network", "expose-routes-to-vswitch", "--disable", strconv.Itoa(networkID)) + assert.NoError(t, err) + assert.Equal(t, "Exposing routes to connected vSwitch of network new-test-network disabled\n", out) + + out, err = runCommand(t, "network", "describe", strconv.Itoa(networkID)) + assert.NoError(t, err) + assert.Regexp(t, `^ID:\s+[0-9]+ +Name:\s+new-test-network +Created:\s+.*? +IP Range:\s+10\.0\.0\.0\/16 +Expose Routes to vSwitch: no +Subnets: +\s+No subnets +Routes: +\s+No routes +Protection: +\s+Delete:\s+no +Labels: +\s+No labels +$`, out) + + out, err = runCommand(t, "network", "delete", strconv.Itoa(networkID)) + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Network %d deleted\n", networkID), out) +} diff --git a/e2e_test/placement_group_test.go b/e2e_test/placement_group_test.go new file mode 100644 index 00000000..714b6515 --- /dev/null +++ b/e2e_test/placement_group_test.go @@ -0,0 +1,86 @@ +package e2e_test + +import ( + "fmt" + "strconv" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/swaggest/assertjson" +) + +func TestPlacementGroup(t *testing.T) { + t.Parallel() + + out, err := runCommand(t, "placement-group", "create") + assert.Empty(t, out) + assert.EqualError(t, err, `required flag(s) "name", "type" not set`) + + out, err = runCommand(t, "placement-group", "create", "--name", "test-placement-group", "--type", "spread") + assert.NoError(t, err) + if !assert.Regexp(t, `^Placement group [0-9]+ created\n$`, out) { + return + } + + pgID, err := strconv.Atoi(out[16 : len(out)-9]) + assert.NoError(t, err) + + out, err = runCommand(t, "placement-group", "add-label", "non-existing-placement-group", "foo=bar") + assert.EqualError(t, err, "placement group not found: non-existing-placement-group") + assert.Empty(t, out) + + out, err = runCommand(t, "placement-group", "add-label", "test-placement-group", "foo=bar") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Label(s) foo added to placement group %d\n", pgID), out) + + out, err = runCommand(t, "placement-group", "add-label", "test-placement-group", "baz=qux") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Label(s) baz added to placement group %d\n", pgID), out) + + out, err = runCommand(t, "placement-group", "update", "test-placement-group", "--name", "new-test-placement-group") + assert.NoError(t, err) + assert.Equal(t, "placement group test-placement-group updated\n", out) + + out, err = runCommand(t, "placement-group", "list", "-o=columns=id,name,servers,type,created,age") + assert.NoError(t, err) + assert.Regexp(t, `ID +NAME +SERVERS +TYPE +CREATED +AGE +[0-9]+ +new-test-placement-group +0 servers +spread .*? (?:just now|[0-9]+s) +`, out) + + out, err = runCommand(t, "placement-group", "describe", strconv.Itoa(pgID)) + assert.NoError(t, err) + assert.Regexp(t, `^ID:\s+[0-9]+ +Name:\s+new-test-placement-group +Created:\s+.*? +Labels: +\s+(baz: qux|foo: bar) +\s+(baz: qux|foo: bar) +Servers: +Type:\s+spread +$`, out) + + out, err = runCommand(t, "placement-group", "list", "-o=json") + assert.NoError(t, err) + assertjson.Equal(t, []byte(fmt.Sprintf(` +[ + { + "id": %d, + "name": "new-test-placement-group", + "labels": { + "baz": "qux", + "foo": "bar" + }, + "created": "", + "servers": [], + "type": "spread" + } +]`, pgID)), []byte(out)) + + out, err = runCommand(t, "placement-group", "remove-label", "new-test-placement-group", "baz") + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Label(s) baz removed from placement group %d\n", pgID), out) + + out, err = runCommand(t, "placement-group", "delete", strconv.Itoa(pgID)) + assert.NoError(t, err) + assert.Equal(t, fmt.Sprintf("placement group %d deleted\n", pgID), out) +} diff --git a/e2e_test/rules_file.json b/e2e_test/rules_file.json new file mode 100644 index 00000000..3b9e3829 --- /dev/null +++ b/e2e_test/rules_file.json @@ -0,0 +1,34 @@ +[ + { + "description": "Allow port 80", + "direction": "in", + "port": "80", + "protocol": "tcp", + "source_ips": [ + "28.239.13.1/32", + "28.239.14.0/24", + "ff21:1eac:9a3b:ee58:5ca:990c:8bc9:c03b/128" + ] + }, + { + "description": "Allow port 443", + "direction": "in", + "port": "443", + "protocol": "tcp", + "source_ips": [ + "0.0.0.0/0", + "::/0" + ] + }, + { + "direction": "out", + "source_ips": [], + "destination_ips": [ + "28.239.13.1/32", + "28.239.14.0/24", + "ff21:1eac:9a3b:ee58:5ca:990c:8bc9:c03b/128" + ], + "protocol": "tcp", + "port": "80" + } +] diff --git a/e2e_test/server_test.go b/e2e_test/server_test.go new file mode 100644 index 00000000..37e164f8 --- /dev/null +++ b/e2e_test/server_test.go @@ -0,0 +1,27 @@ +package e2e_test + +import ( + "strconv" + "strings" + "testing" + + "github.com/stretchr/testify/assert" +) + +func createServer(t *testing.T, name, serverType, image string, args ...string) int { + out, err := runCommand(t, append([]string{"server", "create", "--name", name, "--type", serverType, "--image", image}, args...)...) + if err != nil { + t.Fatal(err) + } + + firstLine := strings.Split(out, "\n")[0] + if !assert.Regexp(t, `^Server [0-9]+ created$`, firstLine) { + t.Fatalf("invalid response: %s", out) + } + + serverID, err := strconv.Atoi(out[7 : len(firstLine)-8]) + if err != nil { + t.Fatal(err) + } + return serverID +} diff --git a/go.mod b/go.mod index d25358bf..2e821532 100644 --- a/go.mod +++ b/go.mod @@ -21,6 +21,7 @@ require ( github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.9.0 + github.com/swaggest/assertjson v1.9.0 golang.org/x/crypto v0.27.0 golang.org/x/term v0.24.0 ) @@ -28,16 +29,19 @@ require ( require ( github.com/VividCortex/ewma v1.2.0 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/bool64/shared v0.1.5 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/iancoleman/orderedmap v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/nxadm/tail v1.4.11 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.19.1 // indirect @@ -47,9 +51,12 @@ require ( github.com/rivo/uniseg v0.2.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sergi/go-diff v1.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect + github.com/yudai/gojsondiff v1.0.0 // indirect + github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect diff --git a/go.sum b/go.sum index 43a61a79..4fe44263 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,10 @@ github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1o github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bool64/dev v0.2.29 h1:x+syGyh+0eWtOzQ1ItvLzOGIWyNWnyjXpHIcpF2HvL4= +github.com/bool64/dev v0.2.29/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= +github.com/bool64/shared v0.1.5 h1:fp3eUhBsrSjNCQPcSdQqZxxh9bBwrYiZ+zOKFkM0/2E= +github.com/bool64/shared v0.1.5/go.mod h1:081yz68YC9jeFB3+Bbmno2RFWvGKv1lPKkMP6MHJlPs= github.com/boumenot/gocover-cobertura v1.2.0 h1:g+VROIASoEHBrEilIyaCmgo7HGm+AV5yKEPLk0qIY+s= github.com/boumenot/gocover-cobertura v1.2.0/go.mod h1:fz7ly8dslE42VRR5ZWLt2OHGDHjkTiA2oNvKgJEjLT0= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= @@ -23,6 +27,7 @@ github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= @@ -43,12 +48,17 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hetznercloud/hcloud-go/v2 v2.13.1 h1:jq0GP4QaYE5d8xR/Zw17s9qoaESRJMXfGmtD1a/qckQ= github.com/hetznercloud/hcloud-go/v2 v2.13.1/go.mod h1:dhix40Br3fDiBhwaSG/zgaYOFFddpfBm/6R1Zz0IiF0= +github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc= +github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jedib0t/go-pretty/v6 v6.5.9 h1:ACteMBRrrmm1gMsXe9PSTOClQ63IXDUt03H5U+UV8OU= github.com/jedib0t/go-pretty/v6 v6.5.9/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= @@ -64,6 +74,12 @@ github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZ github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= +github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= +github.com/onsi/ginkgo v1.15.2 h1:l77YT15o814C2qVL47NOyjV/6RbaP7kKdrvZnxQ3Org= +github.com/onsi/ginkgo v1.15.2/go.mod h1:Dd6YFfwBW84ETqqtL0CPyPXillHgY6XhQH3uuCCTr/o= +github.com/onsi/gomega v1.11.0 h1:+CqWgvj0OZycCaqclBD1pxKHAU+tOkHmQIWvDHq2aug= +github.com/onsi/gomega v1.11.0/go.mod h1:azGKhqFUon9Vuj0YmTfLSmx0FUwqXYSTl5re8lQLTUg= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -86,6 +102,8 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= @@ -103,6 +121,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -111,6 +130,14 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/swaggest/assertjson v1.9.0 h1:dKu0BfJkIxv/xe//mkCrK5yZbs79jL7OVf9Ija7o2xQ= +github.com/swaggest/assertjson v1.9.0/go.mod h1:b+ZKX2VRiUjxfUIal0HDN85W0nHPAYUbYH5WkkSsFsU= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI= +github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= @@ -144,6 +171,7 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= @@ -169,10 +197,17 @@ golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6f google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From bddbb1b5203f77bd120599eb821516fc55d9ce89 Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Thu, 11 Jul 2024 14:06:29 +0200 Subject: [PATCH 02/11] ci: add tps action to get HCLOUD_TOKEN --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f78e9a50..e7ca7965 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,6 +33,8 @@ jobs: test: runs-on: ubuntu-latest + permissions: + id-token: write steps: - name: Checkout uses: actions/checkout@v4 @@ -42,6 +44,8 @@ jobs: with: go-version: "1.23" + - uses: hetznercloud/tps-action@main + - name: Run tests run: go test -coverpkg=./... -coverprofile=coverage.txt -v -race ./... From 66ea9556bc58692a4b339ee61b14d13a6cdd43ea Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Thu, 12 Sep 2024 14:37:31 +0200 Subject: [PATCH 03/11] fix lint --- e2e_test/combined_test.go | 19 ++++---- e2e_test/datacenter_test.go | 11 ++--- e2e_test/firewall_test.go | 75 ++++++++++++++++---------------- e2e_test/floatingip_test.go | 55 +++++++++++------------ e2e_test/network_test.go | 67 ++++++++++++++-------------- e2e_test/placement_group_test.go | 25 ++++++----- 6 files changed, 129 insertions(+), 123 deletions(-) diff --git a/e2e_test/combined_test.go b/e2e_test/combined_test.go index 55dd16f5..d9c56944 100644 --- a/e2e_test/combined_test.go +++ b/e2e_test/combined_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestCombined(t *testing.T) { @@ -18,7 +19,7 @@ func TestCombined(t *testing.T) { } out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "server", "--server", "test-server", strconv.Itoa(firewallID)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Firewall %d applied to resource\n", firewallID), out) out, err = runCommand(t, "firewall", "delete", strconv.Itoa(firewallID)) @@ -26,11 +27,11 @@ func TestCombined(t *testing.T) { assert.Empty(t, out) out, err = runCommand(t, "firewall", "remove-from-resource", "--type", "server", "--server", "test-server", strconv.Itoa(firewallID)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Firewall %d removed from resource\n", firewallID), out) out, err = runCommand(t, "firewall", "delete", strconv.Itoa(firewallID)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("firewall %d deleted\n", firewallID), out) floatingIP, err := createFloatingIP(t, "ipv4", "--server", strconv.Itoa(serverID)) @@ -39,15 +40,15 @@ func TestCombined(t *testing.T) { } out, err = runCommand(t, "floating-ip", "unassign", strconv.Itoa(floatingIP)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Floating IP %d unassigned\n", floatingIP), out) out, err = runCommand(t, "floating-ip", "assign", strconv.Itoa(floatingIP), strconv.Itoa(serverID)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Floating IP %d assigned to server %d\n", floatingIP, serverID), out) out, err = runCommand(t, "floating-ip", "describe", strconv.Itoa(floatingIP)) - assert.NoError(t, err) + require.NoError(t, err) assert.Regexp(t, `ID:\s+[0-9]+ Type:\s+ipv4 Name:\s+test-floating-ip @@ -68,14 +69,14 @@ Labels: `, out) out, err = runCommand(t, "floating-ip", "list", "-o", "columns=server", "-o", "noheader") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "test-server\n", out) out, err = runCommand(t, "floating-ip", "delete", strconv.Itoa(floatingIP)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Floating IP %d deleted\n", floatingIP), out) out, err = runCommand(t, "server", "delete", strconv.Itoa(serverID)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Server %d deleted\n", serverID), out) } diff --git a/e2e_test/datacenter_test.go b/e2e_test/datacenter_test.go index 04f6bbe6..d3dcdf3b 100644 --- a/e2e_test/datacenter_test.go +++ b/e2e_test/datacenter_test.go @@ -5,26 +5,27 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestDatacenter(t *testing.T) { t.Parallel() out, err := runCommand(t, "datacenter", "list") - assert.NoError(t, err) + require.NoError(t, err) assert.Regexp(t, `ID +NAME +DESCRIPTION +LOCATION ([0-9]+ +[a-z0-9\-]+ +[a-zA-Z0-9\- ]+ +[a-z0-9\-]+\n)+`, out) out, err = runCommand(t, "datacenter", "list", "-o=json") - assert.NoError(t, err) - assert.NoError(t, json.Unmarshal([]byte(out), new([]any))) + require.NoError(t, err) + require.NoError(t, json.Unmarshal([]byte(out), new([]any))) out, err = runCommand(t, "datacenter", "describe", "123456") - assert.EqualError(t, err, "datacenter not found: 123456") + require.EqualError(t, err, "datacenter not found: 123456") assert.Empty(t, out) out, err = runCommand(t, "datacenter", "describe", "2") - assert.NoError(t, err) + require.NoError(t, err) assert.Regexp(t, `ID:\s+[0-9]+ Name:\s+[a-z0-9\-]+ Description:\s+[a-zA-Z0-9\- ]+ diff --git a/e2e_test/firewall_test.go b/e2e_test/firewall_test.go index f3239677..3ac36d99 100644 --- a/e2e_test/firewall_test.go +++ b/e2e_test/firewall_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestFirewall(t *testing.T) { @@ -17,83 +18,83 @@ func TestFirewall(t *testing.T) { } out, err := runCommand(t, "firewall", "add-label", "non-existing-firewall", "foo=bar") - assert.EqualError(t, err, "firewall not found: non-existing-firewall") + require.EqualError(t, err, "firewall not found: non-existing-firewall") assert.Empty(t, out) out, err = runCommand(t, "firewall", "add-label", strconv.Itoa(firewallID), "foo=bar") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) foo added to firewall %d\n", firewallID), out) out, err = runCommand(t, "firewall", "add-label", strconv.Itoa(firewallID), "baz=qux") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) baz added to firewall %d\n", firewallID), out) out, err = runCommand(t, "firewall", "update", strconv.Itoa(firewallID), "--name", "new-test-firewall") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Firewall %d updated\n", firewallID), out) out, err = runCommand(t, "firewall", "remove-label", "new-test-firewall", "baz") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) baz removed from firewall %d\n", firewallID), out) t.Run("add-rule", func(t *testing.T) { t.Run("missing-args", func(t *testing.T) { out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID)) - assert.EqualError(t, err, `required flag(s) "direction", "protocol" not set`) + require.EqualError(t, err, `required flag(s) "direction", "protocol" not set`) assert.Empty(t, out) }) t.Run("unknown-firewall", func(t *testing.T) { out, err := runCommand(t, "firewall", "add-rule", "non-existing-firewall", "--direction", "in", "--source-ips", "10.0.0.0/24", "--protocol", "tcp", "--port", "9100") - assert.EqualError(t, err, "Firewall not found: non-existing-firewall") + require.EqualError(t, err, "Firewall not found: non-existing-firewall") assert.Empty(t, out) }) t.Run("missing-port", func(t *testing.T) { out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "in", "--source-ips", "10.0.0.0/24", "--protocol", "tcp", "--description", "Some random description") - assert.EqualError(t, err, "port is required (--port)") + require.EqualError(t, err, "port is required (--port)") assert.Empty(t, out) }) t.Run("port-not-allowed", func(t *testing.T) { out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "out", "--destination-ips", "192.168.1.0/24", "--protocol", "icmp", "--port", "12345") - assert.EqualError(t, err, "port is not allowed for this protocol") + require.EqualError(t, err, "port is not allowed for this protocol") assert.Empty(t, out) }) t.Run("invalid-direction", func(t *testing.T) { out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "foo", "--destination-ips", "192.168.1.0/24", "--protocol", "tcp", "--port", "12345") - assert.EqualError(t, err, "invalid direction: foo") + require.EqualError(t, err, "invalid direction: foo") assert.Empty(t, out) }) t.Run("invalid-protocol", func(t *testing.T) { out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "out", "--destination-ips", "192.168.1.0/24", "--protocol", "abc", "--port", "12345") - assert.EqualError(t, err, "invalid protocol: abc") + require.EqualError(t, err, "invalid protocol: abc") assert.Empty(t, out) }) t.Run("tcp-in", func(t *testing.T) { out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "in", "--source-ips", "10.0.0.0/24", "--protocol", "tcp", "--port", "9100", "--description", "Some random description") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Firewall Rules for Firewall %d updated\n", firewallID), out) }) t.Run("icmp-out", func(t *testing.T) { out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "out", "--destination-ips", "192.168.1.0/24", "--protocol", "icmp") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Firewall Rules for Firewall %d updated\n", firewallID), out) }) t.Run("invalid-ip-out", func(t *testing.T) { out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "out", "--destination-ips", "invalid-ip", "--protocol", "tcp", "--port", "9100") - assert.EqualError(t, err, "destination error on index 0: invalid CIDR address: invalid-ip") + require.EqualError(t, err, "destination error on index 0: invalid CIDR address: invalid-ip") assert.Empty(t, out) }) t.Run("invalid-ip-range-out", func(t *testing.T) { out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "in", "--source-ips", "10.1.2.3/8", "--protocol", "tcp", "--port", "9100") - assert.EqualError(t, err, "source ips error on index 0: 10.1.2.3/8 is not the start of the cidr block 10.0.0.0/8") + require.EqualError(t, err, "source ips error on index 0: 10.1.2.3/8 is not the start of the cidr block 10.0.0.0/8") assert.Empty(t, out) }) }) @@ -101,38 +102,38 @@ func TestFirewall(t *testing.T) { t.Run("apply-to-resource", func(t *testing.T) { t.Run("unknown-type", func(t *testing.T) { out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "non-existing-type", strconv.Itoa(firewallID)) - assert.EqualError(t, err, "unknown type non-existing-type") + require.EqualError(t, err, "unknown type non-existing-type") assert.Empty(t, out) }) t.Run("missing-server", func(t *testing.T) { out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "server", strconv.Itoa(firewallID)) - assert.EqualError(t, err, "type server need a --server specific") + require.EqualError(t, err, "type server need a --server specific") assert.Empty(t, out) }) t.Run("missing-label-selector", func(t *testing.T) { out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "label_selector", strconv.Itoa(firewallID)) - assert.EqualError(t, err, "type label_selector need a --label-selector specific") + require.EqualError(t, err, "type label_selector need a --label-selector specific") assert.Empty(t, out) }) t.Run("unknown-firewall", func(t *testing.T) { out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "server", "--server", "non-existing-server", "non-existing-firewall") - assert.EqualError(t, err, "Firewall not found: non-existing-firewall") + require.EqualError(t, err, "Firewall not found: non-existing-firewall") assert.Empty(t, out) }) t.Run("unknown-server", func(t *testing.T) { out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "server", "--server", "non-existing-server", strconv.Itoa(firewallID)) - assert.EqualError(t, err, "Server not found: non-existing-server") + require.EqualError(t, err, "Server not found: non-existing-server") assert.Empty(t, out) }) t.Run("label-selector", func(t *testing.T) { out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "label_selector", "--label-selector", "foo=bar", strconv.Itoa(firewallID)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Firewall %d applied to resource\n", firewallID), out) }) }) out, err = runCommand(t, "firewall", "describe", strconv.Itoa(firewallID)) - assert.NoError(t, err) + require.NoError(t, err) assert.Regexp(t, `ID:\s+[0-9]+ Name:\s+new-test-firewall Created:\s+.*? @@ -179,32 +180,32 @@ Applied To: t.Run("remove-from-resource", func(t *testing.T) { t.Run("unknown-type", func(t *testing.T) { out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "non-existing-type", strconv.Itoa(firewallID)) - assert.EqualError(t, err, "unknown type non-existing-type") + require.EqualError(t, err, "unknown type non-existing-type") assert.Empty(t, out) }) t.Run("missing-server", func(t *testing.T) { out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "server", strconv.Itoa(firewallID)) - assert.EqualError(t, err, "type server need a --server specific") + require.EqualError(t, err, "type server need a --server specific") assert.Empty(t, out) }) t.Run("missing-label-selector", func(t *testing.T) { out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "label_selector", strconv.Itoa(firewallID)) - assert.EqualError(t, err, "type label_selector need a --label-selector specific") + require.EqualError(t, err, "type label_selector need a --label-selector specific") assert.Empty(t, out) }) t.Run("unknown-firewall", func(t *testing.T) { out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "server", "--server", "non-existing-server", "non-existing-firewall") - assert.EqualError(t, err, "Firewall not found: non-existing-firewall") + require.EqualError(t, err, "Firewall not found: non-existing-firewall") assert.Empty(t, out) }) t.Run("unknown-server", func(t *testing.T) { out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "server", "--server", "non-existing-server", strconv.Itoa(firewallID)) - assert.EqualError(t, err, "Server not found: non-existing-server") + require.EqualError(t, err, "Server not found: non-existing-server") assert.Empty(t, out) }) t.Run("label-selector", func(t *testing.T) { out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "label_selector", "--label-selector", "foo=bar", strconv.Itoa(firewallID)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Firewall %d removed from resource\n", firewallID), out) }) }) @@ -212,51 +213,51 @@ Applied To: t.Run("delete-rule", func(t *testing.T) { t.Run("unknown-firewall", func(t *testing.T) { out, err := runCommand(t, "firewall", "delete-rule", "non-existing-firewall", "--direction", "in", "--source-ips", "10.0.0.0/24", "--protocol", "tcp", "--port", "9100") - assert.EqualError(t, err, "Firewall not found: non-existing-firewall") + require.EqualError(t, err, "Firewall not found: non-existing-firewall") assert.Empty(t, out) }) t.Run("missing-port", func(t *testing.T) { out, err := runCommand(t, "firewall", "delete-rule", strconv.Itoa(firewallID), "--direction", "in", "--source-ips", "10.0.0.0/24", "--protocol", "tcp") - assert.EqualError(t, err, "port is required (--port)") + require.EqualError(t, err, "port is required (--port)") assert.Empty(t, out) }) t.Run("port-not-allowed", func(t *testing.T) { out, err := runCommand(t, "firewall", "delete-rule", strconv.Itoa(firewallID), "--direction", "out", "--destination-ips", "192.168.1.0/24", "--protocol", "icmp", "--port", "12345") - assert.EqualError(t, err, "port is not allowed for this protocol") + require.EqualError(t, err, "port is not allowed for this protocol") assert.Empty(t, out) }) t.Run("tcp-in", func(t *testing.T) { out, err := runCommand(t, "firewall", "delete-rule", strconv.Itoa(firewallID), "--direction", "in", "--source-ips", "10.0.0.0/24", "--protocol", "tcp", "--port", "9100", "--description", "Some random description") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Firewall Rules for Firewall %d updated\n", firewallID), out) }) t.Run("icmp-out", func(t *testing.T) { out, err := runCommand(t, "firewall", "delete-rule", strconv.Itoa(firewallID), "--direction", "out", "--destination-ips", "192.168.1.0/24", "--protocol", "icmp") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Firewall Rules for Firewall %d updated\n", firewallID), out) }) t.Run("non-existing-rule", func(t *testing.T) { out, err := runCommand(t, "firewall", "delete-rule", strconv.Itoa(firewallID), "--direction", "in", "--source-ips", "123.123.123.123/32", "--port", "1234", "--protocol", "tcp") - assert.EqualError(t, err, fmt.Sprintf("the specified rule was not found in the ruleset of Firewall %d", firewallID)) + require.EqualError(t, err, fmt.Sprintf("the specified rule was not found in the ruleset of Firewall %d", firewallID)) assert.Empty(t, out) }) }) out, err = runCommand(t, "firewall", "replace-rules", "non-existing-firewall", "--rules-file", "rules_file.json") - assert.EqualError(t, err, "Firewall not found: non-existing-firewall") + require.EqualError(t, err, "Firewall not found: non-existing-firewall") assert.Empty(t, out) out, err = runCommand(t, "firewall", "replace-rules", strconv.Itoa(firewallID), "--rules-file", "rules_file.json") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Firewall Rules for Firewall %d updated\n", firewallID), out) out, err = runCommand(t, "firewall", "delete", strconv.Itoa(firewallID)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("firewall %d deleted\n", firewallID), out) } diff --git a/e2e_test/floatingip_test.go b/e2e_test/floatingip_test.go index 429720a1..63dcde24 100644 --- a/e2e_test/floatingip_test.go +++ b/e2e_test/floatingip_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/swaggest/assertjson" ) @@ -15,13 +16,13 @@ func TestFloatingIP(t *testing.T) { t.Parallel() _, err := createFloatingIP(t, "") - assert.EqualError(t, err, "type is required") + require.EqualError(t, err, "type is required") _, err = createFloatingIP(t, "ipv4") - assert.EqualError(t, err, "one of --home-location or --server is required") + require.EqualError(t, err, "one of --home-location or --server is required") _, err = createFloatingIP(t, "ipv4", "--server", "non-existing-server") - assert.EqualError(t, err, "server not found: non-existing-server") + require.EqualError(t, err, "server not found: non-existing-server") floatingIPId, err := createFloatingIP(t, "ipv4", "--home-location", "fsn1") if err != nil { @@ -31,64 +32,64 @@ func TestFloatingIP(t *testing.T) { t.Run("labels", func(t *testing.T) { t.Run("add-label-non-existing-floating-ip", func(t *testing.T) { out, err := runCommand(t, "floating-ip", "add-label", "non-existing-floating-ip", "foo=bar") - assert.EqualError(t, err, "floating IP not found: non-existing-floating-ip") + require.EqualError(t, err, "floating IP not found: non-existing-floating-ip") assert.Empty(t, out) }) t.Run("add-label", func(t *testing.T) { out, err := runCommand(t, "floating-ip", "add-label", strconv.Itoa(floatingIPId), "foo=bar") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) foo added to Floating IP %d\n", floatingIPId), out) }) }) out, err := runCommand(t, "floating-ip", "update", strconv.Itoa(floatingIPId), "--name", "new-test-floating-ip", "--description", "Some description") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Floating IP %d updated\n", floatingIPId), out) out, err = runCommand(t, "floating-ip", "set-rdns", strconv.Itoa(floatingIPId), "--hostname", "s1.example.com") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Reverse DNS of Floating IP %d changed\n", floatingIPId), out) out, err = runCommand(t, "floating-ip", "unassign", "non-existing-floating-ip") - assert.EqualError(t, err, "Floating IP not found: non-existing-floating-ip") + require.EqualError(t, err, "Floating IP not found: non-existing-floating-ip") assert.Empty(t, out) out, err = runCommand(t, "floating-ip", "assign", "non-existing-floating-ip", "non-existing-server") - assert.EqualError(t, err, "Floating IP not found: non-existing-floating-ip") + require.EqualError(t, err, "Floating IP not found: non-existing-floating-ip") assert.Empty(t, out) out, err = runCommand(t, "floating-ip", "assign", strconv.Itoa(floatingIPId), "non-existing-server") - assert.EqualError(t, err, "server not found: non-existing-server") + require.EqualError(t, err, "server not found: non-existing-server") assert.Empty(t, out) t.Run("enable-protection", func(t *testing.T) { t.Run("unknown-protection-level", func(t *testing.T) { out, err := runCommand(t, "floating-ip", "enable-protection", strconv.Itoa(floatingIPId), "unknown-protection-level") - assert.EqualError(t, err, "unknown protection level: unknown-protection-level") + require.EqualError(t, err, "unknown protection level: unknown-protection-level") assert.Empty(t, out) }) t.Run("non-existing-floating-ip", func(t *testing.T) { out, err := runCommand(t, "floating-ip", "enable-protection", "non-existing-floating-ip", "delete") - assert.EqualError(t, err, "Floating IP not found: non-existing-floating-ip") + require.EqualError(t, err, "Floating IP not found: non-existing-floating-ip") assert.Empty(t, out) }) t.Run("enable-delete-protection", func(t *testing.T) { out, err := runCommand(t, "floating-ip", "enable-protection", strconv.Itoa(floatingIPId), "delete") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Resource protection enabled for floating IP %d\n", floatingIPId), out) }) }) ipStr, err := runCommand(t, "floating-ip", "describe", strconv.Itoa(floatingIPId), "--output", "format={{.IP}}") - assert.NoError(t, err) + require.NoError(t, err) ipStr = strings.TrimSpace(ipStr) assert.Regexp(t, `^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$`, ipStr) out, err = runCommand(t, "floating-ip", "describe", strconv.Itoa(floatingIPId)) - assert.NoError(t, err) + require.NoError(t, err) assert.Regexp(t, `ID:\s+[0-9]+ Type:\s+ipv4 Name:\s+new-test-floating-ip @@ -108,13 +109,13 @@ Labels: `, out) out, err = runCommand(t, "floating-ip", "list", "--output", "columns=id,name,type,ip,dns,server,home,blocked,protection,labels,created,age") - assert.NoError(t, err) + require.NoError(t, err) assert.Regexp(t, `^ID +NAME +TYPE +IP +DNS +SERVER +HOME +BLOCKED +PROTECTION +LABELS +CREATED +AGE [0-9]+ +new-test-floating-ip +ipv4 +(?:[0-9]{1,3}\.){3}[0-9]{1,3} +s1\.example\.com +- +fsn1 +no +delete +foo=bar.*? $`, out) out, err = runCommand(t, "floating-ip", "list", "-o=json") - assert.NoError(t, err) + require.NoError(t, err) assertjson.Equal(t, []byte(fmt.Sprintf(` [ { @@ -159,25 +160,25 @@ $`, out) t.Run("disable-protection", func(t *testing.T) { t.Run("non-existing-floating-ip", func(t *testing.T) { out, err := runCommand(t, "floating-ip", "disable-protection", "non-existing-floating-ip", "delete") - assert.EqualError(t, err, "Floating IP not found: non-existing-floating-ip") + require.EqualError(t, err, "Floating IP not found: non-existing-floating-ip") assert.Empty(t, out) }) t.Run("unknown-protection-level", func(t *testing.T) { out, err := runCommand(t, "floating-ip", "disable-protection", strconv.Itoa(floatingIPId), "unknown-protection-level") - assert.EqualError(t, err, "unknown protection level: unknown-protection-level") + require.EqualError(t, err, "unknown protection level: unknown-protection-level") assert.Empty(t, out) }) t.Run("disable-delete-protection", func(t *testing.T) { out, err = runCommand(t, "floating-ip", "disable-protection", strconv.Itoa(floatingIPId), "delete") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Resource protection disabled for floating IP %d\n", floatingIPId), out) }) }) out, err = runCommand(t, "floating-ip", "delete", strconv.Itoa(floatingIPId)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Floating IP %d deleted\n", floatingIPId), out) floatingIPId, err = createFloatingIP(t, "ipv6", "--home-location", "fsn1") @@ -186,7 +187,7 @@ $`, out) } out, err = runCommand(t, "floating-ip", "describe", strconv.Itoa(floatingIPId)) - assert.NoError(t, err) + require.NoError(t, err) assert.Regexp(t, `ID:\s+[0-9]+ Type:\s+ipv6 Name:\s+test-floating-ip @@ -206,29 +207,29 @@ Labels: `, out) out, err = runCommand(t, "floating-ip", "describe", strconv.Itoa(floatingIPId), "--output", "format={{.IP}}") - assert.NoError(t, err) + require.NoError(t, err) out = strings.TrimSpace(out) ipv6 := net.ParseIP(out) if ipv6 != nil { out, err = runCommand(t, "floating-ip", "set-rdns", strconv.Itoa(floatingIPId), "--ip", ipv6.String()+"1", "--hostname", "s1.example.com") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Reverse DNS of Floating IP %d changed\n", floatingIPId), out) out, err = runCommand(t, "floating-ip", "set-rdns", strconv.Itoa(floatingIPId), "--ip", ipv6.String()+"2", "--hostname", "s2.example.com") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Reverse DNS of Floating IP %d changed\n", floatingIPId), out) } else { t.Errorf("invalid IPv6 address: %s", out) } out, err = runCommand(t, "floating-ip", "list", "-o", "columns=ip,dns") - assert.NoError(t, err) + require.NoError(t, err) assert.Regexp(t, fmt.Sprintf(`^IP +DNS %s\/64 +2 entries `, ipv6), out) out, err = runCommand(t, "floating-ip", "delete", strconv.Itoa(floatingIPId)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Floating IP %d deleted\n", floatingIPId), out) } diff --git a/e2e_test/network_test.go b/e2e_test/network_test.go index b47f21d7..ae0229ed 100644 --- a/e2e_test/network_test.go +++ b/e2e_test/network_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/swaggest/assertjson" ) @@ -14,67 +15,67 @@ func TestNetwork(t *testing.T) { out, err := runCommand(t, "network", "create") assert.Empty(t, out) - assert.EqualError(t, err, `required flag(s) "ip-range", "name" not set`) + require.EqualError(t, err, `required flag(s) "ip-range", "name" not set`) out, err = runCommand(t, "network", "create", "--name", "test-network", "--ip-range", "10.0.0.0/24") - assert.NoError(t, err) + require.NoError(t, err) if !assert.Regexp(t, `^Network [0-9]+ created\n$`, out) { // network was not created (properly), so there's no need to test it return } networkID, err := strconv.Atoi(out[8 : len(out)-9]) - assert.NoError(t, err) + require.NoError(t, err) out, err = runCommand(t, "network", "create", "--name", "test-network", "--ip-range", "10.0.1.0/24") assert.Empty(t, out) - assert.Error(t, err) + require.Error(t, err) assert.Regexp(t, `^name is already used \(uniqueness_error, [0-9a-f]+\)$`, err.Error()) out, err = runCommand(t, "network", "enable-protection", strconv.Itoa(networkID), "non-existing-protection") - assert.EqualError(t, err, "unknown protection level: non-existing-protection") + require.EqualError(t, err, "unknown protection level: non-existing-protection") assert.Empty(t, out) out, err = runCommand(t, "network", "enable-protection", "non-existing-network", "delete") - assert.EqualError(t, err, "network not found: non-existing-network") + require.EqualError(t, err, "network not found: non-existing-network") assert.Empty(t, out) out, err = runCommand(t, "network", "enable-protection", strconv.Itoa(networkID), "delete") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Resource protection enabled for network %d\n", networkID), out) out, err = runCommand(t, "network", "list", "-o=columns=servers,ip_range,labels,protection,created,age") - assert.NoError(t, err) + require.NoError(t, err) assert.Regexp(t, `SERVERS +IP RANGE +LABELS +PROTECTION +CREATED +AGE 0 servers +10\.0\.0\.0/24 +delete .*? (?:just now|[0-9]+s) `, out) out, err = runCommand(t, "network", "change-ip-range", "--ip-range", "10.0.2.0/16", "non-existing-network") - assert.EqualError(t, err, "network not found: non-existing-network") + require.EqualError(t, err, "network not found: non-existing-network") assert.Empty(t, out) out, err = runCommand(t, "network", "change-ip-range", "--ip-range", "10.0.2.0/16", "test-network") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("IP range of network %d changed\n", networkID), out) out, err = runCommand(t, "network", "add-label", "non-existing-network", "foo=bar") - assert.EqualError(t, err, "network not found: non-existing-network") + require.EqualError(t, err, "network not found: non-existing-network") assert.Empty(t, out) out, err = runCommand(t, "network", "add-label", "test-network", "foo=bar") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) foo added to Network %d\n", networkID), out) out, err = runCommand(t, "network", "add-label", "test-network", "baz=qux") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) baz added to Network %d\n", networkID), out) out, err = runCommand(t, "network", "remove-label", "test-network", "baz") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) baz removed from Network %d\n", networkID), out) out, err = runCommand(t, "network", "update", "test-network", "--name", "new-test-network") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "Network test-network updated\n", out) out, err = runCommand(t, "network", "delete", strconv.Itoa(networkID)) @@ -82,7 +83,7 @@ func TestNetwork(t *testing.T) { assert.Regexp(t, `^network is delete protected \(protected, [0-9a-f]+\)$`, err.Error()) out, err = runCommand(t, "network", "add-subnet", "--type", "cloud", "--network-zone", "eu-central", "--ip-range", "10.0.16.0/24", "non-existing-network") - assert.EqualError(t, err, "network not found: non-existing-network") + require.EqualError(t, err, "network not found: non-existing-network") assert.Empty(t, out) out, err = runCommand(t, "network", "add-subnet", "--type", "vswitch", "--vswitch-id", "42", "--network-zone", "eu-central", "--ip-range", "10.0.17.0/24", strconv.Itoa(networkID)) @@ -90,27 +91,27 @@ func TestNetwork(t *testing.T) { assert.Regexp(t, `^vswitch not found \(service_error, [0-9a-f]+\)$`, err.Error()) out, err = runCommand(t, "network", "add-subnet", "--type", "cloud", "--network-zone", "eu-central", "--ip-range", "10.0.16.0/24", strconv.Itoa(networkID)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Subnet added to network %d\n", networkID), out) out, err = runCommand(t, "network", "add-route", "--destination", "10.100.1.0/24", "--gateway", "10.0.1.1", "non-existing-network") - assert.EqualError(t, err, "network not found: non-existing-network") + require.EqualError(t, err, "network not found: non-existing-network") assert.Empty(t, out) out, err = runCommand(t, "network", "add-route", "--destination", "10.100.1.0/24", "--gateway", "10.0.1.1", strconv.Itoa(networkID)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Route added to network %d\n", networkID), out) out, err = runCommand(t, "network", "expose-routes-to-vswitch", "non-existing-network") - assert.EqualError(t, err, "network not found: non-existing-network") + require.EqualError(t, err, "network not found: non-existing-network") assert.Empty(t, out) out, err = runCommand(t, "network", "expose-routes-to-vswitch", strconv.Itoa(networkID)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "Exposing routes to connected vSwitch of network new-test-network enabled\n", out) out, err = runCommand(t, "network", "describe", strconv.Itoa(networkID)) - assert.NoError(t, err) + require.NoError(t, err) assert.Regexp(t, `^ID:\s+[0-9]+ Name:\s+new-test-network Created:\s+.*? @@ -131,7 +132,7 @@ Labels: $`, out) out, err = runCommand(t, "network", "list", "-o=json") - assert.NoError(t, err) + require.NoError(t, err) assertjson.Equal(t, []byte(fmt.Sprintf(` [ { @@ -166,39 +167,39 @@ $`, out) `, networkID)), []byte(out)) out, err = runCommand(t, "network", "remove-route", "--destination", "10.100.1.0/24", "--gateway", "10.0.1.1", "non-existing-network") - assert.EqualError(t, err, "network not found: non-existing-network") + require.EqualError(t, err, "network not found: non-existing-network") assert.Empty(t, out) out, err = runCommand(t, "network", "remove-route", "--destination", "10.100.1.0/24", "--gateway", "10.0.1.1", strconv.Itoa(networkID)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Route removed from network %d\n", networkID), out) out, err = runCommand(t, "network", "remove-subnet", "--ip-range", "10.0.16.0/24", "non-existing-network") - assert.EqualError(t, err, "network not found: non-existing-network") + require.EqualError(t, err, "network not found: non-existing-network") assert.Empty(t, out) out, err = runCommand(t, "network", "remove-subnet", "--ip-range", "10.0.16.0/24", strconv.Itoa(networkID)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Subnet 10.0.16.0/24 removed from network %d\n", networkID), out) out, err = runCommand(t, "network", "disable-protection", "non-existing-network", "delete") - assert.EqualError(t, err, "network not found: non-existing-network") + require.EqualError(t, err, "network not found: non-existing-network") assert.Empty(t, out) out, err = runCommand(t, "network", "disable-protection", strconv.Itoa(networkID), "delete") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Resource protection disabled for network %d\n", networkID), out) out, err = runCommand(t, "network", "remove-label", strconv.Itoa(networkID), "foo") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) foo removed from Network %d\n", networkID), out) out, err = runCommand(t, "network", "expose-routes-to-vswitch", "--disable", strconv.Itoa(networkID)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "Exposing routes to connected vSwitch of network new-test-network disabled\n", out) out, err = runCommand(t, "network", "describe", strconv.Itoa(networkID)) - assert.NoError(t, err) + require.NoError(t, err) assert.Regexp(t, `^ID:\s+[0-9]+ Name:\s+new-test-network Created:\s+.*? @@ -215,6 +216,6 @@ Labels: $`, out) out, err = runCommand(t, "network", "delete", strconv.Itoa(networkID)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Network %d deleted\n", networkID), out) } diff --git a/e2e_test/placement_group_test.go b/e2e_test/placement_group_test.go index 714b6515..3858f6f8 100644 --- a/e2e_test/placement_group_test.go +++ b/e2e_test/placement_group_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/swaggest/assertjson" ) @@ -14,41 +15,41 @@ func TestPlacementGroup(t *testing.T) { out, err := runCommand(t, "placement-group", "create") assert.Empty(t, out) - assert.EqualError(t, err, `required flag(s) "name", "type" not set`) + require.EqualError(t, err, `required flag(s) "name", "type" not set`) out, err = runCommand(t, "placement-group", "create", "--name", "test-placement-group", "--type", "spread") - assert.NoError(t, err) + require.NoError(t, err) if !assert.Regexp(t, `^Placement group [0-9]+ created\n$`, out) { return } pgID, err := strconv.Atoi(out[16 : len(out)-9]) - assert.NoError(t, err) + require.NoError(t, err) out, err = runCommand(t, "placement-group", "add-label", "non-existing-placement-group", "foo=bar") - assert.EqualError(t, err, "placement group not found: non-existing-placement-group") + require.EqualError(t, err, "placement group not found: non-existing-placement-group") assert.Empty(t, out) out, err = runCommand(t, "placement-group", "add-label", "test-placement-group", "foo=bar") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) foo added to placement group %d\n", pgID), out) out, err = runCommand(t, "placement-group", "add-label", "test-placement-group", "baz=qux") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) baz added to placement group %d\n", pgID), out) out, err = runCommand(t, "placement-group", "update", "test-placement-group", "--name", "new-test-placement-group") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "placement group test-placement-group updated\n", out) out, err = runCommand(t, "placement-group", "list", "-o=columns=id,name,servers,type,created,age") - assert.NoError(t, err) + require.NoError(t, err) assert.Regexp(t, `ID +NAME +SERVERS +TYPE +CREATED +AGE [0-9]+ +new-test-placement-group +0 servers +spread .*? (?:just now|[0-9]+s) `, out) out, err = runCommand(t, "placement-group", "describe", strconv.Itoa(pgID)) - assert.NoError(t, err) + require.NoError(t, err) assert.Regexp(t, `^ID:\s+[0-9]+ Name:\s+new-test-placement-group Created:\s+.*? @@ -60,7 +61,7 @@ Type:\s+spread $`, out) out, err = runCommand(t, "placement-group", "list", "-o=json") - assert.NoError(t, err) + require.NoError(t, err) assertjson.Equal(t, []byte(fmt.Sprintf(` [ { @@ -77,10 +78,10 @@ $`, out) ]`, pgID)), []byte(out)) out, err = runCommand(t, "placement-group", "remove-label", "new-test-placement-group", "baz") - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) baz removed from placement group %d\n", pgID), out) out, err = runCommand(t, "placement-group", "delete", strconv.Itoa(pgID)) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, fmt.Sprintf("placement group %d deleted\n", pgID), out) } From b8afca8243e283faa07dffded724b565199306fd Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Wed, 18 Sep 2024 14:40:00 +0200 Subject: [PATCH 04/11] ci: separate unit & e2e tests --- .github/workflows/ci.yml | 2 -- .github/workflows/e2e_test.yml | 33 ++++++++++++++++++++++++++++++++ e2e_test/combined_test.go | 2 ++ e2e_test/datacenter_test.go | 2 ++ e2e_test/e2e_test.go | 2 ++ e2e_test/firewall_test.go | 2 ++ e2e_test/floatingip_test.go | 2 ++ e2e_test/network_test.go | 2 ++ e2e_test/placement_group_test.go | 2 ++ e2e_test/server_test.go | 2 ++ 10 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/e2e_test.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e7ca7965..784e341f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,8 +44,6 @@ jobs: with: go-version: "1.23" - - uses: hetznercloud/tps-action@main - - name: Run tests run: go test -coverpkg=./... -coverprofile=coverage.txt -v -race ./... diff --git a/.github/workflows/e2e_test.yml b/.github/workflows/e2e_test.yml new file mode 100644 index 00000000..eec4c56f --- /dev/null +++ b/.github/workflows/e2e_test.yml @@ -0,0 +1,33 @@ +name: E2E Tests + +on: + push: + branches: [main] + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: "1.23" + + - uses: hetznercloud/tps-action@main + + - name: Run tests + run: go test -tags e2e -coverpkg=./... -coverprofile=coverage.txt -v -race ./e2e_test + + - name: Upload coverage reports to Codecov + if: > + !startsWith(github.head_ref, 'renovate/') && + !startsWith(github.head_ref, 'release-please--') + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/e2e_test/combined_test.go b/e2e_test/combined_test.go index d9c56944..daf52d2b 100644 --- a/e2e_test/combined_test.go +++ b/e2e_test/combined_test.go @@ -1,3 +1,5 @@ +//go:build e2e + package e2e_test import ( diff --git a/e2e_test/datacenter_test.go b/e2e_test/datacenter_test.go index d3dcdf3b..10ba8359 100644 --- a/e2e_test/datacenter_test.go +++ b/e2e_test/datacenter_test.go @@ -1,3 +1,5 @@ +//go:build e2e + package e2e_test import ( diff --git a/e2e_test/e2e_test.go b/e2e_test/e2e_test.go index 34ce59ca..6f16384c 100644 --- a/e2e_test/e2e_test.go +++ b/e2e_test/e2e_test.go @@ -1,3 +1,5 @@ +//go:build e2e + package e2e_test import ( diff --git a/e2e_test/firewall_test.go b/e2e_test/firewall_test.go index 3ac36d99..0420bf3b 100644 --- a/e2e_test/firewall_test.go +++ b/e2e_test/firewall_test.go @@ -1,3 +1,5 @@ +//go:build e2e + package e2e_test import ( diff --git a/e2e_test/floatingip_test.go b/e2e_test/floatingip_test.go index 63dcde24..fc8d89e7 100644 --- a/e2e_test/floatingip_test.go +++ b/e2e_test/floatingip_test.go @@ -1,3 +1,5 @@ +//go:build e2e + package e2e_test import ( diff --git a/e2e_test/network_test.go b/e2e_test/network_test.go index ae0229ed..241b9bc4 100644 --- a/e2e_test/network_test.go +++ b/e2e_test/network_test.go @@ -1,3 +1,5 @@ +//go:build e2e + package e2e_test import ( diff --git a/e2e_test/placement_group_test.go b/e2e_test/placement_group_test.go index 3858f6f8..d98c2d3a 100644 --- a/e2e_test/placement_group_test.go +++ b/e2e_test/placement_group_test.go @@ -1,3 +1,5 @@ +//go:build e2e + package e2e_test import ( diff --git a/e2e_test/server_test.go b/e2e_test/server_test.go index 37e164f8..ab5eedee 100644 --- a/e2e_test/server_test.go +++ b/e2e_test/server_test.go @@ -1,3 +1,5 @@ +//go:build e2e + package e2e_test import ( From dd0123c2b87b4501b2cea60ffa64fccfdbec8eed Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Wed, 18 Sep 2024 15:03:24 +0200 Subject: [PATCH 05/11] fix location regex --- e2e_test/combined_test.go | 2 +- e2e_test/floatingip_test.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/e2e_test/combined_test.go b/e2e_test/combined_test.go index daf52d2b..af62376f 100644 --- a/e2e_test/combined_test.go +++ b/e2e_test/combined_test.go @@ -58,7 +58,7 @@ Description:\s+- Created:.*? IP:\s+(?:[0-9]{1,3}\.){3}[0-9]{1,3} Blocked:\s+no -Home Location:\s+[a-z]{3}[0-9]+ +Home Location:\s+[a-z]{3}[0-9]* Server: \s+ID:\s+[0-9]+ \s+Name:\s+test-server diff --git a/e2e_test/floatingip_test.go b/e2e_test/floatingip_test.go index fc8d89e7..beb9034c 100644 --- a/e2e_test/floatingip_test.go +++ b/e2e_test/floatingip_test.go @@ -99,7 +99,7 @@ Description:\s+Some description Created:.*? IP:\s+(?:[0-9]{1,3}\.){3}[0-9]{1,3} Blocked:\s+no -Home Location:\s+fsn1 +Home Location:\s+[a-z]{3}[0-9]* Server: \s+Not assigned DNS: @@ -113,7 +113,7 @@ Labels: out, err = runCommand(t, "floating-ip", "list", "--output", "columns=id,name,type,ip,dns,server,home,blocked,protection,labels,created,age") require.NoError(t, err) assert.Regexp(t, `^ID +NAME +TYPE +IP +DNS +SERVER +HOME +BLOCKED +PROTECTION +LABELS +CREATED +AGE -[0-9]+ +new-test-floating-ip +ipv4 +(?:[0-9]{1,3}\.){3}[0-9]{1,3} +s1\.example\.com +- +fsn1 +no +delete +foo=bar.*? +[0-9]+ +new-test-floating-ip +ipv4 +(?:[0-9]{1,3}\.){3}[0-9]{1,3} +s1\.example\.com +- +[a-z]{3}[0-9]* +no +delete +foo=bar.*? $`, out) out, err = runCommand(t, "floating-ip", "list", "-o=json") @@ -197,7 +197,7 @@ Description:\s+- Created:.*? IP:\s+[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+::\/64 Blocked:\s+no -Home Location:\s+fsn1 +Home Location:\s+[a-z]{3}[0-9]* Server: \s+Not assigned DNS: From 5e0ba186fc8651ba11899e713ae220996d558f30 Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Wed, 18 Sep 2024 15:04:24 +0200 Subject: [PATCH 06/11] add testing variables --- e2e_test/combined_test.go | 4 +-- e2e_test/datacenter_test.go | 2 +- e2e_test/e2e_test.go | 2 +- e2e_test/firewall_test.go | 2 +- e2e_test/floatingip_test.go | 10 ++++---- e2e_test/network_test.go | 2 +- e2e_test/placement_group_test.go | 2 +- e2e_test/server_test.go | 2 +- e2e_test/variables.go | 42 ++++++++++++++++++++++++++++++++ 9 files changed, 55 insertions(+), 13 deletions(-) create mode 100644 e2e_test/variables.go diff --git a/e2e_test/combined_test.go b/e2e_test/combined_test.go index af62376f..574595f6 100644 --- a/e2e_test/combined_test.go +++ b/e2e_test/combined_test.go @@ -1,6 +1,6 @@ //go:build e2e -package e2e_test +package e2e import ( "fmt" @@ -13,7 +13,7 @@ import ( func TestCombined(t *testing.T) { // combined tests combine multiple resources and can thus not be run in parallel - serverID := createServer(t, "test-server", "cpx11", "ubuntu-24.04") + serverID := createServer(t, "test-server", TestServerType, TestImage) firewallID, err := createFirewall(t, "test-firewall") if err != nil { diff --git a/e2e_test/datacenter_test.go b/e2e_test/datacenter_test.go index 10ba8359..48ea22ab 100644 --- a/e2e_test/datacenter_test.go +++ b/e2e_test/datacenter_test.go @@ -1,6 +1,6 @@ //go:build e2e -package e2e_test +package e2e import ( "encoding/json" diff --git a/e2e_test/e2e_test.go b/e2e_test/e2e_test.go index 6f16384c..31d9e123 100644 --- a/e2e_test/e2e_test.go +++ b/e2e_test/e2e_test.go @@ -1,6 +1,6 @@ //go:build e2e -package e2e_test +package e2e import ( "bytes" diff --git a/e2e_test/firewall_test.go b/e2e_test/firewall_test.go index 0420bf3b..16b42115 100644 --- a/e2e_test/firewall_test.go +++ b/e2e_test/firewall_test.go @@ -1,6 +1,6 @@ //go:build e2e -package e2e_test +package e2e import ( "fmt" diff --git a/e2e_test/floatingip_test.go b/e2e_test/floatingip_test.go index beb9034c..559c9ed9 100644 --- a/e2e_test/floatingip_test.go +++ b/e2e_test/floatingip_test.go @@ -1,6 +1,6 @@ //go:build e2e -package e2e_test +package e2e import ( "fmt" @@ -26,7 +26,7 @@ func TestFloatingIP(t *testing.T) { _, err = createFloatingIP(t, "ipv4", "--server", "non-existing-server") require.EqualError(t, err, "server not found: non-existing-server") - floatingIPId, err := createFloatingIP(t, "ipv4", "--home-location", "fsn1") + floatingIPId, err := createFloatingIP(t, "ipv4", "--home-location", TestLocationName) if err != nil { t.Fatal(err) } @@ -135,7 +135,7 @@ $`, out) ], "home_location": { "id": 1, - "name": "fsn1", + "name": "%s", "description": "Falkenstein DC Park 1", "country": "DE", "city": "Falkenstein", @@ -153,7 +153,7 @@ $`, out) "name": "new-test-floating-ip" } ] -`, floatingIPId, ipStr, ipStr)), []byte(out)) +`, floatingIPId, ipStr, ipStr, TestLocationName)), []byte(out)) out, err = runCommand(t, "floating-ip", "delete", strconv.Itoa(floatingIPId)) assert.Regexp(t, `^Floating IP deletion is protected \(protected, [0-9a-f]+\)$`, err.Error()) @@ -183,7 +183,7 @@ $`, out) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Floating IP %d deleted\n", floatingIPId), out) - floatingIPId, err = createFloatingIP(t, "ipv6", "--home-location", "fsn1") + floatingIPId, err = createFloatingIP(t, "ipv6", "--home-location", TestLocationName) if err != nil { t.Fatal(err) } diff --git a/e2e_test/network_test.go b/e2e_test/network_test.go index 241b9bc4..c6c1a769 100644 --- a/e2e_test/network_test.go +++ b/e2e_test/network_test.go @@ -1,6 +1,6 @@ //go:build e2e -package e2e_test +package e2e import ( "fmt" diff --git a/e2e_test/placement_group_test.go b/e2e_test/placement_group_test.go index d98c2d3a..47a61ccc 100644 --- a/e2e_test/placement_group_test.go +++ b/e2e_test/placement_group_test.go @@ -1,6 +1,6 @@ //go:build e2e -package e2e_test +package e2e import ( "fmt" diff --git a/e2e_test/server_test.go b/e2e_test/server_test.go index ab5eedee..4509e6a6 100644 --- a/e2e_test/server_test.go +++ b/e2e_test/server_test.go @@ -1,6 +1,6 @@ //go:build e2e -package e2e_test +package e2e import ( "strconv" diff --git a/e2e_test/variables.go b/e2e_test/variables.go new file mode 100644 index 00000000..02ec8958 --- /dev/null +++ b/e2e_test/variables.go @@ -0,0 +1,42 @@ +//go:build e2e + +package e2e + +import ( + "os" + + "github.com/hetznercloud/hcloud-go/v2/hcloud" +) + +var ( + // TestImage is the system image that is used in end-to-end tests. + TestImage = getEnv("TEST_IMAGE", "ubuntu-24.04") + + // TestImageID is the system image ID that is used in end-to-end tests. + TestImageID = getEnv("TEST_IMAGE_ID", "161547269") + + // TestServerType is the default server type used in end-to-end tests. + TestServerType = getEnv("TEST_SERVER_TYPE", "cpx11") + + // TestServerTypeUpgrade is the upgrade server type used in end-to-end tests. + TestServerTypeUpgrade = getEnv("TEST_SERVER_TYPE_UPGRADE", "cpx21") + + // TestArchitecture is the default architecture used in end-to-end tests, should match the architecture of the TestServerType. + TestArchitecture = getEnv("TEST_ARCHITECTURE", string(hcloud.ArchitectureX86)) + + // TestLoadBalancerType is the default Load Balancer type used in end-to-end tests. + TestLoadBalancerType = "lb11" + + // TestDataCenter is the default datacenter where we execute our end-to-end tests. + TestDataCenter = getEnv("TEST_DATACENTER", "nbg1-dc3") + + // TestLocationName is the default location where we execute our end-to-end tests. + TestLocationName = getEnv("TEST_LOCATION", "nbg1") +) + +func getEnv(key, fallback string) string { + if value, ok := os.LookupEnv(key); ok { + return value + } + return fallback +} From 06bb9cac440f455d8878ef45895c9717ed2fb096 Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Wed, 18 Sep 2024 15:07:52 +0200 Subject: [PATCH 07/11] fix --- e2e_test/floatingip_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/e2e_test/floatingip_test.go b/e2e_test/floatingip_test.go index 559c9ed9..5b5d1a92 100644 --- a/e2e_test/floatingip_test.go +++ b/e2e_test/floatingip_test.go @@ -134,14 +134,14 @@ $`, out) } ], "home_location": { - "id": 1, + "id": "", "name": "%s", - "description": "Falkenstein DC Park 1", + "description": "", "country": "DE", - "city": "Falkenstein", - "latitude": 50.47612, - "longitude": 12.370071, - "network_zone": "eu-central" + "city": "", + "latitude": "", + "longitude": "", + "network_zone": "" }, "blocked": false, "protection": { From 2e9345c30ca44e9c5a2e6f863d95a7bbe31bf5a0 Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Wed, 18 Sep 2024 15:42:45 +0200 Subject: [PATCH 08/11] variable for datacenter --- e2e_test/datacenter_test.go | 2 +- e2e_test/variables.go | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/e2e_test/datacenter_test.go b/e2e_test/datacenter_test.go index 48ea22ab..151883fc 100644 --- a/e2e_test/datacenter_test.go +++ b/e2e_test/datacenter_test.go @@ -26,7 +26,7 @@ func TestDatacenter(t *testing.T) { require.EqualError(t, err, "datacenter not found: 123456") assert.Empty(t, out) - out, err = runCommand(t, "datacenter", "describe", "2") + out, err = runCommand(t, "datacenter", "describe", TestDatacenterID) require.NoError(t, err) assert.Regexp(t, `ID:\s+[0-9]+ Name:\s+[a-z0-9\-]+ diff --git a/e2e_test/variables.go b/e2e_test/variables.go index 02ec8958..193cbfb2 100644 --- a/e2e_test/variables.go +++ b/e2e_test/variables.go @@ -27,8 +27,11 @@ var ( // TestLoadBalancerType is the default Load Balancer type used in end-to-end tests. TestLoadBalancerType = "lb11" - // TestDataCenter is the default datacenter where we execute our end-to-end tests. - TestDataCenter = getEnv("TEST_DATACENTER", "nbg1-dc3") + // TestDatacenterName is the default datacenter name where we execute our end-to-end tests. + TestDatacenterName = getEnv("TEST_DATACENTER_NAME", "nbg1-dc3") + + // TestDatacenterID is the default datacenter ID where we execute our end-to-end tests (Must be the ID of TestDatacenterName) + TestDatacenterID = getEnv("TEST_DATACENTER_ID", "2") // TestLocationName is the default location where we execute our end-to-end tests. TestLocationName = getEnv("TEST_LOCATION", "nbg1") From f541428d4e218fd7355292503d380afd8dbc0d42 Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:45:20 +0200 Subject: [PATCH 09/11] random resource names, failsafe cleanup --- e2e_test/combined_test.go | 22 ++++++---- e2e_test/e2e_test.go | 17 ++++++++ e2e_test/firewall_test.go | 23 +++++++++-- e2e_test/floatingip_test.go | 43 ++++++++++++++------ e2e_test/network_test.go | 69 ++++++++++++++++++++++---------- e2e_test/placement_group_test.go | 59 +++++++++++++++++++-------- e2e_test/server_test.go | 25 +++++++++--- 7 files changed, 189 insertions(+), 69 deletions(-) diff --git a/e2e_test/combined_test.go b/e2e_test/combined_test.go index 574595f6..db26694b 100644 --- a/e2e_test/combined_test.go +++ b/e2e_test/combined_test.go @@ -13,14 +13,19 @@ import ( func TestCombined(t *testing.T) { // combined tests combine multiple resources and can thus not be run in parallel - serverID := createServer(t, "test-server", TestServerType, TestImage) + serverName := withSuffix("test-server") + serverID, err := createServer(t, serverName, TestServerType, TestImage) + if err != nil { + t.Fatal(err) + } - firewallID, err := createFirewall(t, "test-firewall") + firewallName := withSuffix("test-firewall") + firewallID, err := createFirewall(t, firewallName) if err != nil { t.Fatal(err) } - out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "server", "--server", "test-server", strconv.Itoa(firewallID)) + out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "server", "--server", serverName, strconv.Itoa(firewallID)) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Firewall %d applied to resource\n", firewallID), out) @@ -28,7 +33,7 @@ func TestCombined(t *testing.T) { assert.Regexp(t, `^firewall with ID [0-9]+ is still in use \(resource_in_use, [0-9a-f]+\)$`, err.Error()) assert.Empty(t, out) - out, err = runCommand(t, "firewall", "remove-from-resource", "--type", "server", "--server", "test-server", strconv.Itoa(firewallID)) + out, err = runCommand(t, "firewall", "remove-from-resource", "--type", "server", "--server", serverName, strconv.Itoa(firewallID)) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Firewall %d removed from resource\n", firewallID), out) @@ -36,7 +41,8 @@ func TestCombined(t *testing.T) { require.NoError(t, err) assert.Equal(t, fmt.Sprintf("firewall %d deleted\n", firewallID), out) - floatingIP, err := createFloatingIP(t, "ipv4", "--server", strconv.Itoa(serverID)) + floatingIPName := withSuffix("test-floating-ip") + floatingIP, err := createFloatingIP(t, floatingIPName, "ipv4", "--server", strconv.Itoa(serverID)) if err != nil { t.Fatal(err) } @@ -53,7 +59,7 @@ func TestCombined(t *testing.T) { require.NoError(t, err) assert.Regexp(t, `ID:\s+[0-9]+ Type:\s+ipv4 -Name:\s+test-floating-ip +Name:\s+test-floating-ip-[0-9a-f]{8} Description:\s+- Created:.*? IP:\s+(?:[0-9]{1,3}\.){3}[0-9]{1,3} @@ -61,7 +67,7 @@ Blocked:\s+no Home Location:\s+[a-z]{3}[0-9]* Server: \s+ID:\s+[0-9]+ -\s+Name:\s+test-server +\s+Name:\s+test-server-[0-9a-f]{8} DNS: .*? Protection: @@ -72,7 +78,7 @@ Labels: out, err = runCommand(t, "floating-ip", "list", "-o", "columns=server", "-o", "noheader") require.NoError(t, err) - assert.Equal(t, "test-server\n", out) + assert.Equal(t, fmt.Sprintf("%s\n", serverName), out) out, err = runCommand(t, "floating-ip", "delete", strconv.Itoa(floatingIP)) require.NoError(t, err) diff --git a/e2e_test/e2e_test.go b/e2e_test/e2e_test.go index 31d9e123..cafed3c5 100644 --- a/e2e_test/e2e_test.go +++ b/e2e_test/e2e_test.go @@ -4,6 +4,8 @@ package e2e import ( "bytes" + "crypto/rand" + "encoding/hex" "fmt" "os" "testing" @@ -13,8 +15,11 @@ import ( "github.com/hetznercloud/cli/internal/cli" "github.com/hetznercloud/cli/internal/state" "github.com/hetznercloud/cli/internal/state/config" + "github.com/hetznercloud/hcloud-go/v2/hcloud" ) +var client = hcloud.NewClient(hcloud.WithToken(os.Getenv("HCLOUD_TOKEN"))) + func TestMain(m *testing.M) { tok := os.Getenv("HCLOUD_TOKEN") if tok == "" { @@ -26,6 +31,7 @@ func TestMain(m *testing.M) { } func newRootCommand(t *testing.T) *cobra.Command { + t.Helper() cfg := config.New() if err := cfg.Read("config.toml"); err != nil { t.Fatalf("unable to read config file \"%s\": %s\n", cfg.Path(), err) @@ -40,6 +46,7 @@ func newRootCommand(t *testing.T) *cobra.Command { } func runCommand(t *testing.T, args ...string) (string, error) { + t.Helper() cmd := newRootCommand(t) var buf bytes.Buffer cmd.SetArgs(args) @@ -47,3 +54,13 @@ func runCommand(t *testing.T, args ...string) (string, error) { err := cmd.Execute() return buf.String(), err } + +func withSuffix(s string) string { + b := make([]byte, 4) + _, err := rand.Read(b) + if err != nil { + panic(err) + } + suffix := hex.EncodeToString(b) + return fmt.Sprintf("%s-%s", s, suffix) +} diff --git a/e2e_test/firewall_test.go b/e2e_test/firewall_test.go index 16b42115..b4476c82 100644 --- a/e2e_test/firewall_test.go +++ b/e2e_test/firewall_test.go @@ -3,18 +3,22 @@ package e2e import ( + "context" "fmt" "strconv" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestFirewall(t *testing.T) { t.Parallel() - firewallID, err := createFirewall(t, "test-firewall", "--rules-file", "rules_file.json") + firewallName := withSuffix("test-firewall") + firewallID, err := createFirewall(t, firewallName, "--rules-file", "rules_file.json") if err != nil { t.Fatal(err) } @@ -31,11 +35,13 @@ func TestFirewall(t *testing.T) { require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) baz added to firewall %d\n", firewallID), out) - out, err = runCommand(t, "firewall", "update", strconv.Itoa(firewallID), "--name", "new-test-firewall") + firewallName = withSuffix("new-test-firewall") + + out, err = runCommand(t, "firewall", "update", strconv.Itoa(firewallID), "--name", firewallName) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Firewall %d updated\n", firewallID), out) - out, err = runCommand(t, "firewall", "remove-label", "new-test-firewall", "baz") + out, err = runCommand(t, "firewall", "remove-label", firewallName, "baz") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) baz removed from firewall %d\n", firewallID), out) @@ -137,7 +143,7 @@ func TestFirewall(t *testing.T) { out, err = runCommand(t, "firewall", "describe", strconv.Itoa(firewallID)) require.NoError(t, err) assert.Regexp(t, `ID:\s+[0-9]+ -Name:\s+new-test-firewall +Name:\s+new-test-firewall-[0-9a-f]{8} Created:\s+.*? Labels: \s+foo: bar @@ -264,6 +270,11 @@ Applied To: } func createFirewall(t *testing.T, name string, args ...string) (int, error) { + t.Helper() + t.Cleanup(func() { + _, _ = client.Firewall.Delete(context.Background(), &hcloud.Firewall{Name: name}) + }) + out, err := runCommand(t, append([]string{"firewall", "create", "--name", name}, args...)...) if err != nil { return 0, err @@ -277,5 +288,9 @@ func createFirewall(t *testing.T, name string, args ...string) (int, error) { if err != nil { return 0, err } + + t.Cleanup(func() { + _, _ = client.Firewall.Delete(context.Background(), &hcloud.Firewall{ID: int64(firewallID)}) + }) return firewallID, nil } diff --git a/e2e_test/floatingip_test.go b/e2e_test/floatingip_test.go index 5b5d1a92..2a4acc77 100644 --- a/e2e_test/floatingip_test.go +++ b/e2e_test/floatingip_test.go @@ -3,6 +3,7 @@ package e2e import ( + "context" "fmt" "net" "strconv" @@ -12,21 +13,25 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/swaggest/assertjson" + + "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestFloatingIP(t *testing.T) { t.Parallel() - _, err := createFloatingIP(t, "") + floatingIPName := withSuffix("test-floating-ip") + + _, err := createFloatingIP(t, floatingIPName, "") require.EqualError(t, err, "type is required") - _, err = createFloatingIP(t, "ipv4") + _, err = createFloatingIP(t, floatingIPName, "ipv4") require.EqualError(t, err, "one of --home-location or --server is required") - _, err = createFloatingIP(t, "ipv4", "--server", "non-existing-server") + _, err = createFloatingIP(t, floatingIPName, "ipv4", "--server", "non-existing-server") require.EqualError(t, err, "server not found: non-existing-server") - floatingIPId, err := createFloatingIP(t, "ipv4", "--home-location", TestLocationName) + floatingIPId, err := createFloatingIP(t, floatingIPName, "ipv4", "--home-location", TestLocationName) if err != nil { t.Fatal(err) } @@ -45,7 +50,9 @@ func TestFloatingIP(t *testing.T) { }) }) - out, err := runCommand(t, "floating-ip", "update", strconv.Itoa(floatingIPId), "--name", "new-test-floating-ip", "--description", "Some description") + floatingIPName = withSuffix("new-test-floating-ip") + + out, err := runCommand(t, "floating-ip", "update", strconv.Itoa(floatingIPId), "--name", floatingIPName, "--description", "Some description") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Floating IP %d updated\n", floatingIPId), out) @@ -94,7 +101,7 @@ func TestFloatingIP(t *testing.T) { require.NoError(t, err) assert.Regexp(t, `ID:\s+[0-9]+ Type:\s+ipv4 -Name:\s+new-test-floating-ip +Name:\s+new-test-floating-ip-[0-9a-f]{8} Description:\s+Some description Created:.*? IP:\s+(?:[0-9]{1,3}\.){3}[0-9]{1,3} @@ -113,7 +120,7 @@ Labels: out, err = runCommand(t, "floating-ip", "list", "--output", "columns=id,name,type,ip,dns,server,home,blocked,protection,labels,created,age") require.NoError(t, err) assert.Regexp(t, `^ID +NAME +TYPE +IP +DNS +SERVER +HOME +BLOCKED +PROTECTION +LABELS +CREATED +AGE -[0-9]+ +new-test-floating-ip +ipv4 +(?:[0-9]{1,3}\.){3}[0-9]{1,3} +s1\.example\.com +- +[a-z]{3}[0-9]* +no +delete +foo=bar.*? +[0-9]+ +new-test-floating-ip-[0-9a-f]{8} +ipv4 +(?:[0-9]{1,3}\.){3}[0-9]{1,3} +s1\.example\.com +- +[a-z]{3}[0-9]* +no +delete +foo=bar.*? $`, out) out, err = runCommand(t, "floating-ip", "list", "-o=json") @@ -150,10 +157,10 @@ $`, out) "labels": { "foo": "bar" }, - "name": "new-test-floating-ip" + "name": "%s" } ] -`, floatingIPId, ipStr, ipStr, TestLocationName)), []byte(out)) +`, floatingIPId, ipStr, ipStr, TestLocationName, floatingIPName)), []byte(out)) out, err = runCommand(t, "floating-ip", "delete", strconv.Itoa(floatingIPId)) assert.Regexp(t, `^Floating IP deletion is protected \(protected, [0-9a-f]+\)$`, err.Error()) @@ -183,7 +190,8 @@ $`, out) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Floating IP %d deleted\n", floatingIPId), out) - floatingIPId, err = createFloatingIP(t, "ipv6", "--home-location", TestLocationName) + floatingIPName = withSuffix("test-floating-ipv6") + floatingIPId, err = createFloatingIP(t, floatingIPName, "ipv6", "--home-location", TestLocationName) if err != nil { t.Fatal(err) } @@ -192,7 +200,7 @@ $`, out) require.NoError(t, err) assert.Regexp(t, `ID:\s+[0-9]+ Type:\s+ipv6 -Name:\s+test-floating-ip +Name:\s+test-floating-ipv6-[0-9a-f]{8} Description:\s+- Created:.*? IP:\s+[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+::\/64 @@ -235,8 +243,13 @@ Labels: assert.Equal(t, fmt.Sprintf("Floating IP %d deleted\n", floatingIPId), out) } -func createFloatingIP(t *testing.T, ipType string, args ...string) (int, error) { - out, err := runCommand(t, append([]string{"floating-ip", "create", "--name", "test-floating-ip", "--type", ipType}, args...)...) +func createFloatingIP(t *testing.T, name, ipType string, args ...string) (int, error) { + t.Helper() + t.Cleanup(func() { + _, _ = client.FloatingIP.Delete(context.Background(), &hcloud.FloatingIP{Name: name}) + }) + + out, err := runCommand(t, append([]string{"floating-ip", "create", "--name", name, "--type", ipType}, args...)...) if err != nil { return 0, err } @@ -250,5 +263,9 @@ func createFloatingIP(t *testing.T, ipType string, args ...string) (int, error) if err != nil { return 0, err } + + t.Cleanup(func() { + _, _ = client.FloatingIP.Delete(context.Background(), &hcloud.FloatingIP{ID: int64(id)}) + }) return id, nil } diff --git a/e2e_test/network_test.go b/e2e_test/network_test.go index c6c1a769..842ce06d 100644 --- a/e2e_test/network_test.go +++ b/e2e_test/network_test.go @@ -3,6 +3,7 @@ package e2e import ( + "context" "fmt" "strconv" "testing" @@ -10,6 +11,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/swaggest/assertjson" + + "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestNetwork(t *testing.T) { @@ -19,18 +22,11 @@ func TestNetwork(t *testing.T) { assert.Empty(t, out) require.EqualError(t, err, `required flag(s) "ip-range", "name" not set`) - out, err = runCommand(t, "network", "create", "--name", "test-network", "--ip-range", "10.0.0.0/24") - require.NoError(t, err) - if !assert.Regexp(t, `^Network [0-9]+ created\n$`, out) { - // network was not created (properly), so there's no need to test it - return - } - - networkID, err := strconv.Atoi(out[8 : len(out)-9]) + networkName := withSuffix("test-network") + networkID, err := createNetwork(t, networkName, "--ip-range", "10.0.0.0/24") require.NoError(t, err) - out, err = runCommand(t, "network", "create", "--name", "test-network", "--ip-range", "10.0.1.0/24") - assert.Empty(t, out) + _, err = createNetwork(t, networkName, "--ip-range", "10.0.1.0/24") require.Error(t, err) assert.Regexp(t, `^name is already used \(uniqueness_error, [0-9a-f]+\)$`, err.Error()) @@ -56,7 +52,7 @@ func TestNetwork(t *testing.T) { require.EqualError(t, err, "network not found: non-existing-network") assert.Empty(t, out) - out, err = runCommand(t, "network", "change-ip-range", "--ip-range", "10.0.2.0/16", "test-network") + out, err = runCommand(t, "network", "change-ip-range", "--ip-range", "10.0.2.0/16", networkName) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("IP range of network %d changed\n", networkID), out) @@ -64,21 +60,24 @@ func TestNetwork(t *testing.T) { require.EqualError(t, err, "network not found: non-existing-network") assert.Empty(t, out) - out, err = runCommand(t, "network", "add-label", "test-network", "foo=bar") + out, err = runCommand(t, "network", "add-label", networkName, "foo=bar") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) foo added to Network %d\n", networkID), out) - out, err = runCommand(t, "network", "add-label", "test-network", "baz=qux") + out, err = runCommand(t, "network", "add-label", networkName, "baz=qux") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) baz added to Network %d\n", networkID), out) - out, err = runCommand(t, "network", "remove-label", "test-network", "baz") + out, err = runCommand(t, "network", "remove-label", networkName, "baz") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) baz removed from Network %d\n", networkID), out) - out, err = runCommand(t, "network", "update", "test-network", "--name", "new-test-network") + oldNetworkName := networkName + networkName = withSuffix("new-test-network") + + out, err = runCommand(t, "network", "update", oldNetworkName, "--name", networkName) require.NoError(t, err) - assert.Equal(t, "Network test-network updated\n", out) + assert.Equal(t, fmt.Sprintf("Network %s updated\n", oldNetworkName), out) out, err = runCommand(t, "network", "delete", strconv.Itoa(networkID)) assert.Empty(t, out) @@ -110,12 +109,12 @@ func TestNetwork(t *testing.T) { out, err = runCommand(t, "network", "expose-routes-to-vswitch", strconv.Itoa(networkID)) require.NoError(t, err) - assert.Equal(t, "Exposing routes to connected vSwitch of network new-test-network enabled\n", out) + assert.Equal(t, fmt.Sprintf("Exposing routes to connected vSwitch of network %s enabled\n", networkName), out) out, err = runCommand(t, "network", "describe", strconv.Itoa(networkID)) require.NoError(t, err) assert.Regexp(t, `^ID:\s+[0-9]+ -Name:\s+new-test-network +Name:\s+new-test-network-[0-9a-f]{8} Created:\s+.*? IP Range:\s+10\.0\.0\.0\/16 Expose Routes to vSwitch: yes @@ -139,7 +138,7 @@ $`, out) [ { "id": %d, - "name": "new-test-network", + "name": "%s", "created": "", "ip_range": "10.0.0.0/16", "subnets": [ @@ -166,7 +165,7 @@ $`, out) "expose_routes_to_vswitch": true } ] -`, networkID)), []byte(out)) +`, networkID, networkName)), []byte(out)) out, err = runCommand(t, "network", "remove-route", "--destination", "10.100.1.0/24", "--gateway", "10.0.1.1", "non-existing-network") require.EqualError(t, err, "network not found: non-existing-network") @@ -198,12 +197,12 @@ $`, out) out, err = runCommand(t, "network", "expose-routes-to-vswitch", "--disable", strconv.Itoa(networkID)) require.NoError(t, err) - assert.Equal(t, "Exposing routes to connected vSwitch of network new-test-network disabled\n", out) + assert.Equal(t, fmt.Sprintf("Exposing routes to connected vSwitch of network %s disabled\n", networkName), out) out, err = runCommand(t, "network", "describe", strconv.Itoa(networkID)) require.NoError(t, err) assert.Regexp(t, `^ID:\s+[0-9]+ -Name:\s+new-test-network +Name:\s+new-test-network-[0-9a-f]{8} Created:\s+.*? IP Range:\s+10\.0\.0\.0\/16 Expose Routes to vSwitch: no @@ -221,3 +220,29 @@ $`, out) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Network %d deleted\n", networkID), out) } + +func createNetwork(t *testing.T, name string, args ...string) (int, error) { + t.Helper() + t.Cleanup(func() { + _, _ = client.Network.Delete(context.Background(), &hcloud.Network{Name: name}) + }) + + out, err := runCommand(t, append([]string{"network", "create", "--name", name}, args...)...) + if err != nil { + return 0, err + } + + if !assert.Regexp(t, `^Network [0-9]+ created\n$`, out) { + return 0, fmt.Errorf("invalid response: %s", out) + } + + id, err := strconv.Atoi(out[8 : len(out)-9]) + if err != nil { + return 0, err + } + + t.Cleanup(func() { + _, _ = client.Network.Delete(context.Background(), &hcloud.Network{ID: int64(id)}) + }) + return id, nil +} diff --git a/e2e_test/placement_group_test.go b/e2e_test/placement_group_test.go index 47a61ccc..abc282a9 100644 --- a/e2e_test/placement_group_test.go +++ b/e2e_test/placement_group_test.go @@ -3,6 +3,7 @@ package e2e import ( + "context" "fmt" "strconv" "testing" @@ -10,6 +11,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/swaggest/assertjson" + + "github.com/hetznercloud/hcloud-go/v2/hcloud" ) func TestPlacementGroup(t *testing.T) { @@ -19,41 +22,39 @@ func TestPlacementGroup(t *testing.T) { assert.Empty(t, out) require.EqualError(t, err, `required flag(s) "name", "type" not set`) - out, err = runCommand(t, "placement-group", "create", "--name", "test-placement-group", "--type", "spread") - require.NoError(t, err) - if !assert.Regexp(t, `^Placement group [0-9]+ created\n$`, out) { - return - } - - pgID, err := strconv.Atoi(out[16 : len(out)-9]) + pgName := withSuffix("test-placement-group") + pgID, err := createPlacementGroup(t, pgName, "--type", "spread") require.NoError(t, err) out, err = runCommand(t, "placement-group", "add-label", "non-existing-placement-group", "foo=bar") require.EqualError(t, err, "placement group not found: non-existing-placement-group") assert.Empty(t, out) - out, err = runCommand(t, "placement-group", "add-label", "test-placement-group", "foo=bar") + out, err = runCommand(t, "placement-group", "add-label", pgName, "foo=bar") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) foo added to placement group %d\n", pgID), out) - out, err = runCommand(t, "placement-group", "add-label", "test-placement-group", "baz=qux") + out, err = runCommand(t, "placement-group", "add-label", pgName, "baz=qux") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) baz added to placement group %d\n", pgID), out) - out, err = runCommand(t, "placement-group", "update", "test-placement-group", "--name", "new-test-placement-group") + oldPgName := pgName + pgName = withSuffix("new-test-placement-group") + + out, err = runCommand(t, "placement-group", "update", oldPgName, "--name", pgName) require.NoError(t, err) - assert.Equal(t, "placement group test-placement-group updated\n", out) + assert.Equal(t, fmt.Sprintf("placement group %s updated\n", oldPgName), out) out, err = runCommand(t, "placement-group", "list", "-o=columns=id,name,servers,type,created,age") require.NoError(t, err) assert.Regexp(t, `ID +NAME +SERVERS +TYPE +CREATED +AGE -[0-9]+ +new-test-placement-group +0 servers +spread .*? (?:just now|[0-9]+s) +[0-9]+ +new-test-placement-group-[0-9a-f]{8} +0 servers +spread .*? (?:just now|[0-9]+s) `, out) out, err = runCommand(t, "placement-group", "describe", strconv.Itoa(pgID)) require.NoError(t, err) assert.Regexp(t, `^ID:\s+[0-9]+ -Name:\s+new-test-placement-group +Name:\s+new-test-placement-group-[0-9a-f]{8} Created:\s+.*? Labels: \s+(baz: qux|foo: bar) @@ -68,7 +69,7 @@ $`, out) [ { "id": %d, - "name": "new-test-placement-group", + "name": "%s", "labels": { "baz": "qux", "foo": "bar" @@ -77,9 +78,9 @@ $`, out) "servers": [], "type": "spread" } -]`, pgID)), []byte(out)) +]`, pgID, pgName)), []byte(out)) - out, err = runCommand(t, "placement-group", "remove-label", "new-test-placement-group", "baz") + out, err = runCommand(t, "placement-group", "remove-label", pgName, "baz") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) baz removed from placement group %d\n", pgID), out) @@ -87,3 +88,29 @@ $`, out) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("placement group %d deleted\n", pgID), out) } + +func createPlacementGroup(t *testing.T, name string, args ...string) (int, error) { + t.Helper() + t.Cleanup(func() { + _, _ = client.PlacementGroup.Delete(context.Background(), &hcloud.PlacementGroup{Name: name}) + }) + + out, err := runCommand(t, append([]string{"placement-group", "create", "--name", name}, args...)...) + if err != nil { + return 0, err + } + + if !assert.Regexp(t, `^Placement group [0-9]+ created\n$`, out) { + return 0, fmt.Errorf("invalid response: %s", out) + } + + id, err := strconv.Atoi(out[16 : len(out)-9]) + if err != nil { + return 0, err + } + + t.Cleanup(func() { + _, _ = client.PlacementGroup.Delete(context.Background(), &hcloud.PlacementGroup{ID: int64(id)}) + }) + return id, nil +} diff --git a/e2e_test/server_test.go b/e2e_test/server_test.go index 4509e6a6..1fd849a7 100644 --- a/e2e_test/server_test.go +++ b/e2e_test/server_test.go @@ -3,27 +3,40 @@ package e2e import ( + "context" + "fmt" "strconv" "strings" "testing" "github.com/stretchr/testify/assert" + + "github.com/hetznercloud/hcloud-go/v2/hcloud" ) -func createServer(t *testing.T, name, serverType, image string, args ...string) int { +func createServer(t *testing.T, name, serverType, image string, args ...string) (int, error) { + t.Helper() + t.Cleanup(func() { + _, _, _ = client.Server.DeleteWithResult(context.Background(), &hcloud.Server{Name: name}) + }) + out, err := runCommand(t, append([]string{"server", "create", "--name", name, "--type", serverType, "--image", image}, args...)...) if err != nil { - t.Fatal(err) + return 0, err } firstLine := strings.Split(out, "\n")[0] if !assert.Regexp(t, `^Server [0-9]+ created$`, firstLine) { - t.Fatalf("invalid response: %s", out) + return 0, fmt.Errorf("invalid response: %s", out) } - serverID, err := strconv.Atoi(out[7 : len(firstLine)-8]) + id, err := strconv.Atoi(out[7 : len(firstLine)-8]) if err != nil { - t.Fatal(err) + return 0, err } - return serverID + + t.Cleanup(func() { + _, _, _ = client.Server.DeleteWithResult(context.Background(), &hcloud.Server{ID: int64(id)}) + }) + return id, nil } From 801e7ab948d62c028e7724dc46d660a141769e48 Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:54:10 +0200 Subject: [PATCH 10/11] 64 bit ids --- e2e_test/combined_test.go | 20 +++++----- e2e_test/firewall_test.go | 68 ++++++++++++++++---------------- e2e_test/floatingip_test.go | 40 +++++++++---------- e2e_test/network_test.go | 36 ++++++++--------- e2e_test/placement_group_test.go | 10 ++--- e2e_test/server_test.go | 4 +- 6 files changed, 89 insertions(+), 89 deletions(-) diff --git a/e2e_test/combined_test.go b/e2e_test/combined_test.go index db26694b..e7c10d38 100644 --- a/e2e_test/combined_test.go +++ b/e2e_test/combined_test.go @@ -25,37 +25,37 @@ func TestCombined(t *testing.T) { t.Fatal(err) } - out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "server", "--server", serverName, strconv.Itoa(firewallID)) + out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "server", "--server", serverName, strconv.FormatInt(firewallID, 10)) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Firewall %d applied to resource\n", firewallID), out) - out, err = runCommand(t, "firewall", "delete", strconv.Itoa(firewallID)) + out, err = runCommand(t, "firewall", "delete", strconv.FormatInt(firewallID, 10)) assert.Regexp(t, `^firewall with ID [0-9]+ is still in use \(resource_in_use, [0-9a-f]+\)$`, err.Error()) assert.Empty(t, out) - out, err = runCommand(t, "firewall", "remove-from-resource", "--type", "server", "--server", serverName, strconv.Itoa(firewallID)) + out, err = runCommand(t, "firewall", "remove-from-resource", "--type", "server", "--server", serverName, strconv.FormatInt(firewallID, 10)) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Firewall %d removed from resource\n", firewallID), out) - out, err = runCommand(t, "firewall", "delete", strconv.Itoa(firewallID)) + out, err = runCommand(t, "firewall", "delete", strconv.FormatInt(firewallID, 10)) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("firewall %d deleted\n", firewallID), out) floatingIPName := withSuffix("test-floating-ip") - floatingIP, err := createFloatingIP(t, floatingIPName, "ipv4", "--server", strconv.Itoa(serverID)) + floatingIP, err := createFloatingIP(t, floatingIPName, "ipv4", "--server", strconv.FormatInt(serverID, 10)) if err != nil { t.Fatal(err) } - out, err = runCommand(t, "floating-ip", "unassign", strconv.Itoa(floatingIP)) + out, err = runCommand(t, "floating-ip", "unassign", strconv.FormatInt(floatingIP, 10)) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Floating IP %d unassigned\n", floatingIP), out) - out, err = runCommand(t, "floating-ip", "assign", strconv.Itoa(floatingIP), strconv.Itoa(serverID)) + out, err = runCommand(t, "floating-ip", "assign", strconv.FormatInt(floatingIP, 10), strconv.FormatInt(serverID, 10)) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Floating IP %d assigned to server %d\n", floatingIP, serverID), out) - out, err = runCommand(t, "floating-ip", "describe", strconv.Itoa(floatingIP)) + out, err = runCommand(t, "floating-ip", "describe", strconv.FormatInt(floatingIP, 10)) require.NoError(t, err) assert.Regexp(t, `ID:\s+[0-9]+ Type:\s+ipv4 @@ -80,11 +80,11 @@ Labels: require.NoError(t, err) assert.Equal(t, fmt.Sprintf("%s\n", serverName), out) - out, err = runCommand(t, "floating-ip", "delete", strconv.Itoa(floatingIP)) + out, err = runCommand(t, "floating-ip", "delete", strconv.FormatInt(floatingIP, 10)) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Floating IP %d deleted\n", floatingIP), out) - out, err = runCommand(t, "server", "delete", strconv.Itoa(serverID)) + out, err = runCommand(t, "server", "delete", strconv.FormatInt(serverID, 10)) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Server %d deleted\n", serverID), out) } diff --git a/e2e_test/firewall_test.go b/e2e_test/firewall_test.go index b4476c82..52f8b508 100644 --- a/e2e_test/firewall_test.go +++ b/e2e_test/firewall_test.go @@ -27,17 +27,17 @@ func TestFirewall(t *testing.T) { require.EqualError(t, err, "firewall not found: non-existing-firewall") assert.Empty(t, out) - out, err = runCommand(t, "firewall", "add-label", strconv.Itoa(firewallID), "foo=bar") + out, err = runCommand(t, "firewall", "add-label", strconv.FormatInt(firewallID, 10), "foo=bar") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) foo added to firewall %d\n", firewallID), out) - out, err = runCommand(t, "firewall", "add-label", strconv.Itoa(firewallID), "baz=qux") + out, err = runCommand(t, "firewall", "add-label", strconv.FormatInt(firewallID, 10), "baz=qux") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) baz added to firewall %d\n", firewallID), out) firewallName = withSuffix("new-test-firewall") - out, err = runCommand(t, "firewall", "update", strconv.Itoa(firewallID), "--name", firewallName) + out, err = runCommand(t, "firewall", "update", strconv.FormatInt(firewallID, 10), "--name", firewallName) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Firewall %d updated\n", firewallID), out) @@ -47,7 +47,7 @@ func TestFirewall(t *testing.T) { t.Run("add-rule", func(t *testing.T) { t.Run("missing-args", func(t *testing.T) { - out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID)) + out, err := runCommand(t, "firewall", "add-rule", strconv.FormatInt(firewallID, 10)) require.EqualError(t, err, `required flag(s) "direction", "protocol" not set`) assert.Empty(t, out) }) @@ -59,49 +59,49 @@ func TestFirewall(t *testing.T) { }) t.Run("missing-port", func(t *testing.T) { - out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "in", "--source-ips", "10.0.0.0/24", "--protocol", "tcp", "--description", "Some random description") + out, err := runCommand(t, "firewall", "add-rule", strconv.FormatInt(firewallID, 10), "--direction", "in", "--source-ips", "10.0.0.0/24", "--protocol", "tcp", "--description", "Some random description") require.EqualError(t, err, "port is required (--port)") assert.Empty(t, out) }) t.Run("port-not-allowed", func(t *testing.T) { - out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "out", "--destination-ips", "192.168.1.0/24", "--protocol", "icmp", "--port", "12345") + out, err := runCommand(t, "firewall", "add-rule", strconv.FormatInt(firewallID, 10), "--direction", "out", "--destination-ips", "192.168.1.0/24", "--protocol", "icmp", "--port", "12345") require.EqualError(t, err, "port is not allowed for this protocol") assert.Empty(t, out) }) t.Run("invalid-direction", func(t *testing.T) { - out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "foo", "--destination-ips", "192.168.1.0/24", "--protocol", "tcp", "--port", "12345") + out, err := runCommand(t, "firewall", "add-rule", strconv.FormatInt(firewallID, 10), "--direction", "foo", "--destination-ips", "192.168.1.0/24", "--protocol", "tcp", "--port", "12345") require.EqualError(t, err, "invalid direction: foo") assert.Empty(t, out) }) t.Run("invalid-protocol", func(t *testing.T) { - out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "out", "--destination-ips", "192.168.1.0/24", "--protocol", "abc", "--port", "12345") + out, err := runCommand(t, "firewall", "add-rule", strconv.FormatInt(firewallID, 10), "--direction", "out", "--destination-ips", "192.168.1.0/24", "--protocol", "abc", "--port", "12345") require.EqualError(t, err, "invalid protocol: abc") assert.Empty(t, out) }) t.Run("tcp-in", func(t *testing.T) { - out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "in", "--source-ips", "10.0.0.0/24", "--protocol", "tcp", "--port", "9100", "--description", "Some random description") + out, err := runCommand(t, "firewall", "add-rule", strconv.FormatInt(firewallID, 10), "--direction", "in", "--source-ips", "10.0.0.0/24", "--protocol", "tcp", "--port", "9100", "--description", "Some random description") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Firewall Rules for Firewall %d updated\n", firewallID), out) }) t.Run("icmp-out", func(t *testing.T) { - out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "out", "--destination-ips", "192.168.1.0/24", "--protocol", "icmp") + out, err := runCommand(t, "firewall", "add-rule", strconv.FormatInt(firewallID, 10), "--direction", "out", "--destination-ips", "192.168.1.0/24", "--protocol", "icmp") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Firewall Rules for Firewall %d updated\n", firewallID), out) }) t.Run("invalid-ip-out", func(t *testing.T) { - out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "out", "--destination-ips", "invalid-ip", "--protocol", "tcp", "--port", "9100") + out, err := runCommand(t, "firewall", "add-rule", strconv.FormatInt(firewallID, 10), "--direction", "out", "--destination-ips", "invalid-ip", "--protocol", "tcp", "--port", "9100") require.EqualError(t, err, "destination error on index 0: invalid CIDR address: invalid-ip") assert.Empty(t, out) }) t.Run("invalid-ip-range-out", func(t *testing.T) { - out, err := runCommand(t, "firewall", "add-rule", strconv.Itoa(firewallID), "--direction", "in", "--source-ips", "10.1.2.3/8", "--protocol", "tcp", "--port", "9100") + out, err := runCommand(t, "firewall", "add-rule", strconv.FormatInt(firewallID, 10), "--direction", "in", "--source-ips", "10.1.2.3/8", "--protocol", "tcp", "--port", "9100") require.EqualError(t, err, "source ips error on index 0: 10.1.2.3/8 is not the start of the cidr block 10.0.0.0/8") assert.Empty(t, out) }) @@ -109,17 +109,17 @@ func TestFirewall(t *testing.T) { t.Run("apply-to-resource", func(t *testing.T) { t.Run("unknown-type", func(t *testing.T) { - out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "non-existing-type", strconv.Itoa(firewallID)) + out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "non-existing-type", strconv.FormatInt(firewallID, 10)) require.EqualError(t, err, "unknown type non-existing-type") assert.Empty(t, out) }) t.Run("missing-server", func(t *testing.T) { - out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "server", strconv.Itoa(firewallID)) + out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "server", strconv.FormatInt(firewallID, 10)) require.EqualError(t, err, "type server need a --server specific") assert.Empty(t, out) }) t.Run("missing-label-selector", func(t *testing.T) { - out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "label_selector", strconv.Itoa(firewallID)) + out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "label_selector", strconv.FormatInt(firewallID, 10)) require.EqualError(t, err, "type label_selector need a --label-selector specific") assert.Empty(t, out) }) @@ -129,18 +129,18 @@ func TestFirewall(t *testing.T) { assert.Empty(t, out) }) t.Run("unknown-server", func(t *testing.T) { - out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "server", "--server", "non-existing-server", strconv.Itoa(firewallID)) + out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "server", "--server", "non-existing-server", strconv.FormatInt(firewallID, 10)) require.EqualError(t, err, "Server not found: non-existing-server") assert.Empty(t, out) }) t.Run("label-selector", func(t *testing.T) { - out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "label_selector", "--label-selector", "foo=bar", strconv.Itoa(firewallID)) + out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "label_selector", "--label-selector", "foo=bar", strconv.FormatInt(firewallID, 10)) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Firewall %d applied to resource\n", firewallID), out) }) }) - out, err = runCommand(t, "firewall", "describe", strconv.Itoa(firewallID)) + out, err = runCommand(t, "firewall", "describe", strconv.FormatInt(firewallID, 10)) require.NoError(t, err) assert.Regexp(t, `ID:\s+[0-9]+ Name:\s+new-test-firewall-[0-9a-f]{8} @@ -187,17 +187,17 @@ Applied To: t.Run("remove-from-resource", func(t *testing.T) { t.Run("unknown-type", func(t *testing.T) { - out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "non-existing-type", strconv.Itoa(firewallID)) + out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "non-existing-type", strconv.FormatInt(firewallID, 10)) require.EqualError(t, err, "unknown type non-existing-type") assert.Empty(t, out) }) t.Run("missing-server", func(t *testing.T) { - out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "server", strconv.Itoa(firewallID)) + out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "server", strconv.FormatInt(firewallID, 10)) require.EqualError(t, err, "type server need a --server specific") assert.Empty(t, out) }) t.Run("missing-label-selector", func(t *testing.T) { - out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "label_selector", strconv.Itoa(firewallID)) + out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "label_selector", strconv.FormatInt(firewallID, 10)) require.EqualError(t, err, "type label_selector need a --label-selector specific") assert.Empty(t, out) }) @@ -207,12 +207,12 @@ Applied To: assert.Empty(t, out) }) t.Run("unknown-server", func(t *testing.T) { - out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "server", "--server", "non-existing-server", strconv.Itoa(firewallID)) + out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "server", "--server", "non-existing-server", strconv.FormatInt(firewallID, 10)) require.EqualError(t, err, "Server not found: non-existing-server") assert.Empty(t, out) }) t.Run("label-selector", func(t *testing.T) { - out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "label_selector", "--label-selector", "foo=bar", strconv.Itoa(firewallID)) + out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "label_selector", "--label-selector", "foo=bar", strconv.FormatInt(firewallID, 10)) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Firewall %d removed from resource\n", firewallID), out) }) @@ -226,31 +226,31 @@ Applied To: }) t.Run("missing-port", func(t *testing.T) { - out, err := runCommand(t, "firewall", "delete-rule", strconv.Itoa(firewallID), "--direction", "in", "--source-ips", "10.0.0.0/24", "--protocol", "tcp") + out, err := runCommand(t, "firewall", "delete-rule", strconv.FormatInt(firewallID, 10), "--direction", "in", "--source-ips", "10.0.0.0/24", "--protocol", "tcp") require.EqualError(t, err, "port is required (--port)") assert.Empty(t, out) }) t.Run("port-not-allowed", func(t *testing.T) { - out, err := runCommand(t, "firewall", "delete-rule", strconv.Itoa(firewallID), "--direction", "out", "--destination-ips", "192.168.1.0/24", "--protocol", "icmp", "--port", "12345") + out, err := runCommand(t, "firewall", "delete-rule", strconv.FormatInt(firewallID, 10), "--direction", "out", "--destination-ips", "192.168.1.0/24", "--protocol", "icmp", "--port", "12345") require.EqualError(t, err, "port is not allowed for this protocol") assert.Empty(t, out) }) t.Run("tcp-in", func(t *testing.T) { - out, err := runCommand(t, "firewall", "delete-rule", strconv.Itoa(firewallID), "--direction", "in", "--source-ips", "10.0.0.0/24", "--protocol", "tcp", "--port", "9100", "--description", "Some random description") + out, err := runCommand(t, "firewall", "delete-rule", strconv.FormatInt(firewallID, 10), "--direction", "in", "--source-ips", "10.0.0.0/24", "--protocol", "tcp", "--port", "9100", "--description", "Some random description") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Firewall Rules for Firewall %d updated\n", firewallID), out) }) t.Run("icmp-out", func(t *testing.T) { - out, err := runCommand(t, "firewall", "delete-rule", strconv.Itoa(firewallID), "--direction", "out", "--destination-ips", "192.168.1.0/24", "--protocol", "icmp") + out, err := runCommand(t, "firewall", "delete-rule", strconv.FormatInt(firewallID, 10), "--direction", "out", "--destination-ips", "192.168.1.0/24", "--protocol", "icmp") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Firewall Rules for Firewall %d updated\n", firewallID), out) }) t.Run("non-existing-rule", func(t *testing.T) { - out, err := runCommand(t, "firewall", "delete-rule", strconv.Itoa(firewallID), "--direction", "in", "--source-ips", "123.123.123.123/32", "--port", "1234", "--protocol", "tcp") + out, err := runCommand(t, "firewall", "delete-rule", strconv.FormatInt(firewallID, 10), "--direction", "in", "--source-ips", "123.123.123.123/32", "--port", "1234", "--protocol", "tcp") require.EqualError(t, err, fmt.Sprintf("the specified rule was not found in the ruleset of Firewall %d", firewallID)) assert.Empty(t, out) }) @@ -260,16 +260,16 @@ Applied To: require.EqualError(t, err, "Firewall not found: non-existing-firewall") assert.Empty(t, out) - out, err = runCommand(t, "firewall", "replace-rules", strconv.Itoa(firewallID), "--rules-file", "rules_file.json") + out, err = runCommand(t, "firewall", "replace-rules", strconv.FormatInt(firewallID, 10), "--rules-file", "rules_file.json") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Firewall Rules for Firewall %d updated\n", firewallID), out) - out, err = runCommand(t, "firewall", "delete", strconv.Itoa(firewallID)) + out, err = runCommand(t, "firewall", "delete", strconv.FormatInt(firewallID, 10)) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("firewall %d deleted\n", firewallID), out) } -func createFirewall(t *testing.T, name string, args ...string) (int, error) { +func createFirewall(t *testing.T, name string, args ...string) (int64, error) { t.Helper() t.Cleanup(func() { _, _ = client.Firewall.Delete(context.Background(), &hcloud.Firewall{Name: name}) @@ -284,13 +284,13 @@ func createFirewall(t *testing.T, name string, args ...string) (int, error) { return 0, fmt.Errorf("invalid response: %s", out) } - firewallID, err := strconv.Atoi(out[9 : len(out)-9]) + id, err := strconv.ParseInt(out[9:len(out)-9], 10, 64) if err != nil { return 0, err } t.Cleanup(func() { - _, _ = client.Firewall.Delete(context.Background(), &hcloud.Firewall{ID: int64(firewallID)}) + _, _ = client.Firewall.Delete(context.Background(), &hcloud.Firewall{ID: id}) }) - return firewallID, nil + return id, nil } diff --git a/e2e_test/floatingip_test.go b/e2e_test/floatingip_test.go index 2a4acc77..8ce02de7 100644 --- a/e2e_test/floatingip_test.go +++ b/e2e_test/floatingip_test.go @@ -44,7 +44,7 @@ func TestFloatingIP(t *testing.T) { }) t.Run("add-label", func(t *testing.T) { - out, err := runCommand(t, "floating-ip", "add-label", strconv.Itoa(floatingIPId), "foo=bar") + out, err := runCommand(t, "floating-ip", "add-label", strconv.FormatInt(floatingIPId, 10), "foo=bar") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) foo added to Floating IP %d\n", floatingIPId), out) }) @@ -52,11 +52,11 @@ func TestFloatingIP(t *testing.T) { floatingIPName = withSuffix("new-test-floating-ip") - out, err := runCommand(t, "floating-ip", "update", strconv.Itoa(floatingIPId), "--name", floatingIPName, "--description", "Some description") + out, err := runCommand(t, "floating-ip", "update", strconv.FormatInt(floatingIPId, 10), "--name", floatingIPName, "--description", "Some description") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Floating IP %d updated\n", floatingIPId), out) - out, err = runCommand(t, "floating-ip", "set-rdns", strconv.Itoa(floatingIPId), "--hostname", "s1.example.com") + out, err = runCommand(t, "floating-ip", "set-rdns", strconv.FormatInt(floatingIPId, 10), "--hostname", "s1.example.com") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Reverse DNS of Floating IP %d changed\n", floatingIPId), out) @@ -68,13 +68,13 @@ func TestFloatingIP(t *testing.T) { require.EqualError(t, err, "Floating IP not found: non-existing-floating-ip") assert.Empty(t, out) - out, err = runCommand(t, "floating-ip", "assign", strconv.Itoa(floatingIPId), "non-existing-server") + out, err = runCommand(t, "floating-ip", "assign", strconv.FormatInt(floatingIPId, 10), "non-existing-server") require.EqualError(t, err, "server not found: non-existing-server") assert.Empty(t, out) t.Run("enable-protection", func(t *testing.T) { t.Run("unknown-protection-level", func(t *testing.T) { - out, err := runCommand(t, "floating-ip", "enable-protection", strconv.Itoa(floatingIPId), "unknown-protection-level") + out, err := runCommand(t, "floating-ip", "enable-protection", strconv.FormatInt(floatingIPId, 10), "unknown-protection-level") require.EqualError(t, err, "unknown protection level: unknown-protection-level") assert.Empty(t, out) }) @@ -86,18 +86,18 @@ func TestFloatingIP(t *testing.T) { }) t.Run("enable-delete-protection", func(t *testing.T) { - out, err := runCommand(t, "floating-ip", "enable-protection", strconv.Itoa(floatingIPId), "delete") + out, err := runCommand(t, "floating-ip", "enable-protection", strconv.FormatInt(floatingIPId, 10), "delete") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Resource protection enabled for floating IP %d\n", floatingIPId), out) }) }) - ipStr, err := runCommand(t, "floating-ip", "describe", strconv.Itoa(floatingIPId), "--output", "format={{.IP}}") + ipStr, err := runCommand(t, "floating-ip", "describe", strconv.FormatInt(floatingIPId, 10), "--output", "format={{.IP}}") require.NoError(t, err) ipStr = strings.TrimSpace(ipStr) assert.Regexp(t, `^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$`, ipStr) - out, err = runCommand(t, "floating-ip", "describe", strconv.Itoa(floatingIPId)) + out, err = runCommand(t, "floating-ip", "describe", strconv.FormatInt(floatingIPId, 10)) require.NoError(t, err) assert.Regexp(t, `ID:\s+[0-9]+ Type:\s+ipv4 @@ -162,7 +162,7 @@ $`, out) ] `, floatingIPId, ipStr, ipStr, TestLocationName, floatingIPName)), []byte(out)) - out, err = runCommand(t, "floating-ip", "delete", strconv.Itoa(floatingIPId)) + out, err = runCommand(t, "floating-ip", "delete", strconv.FormatInt(floatingIPId, 10)) assert.Regexp(t, `^Floating IP deletion is protected \(protected, [0-9a-f]+\)$`, err.Error()) assert.Empty(t, out) @@ -174,19 +174,19 @@ $`, out) }) t.Run("unknown-protection-level", func(t *testing.T) { - out, err := runCommand(t, "floating-ip", "disable-protection", strconv.Itoa(floatingIPId), "unknown-protection-level") + out, err := runCommand(t, "floating-ip", "disable-protection", strconv.FormatInt(floatingIPId, 10), "unknown-protection-level") require.EqualError(t, err, "unknown protection level: unknown-protection-level") assert.Empty(t, out) }) t.Run("disable-delete-protection", func(t *testing.T) { - out, err = runCommand(t, "floating-ip", "disable-protection", strconv.Itoa(floatingIPId), "delete") + out, err = runCommand(t, "floating-ip", "disable-protection", strconv.FormatInt(floatingIPId, 10), "delete") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Resource protection disabled for floating IP %d\n", floatingIPId), out) }) }) - out, err = runCommand(t, "floating-ip", "delete", strconv.Itoa(floatingIPId)) + out, err = runCommand(t, "floating-ip", "delete", strconv.FormatInt(floatingIPId, 10)) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Floating IP %d deleted\n", floatingIPId), out) @@ -196,7 +196,7 @@ $`, out) t.Fatal(err) } - out, err = runCommand(t, "floating-ip", "describe", strconv.Itoa(floatingIPId)) + out, err = runCommand(t, "floating-ip", "describe", strconv.FormatInt(floatingIPId, 10)) require.NoError(t, err) assert.Regexp(t, `ID:\s+[0-9]+ Type:\s+ipv6 @@ -216,16 +216,16 @@ Labels: \s+No labels `, out) - out, err = runCommand(t, "floating-ip", "describe", strconv.Itoa(floatingIPId), "--output", "format={{.IP}}") + out, err = runCommand(t, "floating-ip", "describe", strconv.FormatInt(floatingIPId, 10), "--output", "format={{.IP}}") require.NoError(t, err) out = strings.TrimSpace(out) ipv6 := net.ParseIP(out) if ipv6 != nil { - out, err = runCommand(t, "floating-ip", "set-rdns", strconv.Itoa(floatingIPId), "--ip", ipv6.String()+"1", "--hostname", "s1.example.com") + out, err = runCommand(t, "floating-ip", "set-rdns", strconv.FormatInt(floatingIPId, 10), "--ip", ipv6.String()+"1", "--hostname", "s1.example.com") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Reverse DNS of Floating IP %d changed\n", floatingIPId), out) - out, err = runCommand(t, "floating-ip", "set-rdns", strconv.Itoa(floatingIPId), "--ip", ipv6.String()+"2", "--hostname", "s2.example.com") + out, err = runCommand(t, "floating-ip", "set-rdns", strconv.FormatInt(floatingIPId, 10), "--ip", ipv6.String()+"2", "--hostname", "s2.example.com") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Reverse DNS of Floating IP %d changed\n", floatingIPId), out) } else { @@ -238,12 +238,12 @@ Labels: %s\/64 +2 entries `, ipv6), out) - out, err = runCommand(t, "floating-ip", "delete", strconv.Itoa(floatingIPId)) + out, err = runCommand(t, "floating-ip", "delete", strconv.FormatInt(floatingIPId, 10)) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Floating IP %d deleted\n", floatingIPId), out) } -func createFloatingIP(t *testing.T, name, ipType string, args ...string) (int, error) { +func createFloatingIP(t *testing.T, name, ipType string, args ...string) (int64, error) { t.Helper() t.Cleanup(func() { _, _ = client.FloatingIP.Delete(context.Background(), &hcloud.FloatingIP{Name: name}) @@ -259,13 +259,13 @@ func createFloatingIP(t *testing.T, name, ipType string, args ...string) (int, e return 0, fmt.Errorf("invalid response: %s", out) } - id, err := strconv.Atoi(out[12 : len(firstLine)-8]) + id, err := strconv.ParseInt(out[12:len(firstLine)-8], 10, 64) if err != nil { return 0, err } t.Cleanup(func() { - _, _ = client.FloatingIP.Delete(context.Background(), &hcloud.FloatingIP{ID: int64(id)}) + _, _ = client.FloatingIP.Delete(context.Background(), &hcloud.FloatingIP{ID: id}) }) return id, nil } diff --git a/e2e_test/network_test.go b/e2e_test/network_test.go index 842ce06d..8cf1985c 100644 --- a/e2e_test/network_test.go +++ b/e2e_test/network_test.go @@ -30,7 +30,7 @@ func TestNetwork(t *testing.T) { require.Error(t, err) assert.Regexp(t, `^name is already used \(uniqueness_error, [0-9a-f]+\)$`, err.Error()) - out, err = runCommand(t, "network", "enable-protection", strconv.Itoa(networkID), "non-existing-protection") + out, err = runCommand(t, "network", "enable-protection", strconv.FormatInt(networkID, 10), "non-existing-protection") require.EqualError(t, err, "unknown protection level: non-existing-protection") assert.Empty(t, out) @@ -38,7 +38,7 @@ func TestNetwork(t *testing.T) { require.EqualError(t, err, "network not found: non-existing-network") assert.Empty(t, out) - out, err = runCommand(t, "network", "enable-protection", strconv.Itoa(networkID), "delete") + out, err = runCommand(t, "network", "enable-protection", strconv.FormatInt(networkID, 10), "delete") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Resource protection enabled for network %d\n", networkID), out) @@ -79,7 +79,7 @@ func TestNetwork(t *testing.T) { require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Network %s updated\n", oldNetworkName), out) - out, err = runCommand(t, "network", "delete", strconv.Itoa(networkID)) + out, err = runCommand(t, "network", "delete", strconv.FormatInt(networkID, 10)) assert.Empty(t, out) assert.Regexp(t, `^network is delete protected \(protected, [0-9a-f]+\)$`, err.Error()) @@ -87,11 +87,11 @@ func TestNetwork(t *testing.T) { require.EqualError(t, err, "network not found: non-existing-network") assert.Empty(t, out) - out, err = runCommand(t, "network", "add-subnet", "--type", "vswitch", "--vswitch-id", "42", "--network-zone", "eu-central", "--ip-range", "10.0.17.0/24", strconv.Itoa(networkID)) + out, err = runCommand(t, "network", "add-subnet", "--type", "vswitch", "--vswitch-id", "42", "--network-zone", "eu-central", "--ip-range", "10.0.17.0/24", strconv.FormatInt(networkID, 10)) assert.Empty(t, out) assert.Regexp(t, `^vswitch not found \(service_error, [0-9a-f]+\)$`, err.Error()) - out, err = runCommand(t, "network", "add-subnet", "--type", "cloud", "--network-zone", "eu-central", "--ip-range", "10.0.16.0/24", strconv.Itoa(networkID)) + out, err = runCommand(t, "network", "add-subnet", "--type", "cloud", "--network-zone", "eu-central", "--ip-range", "10.0.16.0/24", strconv.FormatInt(networkID, 10)) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Subnet added to network %d\n", networkID), out) @@ -99,7 +99,7 @@ func TestNetwork(t *testing.T) { require.EqualError(t, err, "network not found: non-existing-network") assert.Empty(t, out) - out, err = runCommand(t, "network", "add-route", "--destination", "10.100.1.0/24", "--gateway", "10.0.1.1", strconv.Itoa(networkID)) + out, err = runCommand(t, "network", "add-route", "--destination", "10.100.1.0/24", "--gateway", "10.0.1.1", strconv.FormatInt(networkID, 10)) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Route added to network %d\n", networkID), out) @@ -107,11 +107,11 @@ func TestNetwork(t *testing.T) { require.EqualError(t, err, "network not found: non-existing-network") assert.Empty(t, out) - out, err = runCommand(t, "network", "expose-routes-to-vswitch", strconv.Itoa(networkID)) + out, err = runCommand(t, "network", "expose-routes-to-vswitch", strconv.FormatInt(networkID, 10)) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Exposing routes to connected vSwitch of network %s enabled\n", networkName), out) - out, err = runCommand(t, "network", "describe", strconv.Itoa(networkID)) + out, err = runCommand(t, "network", "describe", strconv.FormatInt(networkID, 10)) require.NoError(t, err) assert.Regexp(t, `^ID:\s+[0-9]+ Name:\s+new-test-network-[0-9a-f]{8} @@ -171,7 +171,7 @@ $`, out) require.EqualError(t, err, "network not found: non-existing-network") assert.Empty(t, out) - out, err = runCommand(t, "network", "remove-route", "--destination", "10.100.1.0/24", "--gateway", "10.0.1.1", strconv.Itoa(networkID)) + out, err = runCommand(t, "network", "remove-route", "--destination", "10.100.1.0/24", "--gateway", "10.0.1.1", strconv.FormatInt(networkID, 10)) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Route removed from network %d\n", networkID), out) @@ -179,7 +179,7 @@ $`, out) require.EqualError(t, err, "network not found: non-existing-network") assert.Empty(t, out) - out, err = runCommand(t, "network", "remove-subnet", "--ip-range", "10.0.16.0/24", strconv.Itoa(networkID)) + out, err = runCommand(t, "network", "remove-subnet", "--ip-range", "10.0.16.0/24", strconv.FormatInt(networkID, 10)) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Subnet 10.0.16.0/24 removed from network %d\n", networkID), out) @@ -187,19 +187,19 @@ $`, out) require.EqualError(t, err, "network not found: non-existing-network") assert.Empty(t, out) - out, err = runCommand(t, "network", "disable-protection", strconv.Itoa(networkID), "delete") + out, err = runCommand(t, "network", "disable-protection", strconv.FormatInt(networkID, 10), "delete") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Resource protection disabled for network %d\n", networkID), out) - out, err = runCommand(t, "network", "remove-label", strconv.Itoa(networkID), "foo") + out, err = runCommand(t, "network", "remove-label", strconv.FormatInt(networkID, 10), "foo") require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) foo removed from Network %d\n", networkID), out) - out, err = runCommand(t, "network", "expose-routes-to-vswitch", "--disable", strconv.Itoa(networkID)) + out, err = runCommand(t, "network", "expose-routes-to-vswitch", "--disable", strconv.FormatInt(networkID, 10)) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Exposing routes to connected vSwitch of network %s disabled\n", networkName), out) - out, err = runCommand(t, "network", "describe", strconv.Itoa(networkID)) + out, err = runCommand(t, "network", "describe", strconv.FormatInt(networkID, 10)) require.NoError(t, err) assert.Regexp(t, `^ID:\s+[0-9]+ Name:\s+new-test-network-[0-9a-f]{8} @@ -216,12 +216,12 @@ Labels: \s+No labels $`, out) - out, err = runCommand(t, "network", "delete", strconv.Itoa(networkID)) + out, err = runCommand(t, "network", "delete", strconv.FormatInt(networkID, 10)) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Network %d deleted\n", networkID), out) } -func createNetwork(t *testing.T, name string, args ...string) (int, error) { +func createNetwork(t *testing.T, name string, args ...string) (int64, error) { t.Helper() t.Cleanup(func() { _, _ = client.Network.Delete(context.Background(), &hcloud.Network{Name: name}) @@ -236,13 +236,13 @@ func createNetwork(t *testing.T, name string, args ...string) (int, error) { return 0, fmt.Errorf("invalid response: %s", out) } - id, err := strconv.Atoi(out[8 : len(out)-9]) + id, err := strconv.ParseInt(out[8:len(out)-9], 10, 64) if err != nil { return 0, err } t.Cleanup(func() { - _, _ = client.Network.Delete(context.Background(), &hcloud.Network{ID: int64(id)}) + _, _ = client.Network.Delete(context.Background(), &hcloud.Network{ID: id}) }) return id, nil } diff --git a/e2e_test/placement_group_test.go b/e2e_test/placement_group_test.go index abc282a9..d9bb2415 100644 --- a/e2e_test/placement_group_test.go +++ b/e2e_test/placement_group_test.go @@ -51,7 +51,7 @@ func TestPlacementGroup(t *testing.T) { [0-9]+ +new-test-placement-group-[0-9a-f]{8} +0 servers +spread .*? (?:just now|[0-9]+s) `, out) - out, err = runCommand(t, "placement-group", "describe", strconv.Itoa(pgID)) + out, err = runCommand(t, "placement-group", "describe", strconv.FormatInt(pgID, 10)) require.NoError(t, err) assert.Regexp(t, `^ID:\s+[0-9]+ Name:\s+new-test-placement-group-[0-9a-f]{8} @@ -84,12 +84,12 @@ $`, out) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("Label(s) baz removed from placement group %d\n", pgID), out) - out, err = runCommand(t, "placement-group", "delete", strconv.Itoa(pgID)) + out, err = runCommand(t, "placement-group", "delete", strconv.FormatInt(pgID, 10)) require.NoError(t, err) assert.Equal(t, fmt.Sprintf("placement group %d deleted\n", pgID), out) } -func createPlacementGroup(t *testing.T, name string, args ...string) (int, error) { +func createPlacementGroup(t *testing.T, name string, args ...string) (int64, error) { t.Helper() t.Cleanup(func() { _, _ = client.PlacementGroup.Delete(context.Background(), &hcloud.PlacementGroup{Name: name}) @@ -104,13 +104,13 @@ func createPlacementGroup(t *testing.T, name string, args ...string) (int, error return 0, fmt.Errorf("invalid response: %s", out) } - id, err := strconv.Atoi(out[16 : len(out)-9]) + id, err := strconv.ParseInt(out[16:len(out)-9], 10, 64) if err != nil { return 0, err } t.Cleanup(func() { - _, _ = client.PlacementGroup.Delete(context.Background(), &hcloud.PlacementGroup{ID: int64(id)}) + _, _ = client.PlacementGroup.Delete(context.Background(), &hcloud.PlacementGroup{ID: id}) }) return id, nil } diff --git a/e2e_test/server_test.go b/e2e_test/server_test.go index 1fd849a7..ff4ea3ee 100644 --- a/e2e_test/server_test.go +++ b/e2e_test/server_test.go @@ -14,7 +14,7 @@ import ( "github.com/hetznercloud/hcloud-go/v2/hcloud" ) -func createServer(t *testing.T, name, serverType, image string, args ...string) (int, error) { +func createServer(t *testing.T, name, serverType, image string, args ...string) (int64, error) { t.Helper() t.Cleanup(func() { _, _, _ = client.Server.DeleteWithResult(context.Background(), &hcloud.Server{Name: name}) @@ -30,7 +30,7 @@ func createServer(t *testing.T, name, serverType, image string, args ...string) return 0, fmt.Errorf("invalid response: %s", out) } - id, err := strconv.Atoi(out[7 : len(firstLine)-8]) + id, err := strconv.ParseInt(out[7:len(firstLine)-8], 10, 64) if err != nil { return 0, err } From 68ea4f574cf93de7181d72bf0616d384e5eb4a5e Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Wed, 18 Sep 2024 17:48:19 +0200 Subject: [PATCH 11/11] use require where possible, nesting using t.Run --- e2e_test/combined_test.go | 109 +++++++----- e2e_test/datacenter_test.go | 42 +++-- e2e_test/firewall_test.go | 92 ++++++---- e2e_test/floatingip_test.go | 279 ++++++++++++++++------------- e2e_test/network_test.go | 291 ++++++++++++++++++++----------- e2e_test/placement_group_test.go | 98 +++++++---- 6 files changed, 561 insertions(+), 350 deletions(-) diff --git a/e2e_test/combined_test.go b/e2e_test/combined_test.go index e7c10d38..7b2d1a04 100644 --- a/e2e_test/combined_test.go +++ b/e2e_test/combined_test.go @@ -15,49 +15,60 @@ func TestCombined(t *testing.T) { // combined tests combine multiple resources and can thus not be run in parallel serverName := withSuffix("test-server") serverID, err := createServer(t, serverName, TestServerType, TestImage) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) firewallName := withSuffix("test-firewall") firewallID, err := createFirewall(t, firewallName) - if err != nil { - t.Fatal(err) - } - - out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "server", "--server", serverName, strconv.FormatInt(firewallID, 10)) - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Firewall %d applied to resource\n", firewallID), out) - - out, err = runCommand(t, "firewall", "delete", strconv.FormatInt(firewallID, 10)) - assert.Regexp(t, `^firewall with ID [0-9]+ is still in use \(resource_in_use, [0-9a-f]+\)$`, err.Error()) - assert.Empty(t, out) - - out, err = runCommand(t, "firewall", "remove-from-resource", "--type", "server", "--server", serverName, strconv.FormatInt(firewallID, 10)) require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Firewall %d removed from resource\n", firewallID), out) - out, err = runCommand(t, "firewall", "delete", strconv.FormatInt(firewallID, 10)) - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("firewall %d deleted\n", firewallID), out) + t.Run("firewall", func(t *testing.T) { + t.Run("apply-to-server", func(t *testing.T) { + out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "server", "--server", serverName, strconv.FormatInt(firewallID, 10)) + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Firewall %d applied to resource\n", firewallID), out) + }) + + t.Run("delete-in-use", func(t *testing.T) { + out, err := runCommand(t, "firewall", "delete", strconv.FormatInt(firewallID, 10)) + assert.Regexp(t, `^firewall with ID [0-9]+ is still in use \(resource_in_use, [0-9a-f]+\)$`, err.Error()) + assert.Empty(t, out) + }) + + t.Run("remove-from-server", func(t *testing.T) { + out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "server", "--server", serverName, strconv.FormatInt(firewallID, 10)) + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Firewall %d removed from resource\n", firewallID), out) + }) + + t.Run("delete", func(t *testing.T) { + out, err := runCommand(t, "firewall", "delete", strconv.FormatInt(firewallID, 10)) + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("firewall %d deleted\n", firewallID), out) + }) + + }) floatingIPName := withSuffix("test-floating-ip") floatingIP, err := createFloatingIP(t, floatingIPName, "ipv4", "--server", strconv.FormatInt(serverID, 10)) - if err != nil { - t.Fatal(err) - } - - out, err = runCommand(t, "floating-ip", "unassign", strconv.FormatInt(floatingIP, 10)) - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Floating IP %d unassigned\n", floatingIP), out) - - out, err = runCommand(t, "floating-ip", "assign", strconv.FormatInt(floatingIP, 10), strconv.FormatInt(serverID, 10)) require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Floating IP %d assigned to server %d\n", floatingIP, serverID), out) - out, err = runCommand(t, "floating-ip", "describe", strconv.FormatInt(floatingIP, 10)) - require.NoError(t, err) - assert.Regexp(t, `ID:\s+[0-9]+ + t.Run("floating-ip", func(t *testing.T) { + t.Run("unassign", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "unassign", strconv.FormatInt(floatingIP, 10)) + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Floating IP %d unassigned\n", floatingIP), out) + }) + + t.Run("assign", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "assign", strconv.FormatInt(floatingIP, 10), strconv.FormatInt(serverID, 10)) + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Floating IP %d assigned to server %d\n", floatingIP, serverID), out) + }) + + t.Run("describe", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "describe", strconv.FormatInt(floatingIP, 10)) + require.NoError(t, err) + assert.Regexp(t, `ID:\s+[0-9]+ Type:\s+ipv4 Name:\s+test-floating-ip-[0-9a-f]{8} Description:\s+- @@ -75,16 +86,24 @@ Protection: Labels: \s+No labels `, out) - - out, err = runCommand(t, "floating-ip", "list", "-o", "columns=server", "-o", "noheader") - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("%s\n", serverName), out) - - out, err = runCommand(t, "floating-ip", "delete", strconv.FormatInt(floatingIP, 10)) - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Floating IP %d deleted\n", floatingIP), out) - - out, err = runCommand(t, "server", "delete", strconv.FormatInt(serverID, 10)) - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Server %d deleted\n", serverID), out) + }) + + t.Run("list", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "list", "-o", "columns=server", "-o", "noheader") + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("%s\n", serverName), out) + }) + + t.Run("delete", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "delete", strconv.FormatInt(floatingIP, 10)) + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Floating IP %d deleted\n", floatingIP), out) + }) + }) + + t.Run("delete-server", func(t *testing.T) { + out, err := runCommand(t, "server", "delete", strconv.FormatInt(serverID, 10)) + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Server %d deleted\n", serverID), out) + }) } diff --git a/e2e_test/datacenter_test.go b/e2e_test/datacenter_test.go index 151883fc..8c4deb21 100644 --- a/e2e_test/datacenter_test.go +++ b/e2e_test/datacenter_test.go @@ -13,22 +13,32 @@ import ( func TestDatacenter(t *testing.T) { t.Parallel() - out, err := runCommand(t, "datacenter", "list") - require.NoError(t, err) - assert.Regexp(t, `ID +NAME +DESCRIPTION +LOCATION + t.Run("list", func(t *testing.T) { + t.Run("table", func(t *testing.T) { + out, err := runCommand(t, "datacenter", "list") + require.NoError(t, err) + assert.Regexp(t, `ID +NAME +DESCRIPTION +LOCATION ([0-9]+ +[a-z0-9\-]+ +[a-zA-Z0-9\- ]+ +[a-z0-9\-]+\n)+`, out) - - out, err = runCommand(t, "datacenter", "list", "-o=json") - require.NoError(t, err) - require.NoError(t, json.Unmarshal([]byte(out), new([]any))) - - out, err = runCommand(t, "datacenter", "describe", "123456") - require.EqualError(t, err, "datacenter not found: 123456") - assert.Empty(t, out) - - out, err = runCommand(t, "datacenter", "describe", TestDatacenterID) - require.NoError(t, err) - assert.Regexp(t, `ID:\s+[0-9]+ + }) + + t.Run("json", func(t *testing.T) { + out, err := runCommand(t, "datacenter", "list", "-o=json") + require.NoError(t, err) + require.NoError(t, json.Unmarshal([]byte(out), new([]any))) + }) + }) + + t.Run("describe", func(t *testing.T) { + t.Run("non-existing", func(t *testing.T) { + out, err := runCommand(t, "datacenter", "describe", "123456") + require.EqualError(t, err, "datacenter not found: 123456") + assert.Empty(t, out) + }) + + t.Run("normal", func(t *testing.T) { + out, err := runCommand(t, "datacenter", "describe", TestDatacenterID) + require.NoError(t, err) + assert.Regexp(t, `ID:\s+[0-9]+ Name:\s+[a-z0-9\-]+ Description:\s+[a-zA-Z0-9\- ]+ Location: @@ -41,4 +51,6 @@ Location: Server Types: (\s+- ID: [0-9]+\s+Name: [a-z0-9]+\s+Supported: (true|false)\s+Available: (true|false))+ `, out) + }) + }) } diff --git a/e2e_test/firewall_test.go b/e2e_test/firewall_test.go index 52f8b508..8bc27705 100644 --- a/e2e_test/firewall_test.go +++ b/e2e_test/firewall_test.go @@ -19,31 +19,41 @@ func TestFirewall(t *testing.T) { firewallName := withSuffix("test-firewall") firewallID, err := createFirewall(t, firewallName, "--rules-file", "rules_file.json") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) - out, err := runCommand(t, "firewall", "add-label", "non-existing-firewall", "foo=bar") - require.EqualError(t, err, "firewall not found: non-existing-firewall") - assert.Empty(t, out) + t.Run("add-label", func(t *testing.T) { + t.Run("non-existing", func(t *testing.T) { + out, err := runCommand(t, "firewall", "add-label", "non-existing-firewall", "foo=bar") + require.EqualError(t, err, "firewall not found: non-existing-firewall") + assert.Empty(t, out) + }) - out, err = runCommand(t, "firewall", "add-label", strconv.FormatInt(firewallID, 10), "foo=bar") - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Label(s) foo added to firewall %d\n", firewallID), out) + t.Run("1", func(t *testing.T) { + out, err := runCommand(t, "firewall", "add-label", strconv.FormatInt(firewallID, 10), "foo=bar") + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Label(s) foo added to firewall %d\n", firewallID), out) + }) - out, err = runCommand(t, "firewall", "add-label", strconv.FormatInt(firewallID, 10), "baz=qux") - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Label(s) baz added to firewall %d\n", firewallID), out) + t.Run("2", func(t *testing.T) { + out, err := runCommand(t, "firewall", "add-label", strconv.FormatInt(firewallID, 10), "baz=qux") + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Label(s) baz added to firewall %d\n", firewallID), out) + }) + }) - firewallName = withSuffix("new-test-firewall") + t.Run("update-name", func(t *testing.T) { + firewallName = withSuffix("new-test-firewall") - out, err = runCommand(t, "firewall", "update", strconv.FormatInt(firewallID, 10), "--name", firewallName) - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Firewall %d updated\n", firewallID), out) + out, err := runCommand(t, "firewall", "update", strconv.FormatInt(firewallID, 10), "--name", firewallName) + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Firewall %d updated\n", firewallID), out) + }) - out, err = runCommand(t, "firewall", "remove-label", firewallName, "baz") - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Label(s) baz removed from firewall %d\n", firewallID), out) + t.Run("remove-label", func(t *testing.T) { + out, err := runCommand(t, "firewall", "remove-label", firewallName, "baz") + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Label(s) baz removed from firewall %d\n", firewallID), out) + }) t.Run("add-rule", func(t *testing.T) { t.Run("missing-args", func(t *testing.T) { @@ -113,26 +123,31 @@ func TestFirewall(t *testing.T) { require.EqualError(t, err, "unknown type non-existing-type") assert.Empty(t, out) }) + t.Run("missing-server", func(t *testing.T) { out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "server", strconv.FormatInt(firewallID, 10)) require.EqualError(t, err, "type server need a --server specific") assert.Empty(t, out) }) + t.Run("missing-label-selector", func(t *testing.T) { out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "label_selector", strconv.FormatInt(firewallID, 10)) require.EqualError(t, err, "type label_selector need a --label-selector specific") assert.Empty(t, out) }) + t.Run("unknown-firewall", func(t *testing.T) { out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "server", "--server", "non-existing-server", "non-existing-firewall") require.EqualError(t, err, "Firewall not found: non-existing-firewall") assert.Empty(t, out) }) + t.Run("unknown-server", func(t *testing.T) { out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "server", "--server", "non-existing-server", strconv.FormatInt(firewallID, 10)) require.EqualError(t, err, "Server not found: non-existing-server") assert.Empty(t, out) }) + t.Run("label-selector", func(t *testing.T) { out, err := runCommand(t, "firewall", "apply-to-resource", "--type", "label_selector", "--label-selector", "foo=bar", strconv.FormatInt(firewallID, 10)) require.NoError(t, err) @@ -140,9 +155,10 @@ func TestFirewall(t *testing.T) { }) }) - out, err = runCommand(t, "firewall", "describe", strconv.FormatInt(firewallID, 10)) - require.NoError(t, err) - assert.Regexp(t, `ID:\s+[0-9]+ + t.Run("describe", func(t *testing.T) { + out, err := runCommand(t, "firewall", "describe", strconv.FormatInt(firewallID, 10)) + require.NoError(t, err) + assert.Regexp(t, `ID:\s+[0-9]+ Name:\s+new-test-firewall-[0-9a-f]{8} Created:\s+.*? Labels: @@ -184,6 +200,7 @@ Applied To: \s+- Type:\s+label_selector \s+Label Selector:\s+foo=bar `, out) + }) t.Run("remove-from-resource", func(t *testing.T) { t.Run("unknown-type", func(t *testing.T) { @@ -191,26 +208,31 @@ Applied To: require.EqualError(t, err, "unknown type non-existing-type") assert.Empty(t, out) }) + t.Run("missing-server", func(t *testing.T) { out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "server", strconv.FormatInt(firewallID, 10)) require.EqualError(t, err, "type server need a --server specific") assert.Empty(t, out) }) + t.Run("missing-label-selector", func(t *testing.T) { out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "label_selector", strconv.FormatInt(firewallID, 10)) require.EqualError(t, err, "type label_selector need a --label-selector specific") assert.Empty(t, out) }) + t.Run("unknown-firewall", func(t *testing.T) { out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "server", "--server", "non-existing-server", "non-existing-firewall") require.EqualError(t, err, "Firewall not found: non-existing-firewall") assert.Empty(t, out) }) + t.Run("unknown-server", func(t *testing.T) { out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "server", "--server", "non-existing-server", strconv.FormatInt(firewallID, 10)) require.EqualError(t, err, "Server not found: non-existing-server") assert.Empty(t, out) }) + t.Run("label-selector", func(t *testing.T) { out, err := runCommand(t, "firewall", "remove-from-resource", "--type", "label_selector", "--label-selector", "foo=bar", strconv.FormatInt(firewallID, 10)) require.NoError(t, err) @@ -256,17 +278,25 @@ Applied To: }) }) - out, err = runCommand(t, "firewall", "replace-rules", "non-existing-firewall", "--rules-file", "rules_file.json") - require.EqualError(t, err, "Firewall not found: non-existing-firewall") - assert.Empty(t, out) + t.Run("replace-rules", func(t *testing.T) { + t.Run("non-existing-firewall", func(t *testing.T) { + out, err := runCommand(t, "firewall", "replace-rules", "non-existing-firewall", "--rules-file", "rules_file.json") + require.EqualError(t, err, "Firewall not found: non-existing-firewall") + assert.Empty(t, out) + }) - out, err = runCommand(t, "firewall", "replace-rules", strconv.FormatInt(firewallID, 10), "--rules-file", "rules_file.json") - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Firewall Rules for Firewall %d updated\n", firewallID), out) + t.Run("normal", func(t *testing.T) { + out, err := runCommand(t, "firewall", "replace-rules", strconv.FormatInt(firewallID, 10), "--rules-file", "rules_file.json") + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Firewall Rules for Firewall %d updated\n", firewallID), out) + }) + }) - out, err = runCommand(t, "firewall", "delete", strconv.FormatInt(firewallID, 10)) - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("firewall %d deleted\n", firewallID), out) + t.Run("delete", func(t *testing.T) { + out, err := runCommand(t, "firewall", "delete", strconv.FormatInt(firewallID, 10)) + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("firewall %d deleted\n", firewallID), out) + }) } func createFirewall(t *testing.T, name string, args ...string) (int64, error) { diff --git a/e2e_test/floatingip_test.go b/e2e_test/floatingip_test.go index 8ce02de7..26c710fc 100644 --- a/e2e_test/floatingip_test.go +++ b/e2e_test/floatingip_test.go @@ -20,86 +20,102 @@ import ( func TestFloatingIP(t *testing.T) { t.Parallel() - floatingIPName := withSuffix("test-floating-ip") + t.Run("ipv4", func(t *testing.T) { + floatingIPName := withSuffix("test-floating-ip") + _, err := createFloatingIP(t, floatingIPName, "") + require.EqualError(t, err, "type is required") - _, err := createFloatingIP(t, floatingIPName, "") - require.EqualError(t, err, "type is required") + _, err = createFloatingIP(t, floatingIPName, "ipv4") + require.EqualError(t, err, "one of --home-location or --server is required") - _, err = createFloatingIP(t, floatingIPName, "ipv4") - require.EqualError(t, err, "one of --home-location or --server is required") + _, err = createFloatingIP(t, floatingIPName, "ipv4", "--server", "non-existing-server") + require.EqualError(t, err, "server not found: non-existing-server") - _, err = createFloatingIP(t, floatingIPName, "ipv4", "--server", "non-existing-server") - require.EqualError(t, err, "server not found: non-existing-server") - - floatingIPId, err := createFloatingIP(t, floatingIPName, "ipv4", "--home-location", TestLocationName) - if err != nil { - t.Fatal(err) - } + floatingIPId, err := createFloatingIP(t, floatingIPName, "ipv4", "--home-location", TestLocationName) + require.NoError(t, err) - t.Run("labels", func(t *testing.T) { - t.Run("add-label-non-existing-floating-ip", func(t *testing.T) { - out, err := runCommand(t, "floating-ip", "add-label", "non-existing-floating-ip", "foo=bar") - require.EqualError(t, err, "floating IP not found: non-existing-floating-ip") - assert.Empty(t, out) + t.Run("labels", func(t *testing.T) { + t.Run("add-label-non-existing-floating-ip", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "add-label", "non-existing-floating-ip", "foo=bar") + require.EqualError(t, err, "floating IP not found: non-existing-floating-ip") + assert.Empty(t, out) + }) + + t.Run("add-label", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "add-label", strconv.FormatInt(floatingIPId, 10), "foo=bar") + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Label(s) foo added to Floating IP %d\n", floatingIPId), out) + }) }) - t.Run("add-label", func(t *testing.T) { - out, err := runCommand(t, "floating-ip", "add-label", strconv.FormatInt(floatingIPId, 10), "foo=bar") + t.Run("update-name", func(t *testing.T) { + floatingIPName = withSuffix("new-test-floating-ip") + out, err := runCommand(t, "floating-ip", "update", strconv.FormatInt(floatingIPId, 10), "--name", floatingIPName, "--description", "Some description") require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Label(s) foo added to Floating IP %d\n", floatingIPId), out) + assert.Equal(t, fmt.Sprintf("Floating IP %d updated\n", floatingIPId), out) }) - }) - - floatingIPName = withSuffix("new-test-floating-ip") - - out, err := runCommand(t, "floating-ip", "update", strconv.FormatInt(floatingIPId, 10), "--name", floatingIPName, "--description", "Some description") - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Floating IP %d updated\n", floatingIPId), out) - - out, err = runCommand(t, "floating-ip", "set-rdns", strconv.FormatInt(floatingIPId, 10), "--hostname", "s1.example.com") - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Reverse DNS of Floating IP %d changed\n", floatingIPId), out) - - out, err = runCommand(t, "floating-ip", "unassign", "non-existing-floating-ip") - require.EqualError(t, err, "Floating IP not found: non-existing-floating-ip") - assert.Empty(t, out) - out, err = runCommand(t, "floating-ip", "assign", "non-existing-floating-ip", "non-existing-server") - require.EqualError(t, err, "Floating IP not found: non-existing-floating-ip") - assert.Empty(t, out) - - out, err = runCommand(t, "floating-ip", "assign", strconv.FormatInt(floatingIPId, 10), "non-existing-server") - require.EqualError(t, err, "server not found: non-existing-server") - assert.Empty(t, out) - - t.Run("enable-protection", func(t *testing.T) { - t.Run("unknown-protection-level", func(t *testing.T) { - out, err := runCommand(t, "floating-ip", "enable-protection", strconv.FormatInt(floatingIPId, 10), "unknown-protection-level") - require.EqualError(t, err, "unknown protection level: unknown-protection-level") - assert.Empty(t, out) + t.Run("set-rnds", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "set-rdns", strconv.FormatInt(floatingIPId, 10), "--hostname", "s1.example.com") + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Reverse DNS of Floating IP %d changed\n", floatingIPId), out) }) - t.Run("non-existing-floating-ip", func(t *testing.T) { - out, err := runCommand(t, "floating-ip", "enable-protection", "non-existing-floating-ip", "delete") + t.Run("unassign-non-existing", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "unassign", "non-existing-floating-ip") require.EqualError(t, err, "Floating IP not found: non-existing-floating-ip") assert.Empty(t, out) }) - t.Run("enable-delete-protection", func(t *testing.T) { - out, err := runCommand(t, "floating-ip", "enable-protection", strconv.FormatInt(floatingIPId, 10), "delete") - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Resource protection enabled for floating IP %d\n", floatingIPId), out) + t.Run("assign", func(t *testing.T) { + t.Run("non-existing-ip", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "assign", "non-existing-floating-ip", "non-existing-server") + require.EqualError(t, err, "Floating IP not found: non-existing-floating-ip") + assert.Empty(t, out) + }) + + t.Run("non-existing-server", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "assign", strconv.FormatInt(floatingIPId, 10), "non-existing-server") + require.EqualError(t, err, "server not found: non-existing-server") + assert.Empty(t, out) + }) }) - }) - ipStr, err := runCommand(t, "floating-ip", "describe", strconv.FormatInt(floatingIPId, 10), "--output", "format={{.IP}}") - require.NoError(t, err) - ipStr = strings.TrimSpace(ipStr) - assert.Regexp(t, `^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$`, ipStr) + t.Run("enable-protection", func(t *testing.T) { + t.Run("unknown-protection-level", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "enable-protection", strconv.FormatInt(floatingIPId, 10), "unknown-protection-level") + require.EqualError(t, err, "unknown protection level: unknown-protection-level") + assert.Empty(t, out) + }) + + t.Run("non-existing-floating-ip", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "enable-protection", "non-existing-floating-ip", "delete") + require.EqualError(t, err, "Floating IP not found: non-existing-floating-ip") + assert.Empty(t, out) + }) + + t.Run("enable-delete-protection", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "enable-protection", strconv.FormatInt(floatingIPId, 10), "delete") + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Resource protection enabled for floating IP %d\n", floatingIPId), out) + }) + }) - out, err = runCommand(t, "floating-ip", "describe", strconv.FormatInt(floatingIPId, 10)) - require.NoError(t, err) - assert.Regexp(t, `ID:\s+[0-9]+ + var ipStr string + + t.Run("describe", func(t *testing.T) { + t.Run("format", func(t *testing.T) { + var err error + ipStr, err = runCommand(t, "floating-ip", "describe", strconv.FormatInt(floatingIPId, 10), "--output", "format={{.IP}}") + require.NoError(t, err) + ipStr = strings.TrimSpace(ipStr) + assert.Regexp(t, `^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$`, ipStr) + }) + + t.Run("normal", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "describe", strconv.FormatInt(floatingIPId, 10)) + require.NoError(t, err) + assert.Regexp(t, `ID:\s+[0-9]+ Type:\s+ipv4 Name:\s+new-test-floating-ip-[0-9a-f]{8} Description:\s+Some description @@ -116,16 +132,22 @@ Protection: Labels: \s+foo: bar `, out) + }) + }) - out, err = runCommand(t, "floating-ip", "list", "--output", "columns=id,name,type,ip,dns,server,home,blocked,protection,labels,created,age") - require.NoError(t, err) - assert.Regexp(t, `^ID +NAME +TYPE +IP +DNS +SERVER +HOME +BLOCKED +PROTECTION +LABELS +CREATED +AGE + t.Run("list", func(t *testing.T) { + t.Run("table", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "list", "--output", "columns=id,name,type,ip,dns,server,home,blocked,protection,labels,created,age") + require.NoError(t, err) + assert.Regexp(t, `^ID +NAME +TYPE +IP +DNS +SERVER +HOME +BLOCKED +PROTECTION +LABELS +CREATED +AGE [0-9]+ +new-test-floating-ip-[0-9a-f]{8} +ipv4 +(?:[0-9]{1,3}\.){3}[0-9]{1,3} +s1\.example\.com +- +[a-z]{3}[0-9]* +no +delete +foo=bar.*? $`, out) + }) - out, err = runCommand(t, "floating-ip", "list", "-o=json") - require.NoError(t, err) - assertjson.Equal(t, []byte(fmt.Sprintf(` + t.Run("json", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "list", "-o=json") + require.NoError(t, err) + assertjson.Equal(t, []byte(fmt.Sprintf(` [ { "id": %d, @@ -161,44 +183,62 @@ $`, out) } ] `, floatingIPId, ipStr, ipStr, TestLocationName, floatingIPName)), []byte(out)) + }) + }) - out, err = runCommand(t, "floating-ip", "delete", strconv.FormatInt(floatingIPId, 10)) - assert.Regexp(t, `^Floating IP deletion is protected \(protected, [0-9a-f]+\)$`, err.Error()) - assert.Empty(t, out) - - t.Run("disable-protection", func(t *testing.T) { - t.Run("non-existing-floating-ip", func(t *testing.T) { - out, err := runCommand(t, "floating-ip", "disable-protection", "non-existing-floating-ip", "delete") - require.EqualError(t, err, "Floating IP not found: non-existing-floating-ip") + t.Run("delete-protected", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "delete", strconv.FormatInt(floatingIPId, 10)) + assert.Regexp(t, `^Floating IP deletion is protected \(protected, [0-9a-f]+\)$`, err.Error()) assert.Empty(t, out) }) - t.Run("unknown-protection-level", func(t *testing.T) { - out, err := runCommand(t, "floating-ip", "disable-protection", strconv.FormatInt(floatingIPId, 10), "unknown-protection-level") - require.EqualError(t, err, "unknown protection level: unknown-protection-level") - assert.Empty(t, out) + t.Run("disable-protection", func(t *testing.T) { + t.Run("non-existing-floating-ip", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "disable-protection", "non-existing-floating-ip", "delete") + require.EqualError(t, err, "Floating IP not found: non-existing-floating-ip") + assert.Empty(t, out) + }) + + t.Run("unknown-protection-level", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "disable-protection", strconv.FormatInt(floatingIPId, 10), "unknown-protection-level") + require.EqualError(t, err, "unknown protection level: unknown-protection-level") + assert.Empty(t, out) + }) + + t.Run("disable-delete-protection", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "disable-protection", strconv.FormatInt(floatingIPId, 10), "delete") + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Resource protection disabled for floating IP %d\n", floatingIPId), out) + }) }) - t.Run("disable-delete-protection", func(t *testing.T) { - out, err = runCommand(t, "floating-ip", "disable-protection", strconv.FormatInt(floatingIPId, 10), "delete") + t.Run("delete", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "delete", strconv.FormatInt(floatingIPId, 10)) require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Resource protection disabled for floating IP %d\n", floatingIPId), out) + assert.Equal(t, fmt.Sprintf("Floating IP %d deleted\n", floatingIPId), out) }) }) - out, err = runCommand(t, "floating-ip", "delete", strconv.FormatInt(floatingIPId, 10)) - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Floating IP %d deleted\n", floatingIPId), out) - - floatingIPName = withSuffix("test-floating-ipv6") - floatingIPId, err = createFloatingIP(t, floatingIPName, "ipv6", "--home-location", TestLocationName) - if err != nil { - t.Fatal(err) - } + t.Run("ipv6", func(t *testing.T) { + floatingIPName := withSuffix("test-floating-ipv6") + floatingIPId, err := createFloatingIP(t, floatingIPName, "ipv6", "--home-location", TestLocationName) + require.NoError(t, err) - out, err = runCommand(t, "floating-ip", "describe", strconv.FormatInt(floatingIPId, 10)) - require.NoError(t, err) - assert.Regexp(t, `ID:\s+[0-9]+ + var ipStr string + + t.Run("describe", func(t *testing.T) { + t.Run("format", func(t *testing.T) { + var err error + ipStr, err = runCommand(t, "floating-ip", "describe", strconv.FormatInt(floatingIPId, 10), "--output", "format={{.IP}}") + require.NoError(t, err) + ipStr = strings.TrimSpace(ipStr) + assert.NotNil(t, net.ParseIP(ipStr)) + }) + + t.Run("normal", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "describe", strconv.FormatInt(floatingIPId, 10)) + require.NoError(t, err) + assert.Regexp(t, `ID:\s+[0-9]+ Type:\s+ipv6 Name:\s+test-floating-ipv6-[0-9a-f]{8} Description:\s+- @@ -215,32 +255,37 @@ Protection: Labels: \s+No labels `, out) + }) + }) - out, err = runCommand(t, "floating-ip", "describe", strconv.FormatInt(floatingIPId, 10), "--output", "format={{.IP}}") - require.NoError(t, err) - out = strings.TrimSpace(out) - ipv6 := net.ParseIP(out) - if ipv6 != nil { - out, err = runCommand(t, "floating-ip", "set-rdns", strconv.FormatInt(floatingIPId, 10), "--ip", ipv6.String()+"1", "--hostname", "s1.example.com") - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Reverse DNS of Floating IP %d changed\n", floatingIPId), out) - - out, err = runCommand(t, "floating-ip", "set-rdns", strconv.FormatInt(floatingIPId, 10), "--ip", ipv6.String()+"2", "--hostname", "s2.example.com") - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Reverse DNS of Floating IP %d changed\n", floatingIPId), out) - } else { - t.Errorf("invalid IPv6 address: %s", out) - } + t.Run("set-rdns", func(t *testing.T) { + t.Run("1", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "set-rdns", strconv.FormatInt(floatingIPId, 10), "--ip", ipStr+"1", "--hostname", "s1.example.com") + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Reverse DNS of Floating IP %d changed\n", floatingIPId), out) + }) + + t.Run("2", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "set-rdns", strconv.FormatInt(floatingIPId, 10), "--ip", ipStr+"2", "--hostname", "s2.example.com") + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Reverse DNS of Floating IP %d changed\n", floatingIPId), out) + }) + }) - out, err = runCommand(t, "floating-ip", "list", "-o", "columns=ip,dns") - require.NoError(t, err) - assert.Regexp(t, fmt.Sprintf(`^IP +DNS + t.Run("list", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "list", "-o", "columns=ip,dns") + require.NoError(t, err) + assert.Regexp(t, fmt.Sprintf(`^IP +DNS %s\/64 +2 entries -`, ipv6), out) +`, ipStr), out) + }) - out, err = runCommand(t, "floating-ip", "delete", strconv.FormatInt(floatingIPId, 10)) - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Floating IP %d deleted\n", floatingIPId), out) + t.Run("delete", func(t *testing.T) { + out, err := runCommand(t, "floating-ip", "delete", strconv.FormatInt(floatingIPId, 10)) + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Floating IP %d deleted\n", floatingIPId), out) + }) + }) } func createFloatingIP(t *testing.T, name, ipType string, args ...string) (int64, error) { diff --git a/e2e_test/network_test.go b/e2e_test/network_test.go index 8cf1985c..c632aae1 100644 --- a/e2e_test/network_test.go +++ b/e2e_test/network_test.go @@ -30,90 +30,144 @@ func TestNetwork(t *testing.T) { require.Error(t, err) assert.Regexp(t, `^name is already used \(uniqueness_error, [0-9a-f]+\)$`, err.Error()) - out, err = runCommand(t, "network", "enable-protection", strconv.FormatInt(networkID, 10), "non-existing-protection") - require.EqualError(t, err, "unknown protection level: non-existing-protection") - assert.Empty(t, out) - - out, err = runCommand(t, "network", "enable-protection", "non-existing-network", "delete") - require.EqualError(t, err, "network not found: non-existing-network") - assert.Empty(t, out) - - out, err = runCommand(t, "network", "enable-protection", strconv.FormatInt(networkID, 10), "delete") - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Resource protection enabled for network %d\n", networkID), out) + t.Run("enable-protection", func(t *testing.T) { + t.Run("non-existing-protection", func(t *testing.T) { + out, err := runCommand(t, "network", "enable-protection", strconv.FormatInt(networkID, 10), "non-existing-protection") + require.EqualError(t, err, "unknown protection level: non-existing-protection") + assert.Empty(t, out) + }) + + t.Run("non-existing-network", func(t *testing.T) { + out, err := runCommand(t, "network", "enable-protection", "non-existing-network", "delete") + require.EqualError(t, err, "network not found: non-existing-network") + assert.Empty(t, out) + }) + + t.Run("delete", func(t *testing.T) { + out, err := runCommand(t, "network", "enable-protection", strconv.FormatInt(networkID, 10), "delete") + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Resource protection enabled for network %d\n", networkID), out) + }) + }) - out, err = runCommand(t, "network", "list", "-o=columns=servers,ip_range,labels,protection,created,age") - require.NoError(t, err) - assert.Regexp(t, `SERVERS +IP RANGE +LABELS +PROTECTION +CREATED +AGE + t.Run("list", func(t *testing.T) { + out, err := runCommand(t, "network", "list", "-o=columns=servers,ip_range,labels,protection,created,age") + require.NoError(t, err) + assert.Regexp(t, `SERVERS +IP RANGE +LABELS +PROTECTION +CREATED +AGE 0 servers +10\.0\.0\.0/24 +delete .*? (?:just now|[0-9]+s) `, out) + }) - out, err = runCommand(t, "network", "change-ip-range", "--ip-range", "10.0.2.0/16", "non-existing-network") - require.EqualError(t, err, "network not found: non-existing-network") - assert.Empty(t, out) - - out, err = runCommand(t, "network", "change-ip-range", "--ip-range", "10.0.2.0/16", networkName) - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("IP range of network %d changed\n", networkID), out) - - out, err = runCommand(t, "network", "add-label", "non-existing-network", "foo=bar") - require.EqualError(t, err, "network not found: non-existing-network") - assert.Empty(t, out) - - out, err = runCommand(t, "network", "add-label", networkName, "foo=bar") - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Label(s) foo added to Network %d\n", networkID), out) - - out, err = runCommand(t, "network", "add-label", networkName, "baz=qux") - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Label(s) baz added to Network %d\n", networkID), out) + t.Run("change-ip-range", func(t *testing.T) { + t.Run("non-existing-network", func(t *testing.T) { + out, err := runCommand(t, "network", "change-ip-range", "--ip-range", "10.0.2.0/16", "non-existing-network") + require.EqualError(t, err, "network not found: non-existing-network") + assert.Empty(t, out) + }) + + t.Run("normal", func(t *testing.T) { + out, err := runCommand(t, "network", "change-ip-range", "--ip-range", "10.0.2.0/16", networkName) + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("IP range of network %d changed\n", networkID), out) + }) + }) - out, err = runCommand(t, "network", "remove-label", networkName, "baz") - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Label(s) baz removed from Network %d\n", networkID), out) + t.Run("labels", func(t *testing.T) { + t.Run("add", func(t *testing.T) { + t.Run("non-existing-network", func(t *testing.T) { + out, err := runCommand(t, "network", "add-label", "non-existing-network", "foo=bar") + require.EqualError(t, err, "network not found: non-existing-network") + assert.Empty(t, out) + }) + + t.Run("1", func(t *testing.T) { + out, err := runCommand(t, "network", "add-label", networkName, "foo=bar") + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Label(s) foo added to Network %d\n", networkID), out) + }) + + t.Run("2", func(t *testing.T) { + out, err := runCommand(t, "network", "add-label", networkName, "baz=qux") + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Label(s) baz added to Network %d\n", networkID), out) + }) + }) + + t.Run("remove", func(t *testing.T) { + out, err := runCommand(t, "network", "remove-label", networkName, "baz") + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Label(s) baz removed from Network %d\n", networkID), out) + }) + }) oldNetworkName := networkName networkName = withSuffix("new-test-network") - out, err = runCommand(t, "network", "update", oldNetworkName, "--name", networkName) - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Network %s updated\n", oldNetworkName), out) - - out, err = runCommand(t, "network", "delete", strconv.FormatInt(networkID, 10)) - assert.Empty(t, out) - assert.Regexp(t, `^network is delete protected \(protected, [0-9a-f]+\)$`, err.Error()) - - out, err = runCommand(t, "network", "add-subnet", "--type", "cloud", "--network-zone", "eu-central", "--ip-range", "10.0.16.0/24", "non-existing-network") - require.EqualError(t, err, "network not found: non-existing-network") - assert.Empty(t, out) + t.Run("update-name", func(t *testing.T) { + out, err := runCommand(t, "network", "update", oldNetworkName, "--name", networkName) + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Network %s updated\n", oldNetworkName), out) + }) - out, err = runCommand(t, "network", "add-subnet", "--type", "vswitch", "--vswitch-id", "42", "--network-zone", "eu-central", "--ip-range", "10.0.17.0/24", strconv.FormatInt(networkID, 10)) - assert.Empty(t, out) - assert.Regexp(t, `^vswitch not found \(service_error, [0-9a-f]+\)$`, err.Error()) + t.Run("delete-protected", func(t *testing.T) { + out, err := runCommand(t, "network", "delete", strconv.FormatInt(networkID, 10)) + assert.Empty(t, out) + assert.Regexp(t, `^network is delete protected \(protected, [0-9a-f]+\)$`, err.Error()) + }) - out, err = runCommand(t, "network", "add-subnet", "--type", "cloud", "--network-zone", "eu-central", "--ip-range", "10.0.16.0/24", strconv.FormatInt(networkID, 10)) - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Subnet added to network %d\n", networkID), out) + t.Run("add-subnet", func(t *testing.T) { + t.Run("non-existing-network", func(t *testing.T) { + out, err := runCommand(t, "network", "add-subnet", "--type", "cloud", "--network-zone", "eu-central", "--ip-range", "10.0.16.0/24", "non-existing-network") + require.EqualError(t, err, "network not found: non-existing-network") + assert.Empty(t, out) + }) + + t.Run("non-existing-vswitch", func(t *testing.T) { + out, err := runCommand(t, "network", "add-subnet", "--type", "vswitch", "--vswitch-id", "42", "--network-zone", "eu-central", "--ip-range", "10.0.17.0/24", strconv.FormatInt(networkID, 10)) + assert.Empty(t, out) + assert.Regexp(t, `^vswitch not found \(service_error, [0-9a-f]+\)$`, err.Error()) + }) + + t.Run("normal", func(t *testing.T) { + out, err := runCommand(t, "network", "add-subnet", "--type", "cloud", "--network-zone", "eu-central", "--ip-range", "10.0.16.0/24", strconv.FormatInt(networkID, 10)) + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Subnet added to network %d\n", networkID), out) + }) + }) - out, err = runCommand(t, "network", "add-route", "--destination", "10.100.1.0/24", "--gateway", "10.0.1.1", "non-existing-network") - require.EqualError(t, err, "network not found: non-existing-network") - assert.Empty(t, out) + t.Run("add-route", func(t *testing.T) { + t.Run("non-existing-network", func(t *testing.T) { + out, err := runCommand(t, "network", "add-route", "--destination", "10.100.1.0/24", "--gateway", "10.0.1.1", "non-existing-network") + require.EqualError(t, err, "network not found: non-existing-network") + assert.Empty(t, out) - out, err = runCommand(t, "network", "add-route", "--destination", "10.100.1.0/24", "--gateway", "10.0.1.1", strconv.FormatInt(networkID, 10)) - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Route added to network %d\n", networkID), out) + }) - out, err = runCommand(t, "network", "expose-routes-to-vswitch", "non-existing-network") - require.EqualError(t, err, "network not found: non-existing-network") - assert.Empty(t, out) + t.Run("normal", func(t *testing.T) { + out, err := runCommand(t, "network", "add-route", "--destination", "10.100.1.0/24", "--gateway", "10.0.1.1", strconv.FormatInt(networkID, 10)) + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Route added to network %d\n", networkID), out) + }) + }) - out, err = runCommand(t, "network", "expose-routes-to-vswitch", strconv.FormatInt(networkID, 10)) - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Exposing routes to connected vSwitch of network %s enabled\n", networkName), out) + t.Run("expose-routes-to-vswitch", func(t *testing.T) { + t.Run("non-existing-network", func(t *testing.T) { + out, err := runCommand(t, "network", "expose-routes-to-vswitch", "non-existing-network") + require.EqualError(t, err, "network not found: non-existing-network") + assert.Empty(t, out) + }) + + t.Run("normal", func(t *testing.T) { + out, err := runCommand(t, "network", "expose-routes-to-vswitch", strconv.FormatInt(networkID, 10)) + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Exposing routes to connected vSwitch of network %s enabled\n", networkName), out) + }) + }) - out, err = runCommand(t, "network", "describe", strconv.FormatInt(networkID, 10)) - require.NoError(t, err) - assert.Regexp(t, `^ID:\s+[0-9]+ + t.Run("describe", func(t *testing.T) { + out, err := runCommand(t, "network", "describe", strconv.FormatInt(networkID, 10)) + require.NoError(t, err) + assert.Regexp(t, `^ID:\s+[0-9]+ Name:\s+new-test-network-[0-9a-f]{8} Created:\s+.*? IP Range:\s+10\.0\.0\.0\/16 @@ -131,10 +185,12 @@ Protection: Labels: \s+foo: bar $`, out) + }) - out, err = runCommand(t, "network", "list", "-o=json") - require.NoError(t, err) - assertjson.Equal(t, []byte(fmt.Sprintf(` + t.Run("list", func(t *testing.T) { + out, err := runCommand(t, "network", "list", "-o=json") + require.NoError(t, err) + assertjson.Equal(t, []byte(fmt.Sprintf(` [ { "id": %d, @@ -166,42 +222,66 @@ $`, out) } ] `, networkID, networkName)), []byte(out)) + }) - out, err = runCommand(t, "network", "remove-route", "--destination", "10.100.1.0/24", "--gateway", "10.0.1.1", "non-existing-network") - require.EqualError(t, err, "network not found: non-existing-network") - assert.Empty(t, out) - - out, err = runCommand(t, "network", "remove-route", "--destination", "10.100.1.0/24", "--gateway", "10.0.1.1", strconv.FormatInt(networkID, 10)) - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Route removed from network %d\n", networkID), out) - - out, err = runCommand(t, "network", "remove-subnet", "--ip-range", "10.0.16.0/24", "non-existing-network") - require.EqualError(t, err, "network not found: non-existing-network") - assert.Empty(t, out) - - out, err = runCommand(t, "network", "remove-subnet", "--ip-range", "10.0.16.0/24", strconv.FormatInt(networkID, 10)) - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Subnet 10.0.16.0/24 removed from network %d\n", networkID), out) + t.Run("remove-route", func(t *testing.T) { + t.Run("non-existing-network", func(t *testing.T) { + out, err := runCommand(t, "network", "remove-route", "--destination", "10.100.1.0/24", "--gateway", "10.0.1.1", "non-existing-network") + require.EqualError(t, err, "network not found: non-existing-network") + assert.Empty(t, out) + }) + + t.Run("normal", func(t *testing.T) { + out, err := runCommand(t, "network", "remove-route", "--destination", "10.100.1.0/24", "--gateway", "10.0.1.1", strconv.FormatInt(networkID, 10)) + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Route removed from network %d\n", networkID), out) + }) + }) - out, err = runCommand(t, "network", "disable-protection", "non-existing-network", "delete") - require.EqualError(t, err, "network not found: non-existing-network") - assert.Empty(t, out) + t.Run("remove-subnet", func(t *testing.T) { + t.Run("non-existing-network", func(t *testing.T) { + out, err := runCommand(t, "network", "remove-subnet", "--ip-range", "10.0.16.0/24", "non-existing-network") + require.EqualError(t, err, "network not found: non-existing-network") + assert.Empty(t, out) + }) + + t.Run("normal", func(t *testing.T) { + out, err := runCommand(t, "network", "remove-subnet", "--ip-range", "10.0.16.0/24", strconv.FormatInt(networkID, 10)) + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Subnet 10.0.16.0/24 removed from network %d\n", networkID), out) + }) + }) - out, err = runCommand(t, "network", "disable-protection", strconv.FormatInt(networkID, 10), "delete") - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Resource protection disabled for network %d\n", networkID), out) + t.Run("disable-protection", func(t *testing.T) { + t.Run("non-existing-network", func(t *testing.T) { + out, err := runCommand(t, "network", "disable-protection", "non-existing-network", "delete") + require.EqualError(t, err, "network not found: non-existing-network") + assert.Empty(t, out) + }) + + t.Run("normal", func(t *testing.T) { + out, err := runCommand(t, "network", "disable-protection", strconv.FormatInt(networkID, 10), "delete") + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Resource protection disabled for network %d\n", networkID), out) + }) + }) - out, err = runCommand(t, "network", "remove-label", strconv.FormatInt(networkID, 10), "foo") - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Label(s) foo removed from Network %d\n", networkID), out) + t.Run("remove-label", func(t *testing.T) { + out, err := runCommand(t, "network", "remove-label", strconv.FormatInt(networkID, 10), "foo") + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Label(s) foo removed from Network %d\n", networkID), out) + }) - out, err = runCommand(t, "network", "expose-routes-to-vswitch", "--disable", strconv.FormatInt(networkID, 10)) - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Exposing routes to connected vSwitch of network %s disabled\n", networkName), out) + t.Run("disable-expose-routes-to-vswitch", func(t *testing.T) { + out, err := runCommand(t, "network", "expose-routes-to-vswitch", "--disable", strconv.FormatInt(networkID, 10)) + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Exposing routes to connected vSwitch of network %s disabled\n", networkName), out) + }) - out, err = runCommand(t, "network", "describe", strconv.FormatInt(networkID, 10)) - require.NoError(t, err) - assert.Regexp(t, `^ID:\s+[0-9]+ + t.Run("describe", func(t *testing.T) { + out, err := runCommand(t, "network", "describe", strconv.FormatInt(networkID, 10)) + require.NoError(t, err) + assert.Regexp(t, `^ID:\s+[0-9]+ Name:\s+new-test-network-[0-9a-f]{8} Created:\s+.*? IP Range:\s+10\.0\.0\.0\/16 @@ -215,10 +295,13 @@ Protection: Labels: \s+No labels $`, out) + }) - out, err = runCommand(t, "network", "delete", strconv.FormatInt(networkID, 10)) - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Network %d deleted\n", networkID), out) + t.Run("delete", func(t *testing.T) { + out, err := runCommand(t, "network", "delete", strconv.FormatInt(networkID, 10)) + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Network %d deleted\n", networkID), out) + }) } func createNetwork(t *testing.T, name string, args ...string) (int64, error) { diff --git a/e2e_test/placement_group_test.go b/e2e_test/placement_group_test.go index d9bb2415..4225ac55 100644 --- a/e2e_test/placement_group_test.go +++ b/e2e_test/placement_group_test.go @@ -26,46 +26,48 @@ func TestPlacementGroup(t *testing.T) { pgID, err := createPlacementGroup(t, pgName, "--type", "spread") require.NoError(t, err) - out, err = runCommand(t, "placement-group", "add-label", "non-existing-placement-group", "foo=bar") - require.EqualError(t, err, "placement group not found: non-existing-placement-group") - assert.Empty(t, out) - - out, err = runCommand(t, "placement-group", "add-label", pgName, "foo=bar") - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Label(s) foo added to placement group %d\n", pgID), out) - - out, err = runCommand(t, "placement-group", "add-label", pgName, "baz=qux") - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Label(s) baz added to placement group %d\n", pgID), out) + t.Run("add-label", func(t *testing.T) { + t.Run("non-existing-placement-group", func(t *testing.T) { + out, err = runCommand(t, "placement-group", "add-label", "non-existing-placement-group", "foo=bar") + require.EqualError(t, err, "placement group not found: non-existing-placement-group") + assert.Empty(t, out) + }) + + t.Run("1", func(t *testing.T) { + out, err = runCommand(t, "placement-group", "add-label", pgName, "foo=bar") + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Label(s) foo added to placement group %d\n", pgID), out) + }) + + t.Run("2", func(t *testing.T) { + out, err = runCommand(t, "placement-group", "add-label", pgName, "baz=qux") + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Label(s) baz added to placement group %d\n", pgID), out) + }) + }) oldPgName := pgName pgName = withSuffix("new-test-placement-group") - out, err = runCommand(t, "placement-group", "update", oldPgName, "--name", pgName) - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("placement group %s updated\n", oldPgName), out) + t.Run("update-name", func(t *testing.T) { + out, err := runCommand(t, "placement-group", "update", oldPgName, "--name", pgName) + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("placement group %s updated\n", oldPgName), out) + }) - out, err = runCommand(t, "placement-group", "list", "-o=columns=id,name,servers,type,created,age") - require.NoError(t, err) - assert.Regexp(t, `ID +NAME +SERVERS +TYPE +CREATED +AGE + t.Run("list", func(t *testing.T) { + t.Run("table", func(t *testing.T) { + out, err := runCommand(t, "placement-group", "list", "-o=columns=id,name,servers,type,created,age") + require.NoError(t, err) + assert.Regexp(t, `ID +NAME +SERVERS +TYPE +CREATED +AGE [0-9]+ +new-test-placement-group-[0-9a-f]{8} +0 servers +spread .*? (?:just now|[0-9]+s) `, out) + }) - out, err = runCommand(t, "placement-group", "describe", strconv.FormatInt(pgID, 10)) - require.NoError(t, err) - assert.Regexp(t, `^ID:\s+[0-9]+ -Name:\s+new-test-placement-group-[0-9a-f]{8} -Created:\s+.*? -Labels: -\s+(baz: qux|foo: bar) -\s+(baz: qux|foo: bar) -Servers: -Type:\s+spread -$`, out) - - out, err = runCommand(t, "placement-group", "list", "-o=json") - require.NoError(t, err) - assertjson.Equal(t, []byte(fmt.Sprintf(` + t.Run("json", func(t *testing.T) { + out, err := runCommand(t, "placement-group", "list", "-o=json") + require.NoError(t, err) + assertjson.Equal(t, []byte(fmt.Sprintf(` [ { "id": %d, @@ -79,14 +81,34 @@ $`, out) "type": "spread" } ]`, pgID, pgName)), []byte(out)) + }) + }) - out, err = runCommand(t, "placement-group", "remove-label", pgName, "baz") - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("Label(s) baz removed from placement group %d\n", pgID), out) + t.Run("describe", func(t *testing.T) { + out, err := runCommand(t, "placement-group", "describe", strconv.FormatInt(pgID, 10)) + require.NoError(t, err) + assert.Regexp(t, `^ID:\s+[0-9]+ +Name:\s+new-test-placement-group-[0-9a-f]{8} +Created:\s+.*? +Labels: +\s+(baz: qux|foo: bar) +\s+(baz: qux|foo: bar) +Servers: +Type:\s+spread +$`, out) + }) - out, err = runCommand(t, "placement-group", "delete", strconv.FormatInt(pgID, 10)) - require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("placement group %d deleted\n", pgID), out) + t.Run("remove-label", func(t *testing.T) { + out, err := runCommand(t, "placement-group", "remove-label", pgName, "baz") + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("Label(s) baz removed from placement group %d\n", pgID), out) + }) + + t.Run("delete", func(t *testing.T) { + out, err := runCommand(t, "placement-group", "delete", strconv.FormatInt(pgID, 10)) + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("placement group %d deleted\n", pgID), out) + }) } func createPlacementGroup(t *testing.T, name string, args ...string) (int64, error) {