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] 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 }