c/shepherd/equinix/wrapngo: isolate live API tests

So far all wrapngo tests were fired directly against a live Equinix
endpoint, and the entire test harness was skipped if such an endpoint
was not configured/available.

This consolidates all of the live tests into a single test with
sub-tests, and only that test is skipped if endpoint data is not
provided.

This will in turn allow us to have some unit/regression tests for
wrapngo that do not need to contact the live Equinix API.

Change-Id: I2590a41b935b5d5417520d7510025f6289cece63
Reviewed-on: https://review.monogon.dev/c/monogon/+/1557
Tested-by: Jenkins CI
Reviewed-by: Tim Windelschmidt <tim@monogon.tech>
diff --git a/cloud/shepherd/equinix/wrapngo/BUILD.bazel b/cloud/shepherd/equinix/wrapngo/BUILD.bazel
index 3694fe1..166ee76 100644
--- a/cloud/shepherd/equinix/wrapngo/BUILD.bazel
+++ b/cloud/shepherd/equinix/wrapngo/BUILD.bazel
@@ -19,7 +19,7 @@
 go_test(
     name = "wrapngo_test",
     timeout = "eternal",
-    srcs = ["wrapngo_test.go"],
+    srcs = ["wrapngo_live_test.go"],
     args = ["-test.v"],
     embed = [":wrapngo"],
     deps = [
diff --git a/cloud/shepherd/equinix/wrapngo/wrapngo_live_test.go b/cloud/shepherd/equinix/wrapngo/wrapngo_live_test.go
new file mode 100644
index 0000000..5a8d194
--- /dev/null
+++ b/cloud/shepherd/equinix/wrapngo/wrapngo_live_test.go
@@ -0,0 +1,344 @@
+package wrapngo
+
+import (
+	"context"
+	"crypto/ed25519"
+	"crypto/rand"
+	"errors"
+	"fmt"
+	"log"
+	"os"
+	"testing"
+	"time"
+
+	"github.com/packethost/packngo"
+	"golang.org/x/crypto/ssh"
+)
+
+type liveTestClient struct {
+	cl  *client
+	ctx context.Context
+
+	apipid string
+	apios  string
+
+	sshKeyLabel        string
+	testDeviceHostname string
+}
+
+func newLiveTestClient(t *testing.T) *liveTestClient {
+	t.Helper()
+
+	apiuser := os.Getenv("EQUINIX_USER")
+	apikey := os.Getenv("EQUINIX_APIKEY")
+	apipid := os.Getenv("EQUINIX_PROJECT_ID")
+	apios := os.Getenv("EQUINIX_DEVICE_OS")
+
+	if apiuser == "" {
+		t.Skip("EQUINIX_USER must be set.")
+	}
+	if apikey == "" {
+		t.Skip("EQUINIX_APIKEY must be set.")
+	}
+	if apipid == "" {
+		t.Skip("EQUINIX_PROJECT_ID must be set.")
+	}
+	if apios == "" {
+		t.Skip("EQUINIX_DEVICE_OS must be set.")
+	}
+	ctx, ctxC := context.WithCancel(context.Background())
+	t.Cleanup(ctxC)
+	return &liveTestClient{
+		cl: new(&Opts{
+			User:   apiuser,
+			APIKey: apikey,
+		}),
+		ctx: ctx,
+
+		apipid: apipid,
+		apios:  apios,
+
+		sshKeyLabel:        "shepherd-livetest-client",
+		testDeviceHostname: "shepherd-livetest-device",
+	}
+}
+
+// awaitDeviceState returns nil after device matching the id reaches one of the
+// provided states. It will return a non-nil value in case of an API error, and
+// particularly if there exists no device matching id.
+func (l *liveTestClient) awaitDeviceState(t *testing.T, id string, states ...string) error {
+	t.Helper()
+
+	for {
+		d, err := l.cl.GetDevice(l.ctx, l.apipid, id)
+		if err != nil {
+			if errors.Is(err, os.ErrDeadlineExceeded) {
+				continue
+			}
+			return fmt.Errorf("while fetching device info: %w", err)
+		}
+		if d == nil {
+			return fmt.Errorf("expected the test device (ID: %s) to exist.", id)
+		}
+		for _, s := range states {
+			if d.State == s {
+				return nil
+			}
+		}
+		t.Logf("Waiting for device to be provisioned (ID: %s, current state: %q)", id, d.State)
+		time.Sleep(time.Second)
+	}
+}
+
+// cleanup ensures both the test device and the test key are deleted at
+// Equinix.
+func (l *liveTestClient) cleanup(t *testing.T) {
+	t.Helper()
+
+	t.Logf("Cleaning up.")
+
+	// Ensure the device matching testDeviceHostname is deleted.
+	ds, err := l.cl.ListDevices(l.ctx, l.apipid)
+	if err != nil {
+		log.Fatalf("while listing devices: %v", err)
+	}
+	var td *packngo.Device
+	for _, d := range ds {
+		if d.Hostname == l.testDeviceHostname {
+			td = &d
+			break
+		}
+	}
+	if td != nil {
+		t.Logf("Found a test device (ID: %s) that needs to be deleted before progressing further.", td.ID)
+
+		// Devices currently being provisioned can't be deleted. After it's
+		// provisioned, device's state will match either "active", or "failed".
+		if err := l.awaitDeviceState(t, "active", "failed"); err != nil {
+			t.Fatalf("while waiting for device to be provisioned: %v", err)
+		}
+		if err := l.cl.deleteDevice(l.ctx, td.ID); err != nil {
+			t.Fatalf("while deleting test device: %v", err)
+		}
+	}
+
+	// Ensure the key matching sshKeyLabel is deleted.
+	ks, err := l.cl.ListSSHKeys(l.ctx)
+	if err != nil {
+		t.Fatalf("while listing SSH keys: %v", err)
+	}
+	for _, k := range ks {
+		if k.Label == l.sshKeyLabel {
+			t.Logf("Found a SSH test key (ID: %s) - deleting...", k.ID)
+			if err := l.cl.deleteSSHKey(l.ctx, k.ID); err != nil {
+				t.Fatalf("while deleting an SSH key: %v", err)
+			}
+			t.Logf("Deleted a SSH test key (ID: %s).", k.ID)
+		}
+	}
+}
+
+// createSSHAuthKey returns an SSH public key in OpenSSH authorized_keys
+// format.
+func createSSHAuthKey(t *testing.T) string {
+	t.Helper()
+	pub, _, err := ed25519.GenerateKey(rand.Reader)
+	if err != nil {
+		t.Errorf("while generating SSH key: %v", err)
+	}
+
+	sshpub, err := ssh.NewPublicKey(pub)
+	if err != nil {
+		t.Errorf("while generating SSH public key: %v", err)
+	}
+	return string(ssh.MarshalAuthorizedKey(sshpub))
+}
+
+// TestLiveAPI performs smoke tests of wrapngo against the real Equinix API. See
+// newLiveTestClient to see which environment variables need to be provided in
+// order for this test to run.
+func TestLiveAPI(t *testing.T) {
+	ltc := newLiveTestClient(t)
+	ltc.cleanup(t)
+
+	cl := ltc.cl
+	ctx := ltc.ctx
+
+	t.Run("ListReservations", func(t *testing.T) {
+		_, err := cl.ListReservations(ctx, ltc.apipid)
+		if err != nil {
+			t.Errorf("while listing hardware reservations: %v", err)
+		}
+	})
+
+	var sshKeyID string
+	t.Run("CreateSSHKey", func(t *testing.T) {
+		nk, err := cl.CreateSSHKey(ctx, &packngo.SSHKeyCreateRequest{
+			Label:     ltc.sshKeyLabel,
+			Key:       createSSHAuthKey(t),
+			ProjectID: ltc.apipid,
+		})
+		if err != nil {
+			t.Fatalf("while creating an SSH key: %v", err)
+		}
+		if nk.Label != ltc.sshKeyLabel {
+			t.Errorf("key labels don't match.")
+		}
+		t.Logf("Created an SSH key (ID: %s)", nk.ID)
+		sshKeyID = nk.ID
+	})
+
+	var dummySSHPK2 string
+	t.Run("UpdateSSHKey", func(t *testing.T) {
+		if sshKeyID == "" {
+			t.Skip("SSH key couldn't have been created - skipping...")
+		}
+
+		dummySSHPK2 = createSSHAuthKey(t)
+		k, err := cl.UpdateSSHKey(ctx, sshKeyID, &packngo.SSHKeyUpdateRequest{
+			Key: &dummySSHPK2,
+		})
+		if err != nil {
+			t.Fatalf("while updating an SSH key: %v", err)
+		}
+		if k.Key != dummySSHPK2 {
+			t.Errorf("updated SSH key doesn't match the original.")
+		}
+	})
+	t.Run("GetSSHKey", func(t *testing.T) {
+		if sshKeyID == "" {
+			t.Skip("SSH key couldn't have been created - skipping...")
+		}
+
+		k, err := cl.getSSHKey(ctx, sshKeyID)
+		if err != nil {
+			t.Fatalf("while getting an SSH key: %v", err)
+		}
+		if k.Key != dummySSHPK2 {
+			t.Errorf("got key contents that don't match the original.")
+		}
+	})
+	t.Run("ListSSHKeys", func(t *testing.T) {
+		if sshKeyID == "" {
+			t.Skip("SSH key couldn't have been created - skipping...")
+		}
+
+		ks, err := cl.ListSSHKeys(ctx)
+		if err != nil {
+			t.Fatalf("while listing SSH keys: %v", err)
+		}
+
+		// Check that our key is part of the list.
+		found := false
+		for _, k := range ks {
+			if k.ID == sshKeyID {
+				found = true
+				break
+			}
+		}
+		if !found {
+			t.Errorf("SSH key not listed.")
+		}
+	})
+
+	var testDevice *packngo.Device
+	t.Run("CreateDevice", func(t *testing.T) {
+		// Find a provisionable hardware reservation the device will be created with.
+		rvs, err := cl.ListReservations(ctx, ltc.apipid)
+		if err != nil {
+			t.Errorf("while listing hardware reservations: %v", err)
+		}
+		var rv *packngo.HardwareReservation
+		for _, r := range rvs {
+			if r.Provisionable {
+				rv = &r
+				break
+			}
+		}
+		if rv == nil {
+			t.Skip("could not find a provisionable hardware reservation - skipping...")
+		}
+
+		d, err := cl.CreateDevice(ctx, &packngo.DeviceCreateRequest{
+			Hostname:              ltc.testDeviceHostname,
+			OS:                    ltc.apios,
+			Plan:                  rv.Plan.Slug,
+			HardwareReservationID: rv.ID,
+			ProjectID:             ltc.apipid,
+		})
+		if err != nil {
+			t.Fatalf("while creating a device: %v", err)
+		}
+		t.Logf("Created a new test device (ID: %s)", d.ID)
+		testDevice = d
+	})
+	t.Run("GetDevice", func(t *testing.T) {
+		if testDevice == nil {
+			t.Skip("the test device couldn't have been created - skipping...")
+		}
+
+		d, err := cl.GetDevice(ctx, ltc.apipid, testDevice.ID)
+		if err != nil {
+			t.Fatalf("while fetching device info: %v", err)
+		}
+		if d == nil {
+			t.Fatalf("expected the test device (ID: %s) to exist.", testDevice.ID)
+		}
+		if d.ID != testDevice.ID {
+			t.Errorf("got device ID that doesn't match the original.")
+		}
+	})
+	t.Run("ListDevices", func(t *testing.T) {
+		if testDevice == nil {
+			t.Skip("the test device couldn't have been created - skipping...")
+		}
+
+		ds, err := cl.ListDevices(ctx, ltc.apipid)
+		if err != nil {
+			t.Errorf("while listing devices: %v", err)
+		}
+		if len(ds) == 0 {
+			t.Errorf("expected at least one device.")
+		}
+	})
+	t.Run("DeleteDevice", func(t *testing.T) {
+		if testDevice == nil {
+			t.Skip("the test device couldn't have been created - skipping...")
+		}
+
+		// Devices currently being provisioned can't be deleted. After it's
+		// provisioned, device's state will match either "active", or "failed".
+		if err := ltc.awaitDeviceState(t, testDevice.ID, "active", "failed"); err != nil {
+			t.Fatalf("while waiting for device to be provisioned: %v", err)
+		}
+		t.Logf("Deleting the test device (ID: %s)", testDevice.ID)
+		if err := cl.deleteDevice(ctx, testDevice.ID); err != nil {
+			t.Fatalf("while deleting a device: %v", err)
+		}
+		d, err := cl.GetDevice(ctx, ltc.apipid, testDevice.ID)
+		if err != nil && !IsNotFound(err) {
+			t.Fatalf("while fetching device info: %v", err)
+		}
+		if d != nil {
+			t.Fatalf("device should not exist.")
+		}
+		t.Logf("Deleted the test device (ID: %s)", testDevice.ID)
+	})
+	t.Run("DeleteSSHKey", func(t *testing.T) {
+		if sshKeyID == "" {
+			t.Skip("SSH key couldn't have been created - skipping...")
+		}
+
+		t.Logf("Deleting the test SSH key (ID: %s)", sshKeyID)
+		if err := cl.deleteSSHKey(ctx, sshKeyID); err != nil {
+			t.Fatalf("couldn't delete an SSH key: %v", err)
+		}
+		_, err := cl.getSSHKey(ctx, sshKeyID)
+		if err == nil {
+			t.Fatalf("SSH key should not exist")
+		}
+		t.Logf("Deleted the test SSH key (ID: %s)", sshKeyID)
+	})
+
+	ltc.cleanup(t)
+}
diff --git a/cloud/shepherd/equinix/wrapngo/wrapngo_test.go b/cloud/shepherd/equinix/wrapngo/wrapngo_test.go
deleted file mode 100644
index d69ff4e..0000000
--- a/cloud/shepherd/equinix/wrapngo/wrapngo_test.go
+++ /dev/null
@@ -1,412 +0,0 @@
-package wrapngo
-
-import (
-	"context"
-	"crypto/ed25519"
-	"crypto/rand"
-	"errors"
-	"fmt"
-	"log"
-	"os"
-	"testing"
-	"time"
-
-	"github.com/packethost/packngo"
-	"golang.org/x/crypto/ssh"
-)
-
-var (
-	ctx context.Context
-
-	// apiuser and apikey are the Equinix credentials necessary to test the
-	// client package.
-
-	apiuser string = os.Getenv("EQUINIX_USER")
-	apikey  string = os.Getenv("EQUINIX_APIKEY")
-
-	// apipid references the Equinix Metal project used. It's recommended to use
-	// non-production projects in the context of testing.
-	apipid string = os.Getenv("EQUINIX_PROJECT_ID")
-	// apios specifies the operating system installed on newly provisioned
-	// devices. See Equinix Metal API documentation for details.
-	apios string = os.Getenv("EQUINIX_DEVICE_OS")
-
-	// sshKeyID identifies the SSH public key registered with Equinix.
-	sshKeyID string
-	// sshKeyLabel is the label used to register the SSH key with Equinix.
-	sshKeyLabel string = "shepherd-client-testkey"
-
-	// testDevice is the device created in TestCreateDevice, and later
-	// referenced to exercise implementation operating on Equinix Metal device
-	// objects.
-	testDevice *packngo.Device
-	// testDeviceHostname is the hostname used to register and reference the
-	// test device.
-	testDeviceHostname string = "shepherd-client-testdev"
-)
-
-// ensureParams returns false if any of the required environment variable
-// parameters are missing.
-func ensureParams() bool {
-	if apiuser == "" {
-		log.Print("EQUINIX_USER must be set.")
-		return false
-	}
-	if apikey == "" {
-		log.Print("EQUINIX_APIKEY must be set.")
-		return false
-	}
-	if apipid == "" {
-		log.Print("EQUINIX_PROJECT_ID must be set.")
-		return false
-	}
-	if apios == "" {
-		log.Print("EQUINIX_DEVICE_OS must be set.")
-		return false
-	}
-	return true
-}
-
-// awaitDeviceState returns nil after device matching the id reaches one of the
-// provided states. It will return a non-nil value in case of an API error, and
-// particularly if there exists no device matching id.
-func awaitDeviceState(ctx context.Context, t *testing.T, cl *client, id string, states ...string) error {
-	if t != nil {
-		t.Helper()
-	}
-
-	for {
-		d, err := cl.GetDevice(ctx, apipid, id)
-		if err != nil {
-			if errors.Is(err, os.ErrDeadlineExceeded) {
-				continue
-			}
-			return fmt.Errorf("while fetching device info: %w", err)
-		}
-		if d == nil {
-			return fmt.Errorf("expected the test device (ID: %s) to exist.", id)
-		}
-		for _, s := range states {
-			if d.State == s {
-				return nil
-			}
-		}
-		log.Printf("Waiting for device to be provisioned (ID: %s, current state: %q)", id, d.State)
-		time.Sleep(time.Second)
-	}
-}
-
-// cleanup ensures both the test device and the test key are deleted at
-// Equinix.
-func cleanup(ctx context.Context, cl *client) {
-	log.Print("Cleaning up.")
-
-	// Ensure the device matching testDeviceHostname is deleted.
-	ds, err := cl.ListDevices(ctx, apipid)
-	if err != nil {
-		log.Fatalf("while listing devices: %v", err)
-	}
-	var td *packngo.Device
-	for _, d := range ds {
-		if d.Hostname == testDeviceHostname {
-			td = &d
-			break
-		}
-	}
-	if td != nil {
-		log.Printf("Found a test device (ID: %s) that needs to be deleted before progressing further.", td.ID)
-
-		// Devices currently being provisioned can't be deleted. After it's
-		// provisioned, device's state will match either "active", or "failed".
-		if err := awaitDeviceState(ctx, nil, cl, td.ID, "active", "failed"); err != nil {
-			log.Fatalf("while waiting for device to be provisioned: %v", err)
-		}
-		if err := cl.deleteDevice(ctx, td.ID); err != nil {
-			log.Fatalf("while deleting test device: %v", err)
-		}
-	}
-
-	// Ensure the key matching sshKeyLabel is deleted.
-	ks, err := cl.ListSSHKeys(ctx)
-	if err != nil {
-		log.Fatalf("while listing SSH keys: %v", err)
-	}
-	for _, k := range ks {
-		if k.Label == sshKeyLabel {
-			log.Printf("Found a SSH test key (ID: %s) - deleting...", k.ID)
-			if err := cl.deleteSSHKey(ctx, k.ID); err != nil {
-				log.Fatalf("while deleting an SSH key: %v", err)
-			}
-			log.Printf("Deleted a SSH test key (ID: %s).", k.ID)
-		}
-	}
-}
-
-func TestMain(m *testing.M) {
-	if !ensureParams() {
-		log.Print("Skipping due to missing parameters.")
-		return
-	}
-	ctx = context.Background()
-
-	cl := new(&Opts{
-		User:   apiuser,
-		APIKey: apikey,
-	})
-	defer cl.Close()
-
-	cleanup(ctx, cl)
-	code := m.Run()
-	cleanup(ctx, cl)
-	os.Exit(code)
-}
-
-// Most test cases depend on the preceding cases having been executed. The
-// test cases can't be run in parallel.
-
-func TestListReservations(t *testing.T) {
-	cl := new(&Opts{
-		User:   apiuser,
-		APIKey: apikey,
-	})
-
-	_, err := cl.ListReservations(ctx, apipid)
-	if err != nil {
-		t.Errorf("while listing hardware reservations: %v", err)
-	}
-}
-
-// createSSHAuthKey returns an SSH public key in OpenSSH authorized_keys
-// format.
-func createSSHAuthKey(t *testing.T) string {
-	t.Helper()
-	pub, _, err := ed25519.GenerateKey(rand.Reader)
-	if err != nil {
-		t.Errorf("while generating SSH key: %v", err)
-	}
-
-	sshpub, err := ssh.NewPublicKey(pub)
-	if err != nil {
-		t.Errorf("while generating SSH public key: %v", err)
-	}
-	return string(ssh.MarshalAuthorizedKey(sshpub))
-}
-
-func TestCreateSSHKey(t *testing.T) {
-	cl := new(&Opts{
-		User:   apiuser,
-		APIKey: apikey,
-	})
-
-	nk, err := cl.CreateSSHKey(ctx, &packngo.SSHKeyCreateRequest{
-		Label:     sshKeyLabel,
-		Key:       createSSHAuthKey(t),
-		ProjectID: apipid,
-	})
-	if err != nil {
-		t.Errorf("while creating an SSH key: %v", err)
-	}
-	if nk.Label != sshKeyLabel {
-		t.Errorf("key labels don't match.")
-	}
-	t.Logf("Created an SSH key (ID: %s)", nk.ID)
-	sshKeyID = nk.ID
-}
-
-var (
-	// dummySSHPK2 is the alternate key used to exercise TestUpdateSSHKey and
-	// TestGetSSHKey.
-	dummySSHPK2 string
-)
-
-func TestUpdateSSHKey(t *testing.T) {
-	cl := new(&Opts{
-		User:   apiuser,
-		APIKey: apikey,
-	})
-
-	if sshKeyID == "" {
-		t.Skip("SSH key couldn't have been created - skipping...")
-	}
-
-	dummySSHPK2 = createSSHAuthKey(t)
-	k, err := cl.UpdateSSHKey(ctx, sshKeyID, &packngo.SSHKeyUpdateRequest{
-		Key: &dummySSHPK2,
-	})
-	if err != nil {
-		t.Errorf("while updating an SSH key: %v", err)
-	}
-	if k.Key != dummySSHPK2 {
-		t.Errorf("updated SSH key doesn't match the original.")
-	}
-}
-
-func TestGetSSHKey(t *testing.T) {
-	cl := new(&Opts{
-		User:   apiuser,
-		APIKey: apikey,
-	})
-
-	if sshKeyID == "" {
-		t.Skip("SSH key couldn't have been created - skipping...")
-	}
-
-	k, err := cl.getSSHKey(ctx, sshKeyID)
-	if err != nil {
-		t.Errorf("while getting an SSH key: %v", err)
-	}
-	if k.Key != dummySSHPK2 {
-		t.Errorf("got key contents that don't match the original.")
-	}
-}
-
-func TestListSSHKeys(t *testing.T) {
-	cl := new(&Opts{
-		User:   apiuser,
-		APIKey: apikey,
-	})
-
-	if sshKeyID == "" {
-		t.Skip("SSH key couldn't have been created - skipping...")
-	}
-
-	ks, err := cl.ListSSHKeys(ctx)
-	if err != nil {
-		t.Errorf("while listing SSH keys: %v", err)
-	}
-
-	// Check that our key is part of the list.
-	found := false
-	for _, k := range ks {
-		if k.ID == sshKeyID {
-			found = true
-			break
-		}
-	}
-	if !found {
-		t.Errorf("SSH key not listed.")
-	}
-}
-
-func TestCreateDevice(t *testing.T) {
-	cl := new(&Opts{
-		User:   apiuser,
-		APIKey: apikey,
-	})
-
-	// Find a provisionable hardware reservation the device will be created with.
-	rvs, err := cl.ListReservations(ctx, apipid)
-	if err != nil {
-		t.Errorf("while listing hardware reservations: %v", err)
-	}
-	var rv *packngo.HardwareReservation
-	for _, r := range rvs {
-		if r.Provisionable {
-			rv = &r
-			break
-		}
-	}
-	if rv == nil {
-		t.Skip("could not find a provisionable hardware reservation - skipping...")
-	}
-
-	d, err := cl.CreateDevice(ctx, &packngo.DeviceCreateRequest{
-		Hostname:              testDeviceHostname,
-		OS:                    apios,
-		Plan:                  rv.Plan.Slug,
-		HardwareReservationID: rv.ID,
-		ProjectID:             apipid,
-	})
-	if err != nil {
-		t.Errorf("while creating a device: %v", err)
-	}
-	t.Logf("Created a new test device (ID: %s)", d.ID)
-	testDevice = d
-}
-
-func TestGetDevice(t *testing.T) {
-	if testDevice == nil {
-		t.Skip("the test device couldn't have been created - skipping...")
-	}
-
-	cl := new(&Opts{
-		User:   apiuser,
-		APIKey: apikey,
-	})
-
-	d, err := cl.GetDevice(ctx, apipid, testDevice.ID)
-	if err != nil {
-		t.Errorf("while fetching device info: %v", err)
-	}
-	if d == nil {
-		t.Errorf("expected the test device (ID: %s) to exist.", testDevice.ID)
-	}
-	if d.ID != testDevice.ID {
-		t.Errorf("got device ID that doesn't match the original.")
-	}
-}
-
-func TestListDevices(t *testing.T) {
-	cl := new(&Opts{
-		User:   apiuser,
-		APIKey: apikey,
-	})
-
-	ds, err := cl.ListDevices(ctx, apipid)
-	if err != nil {
-		t.Errorf("while listing devices: %v", err)
-	}
-	if len(ds) == 0 {
-		t.Errorf("expected at least one device.")
-	}
-}
-
-func TestDeleteDevice(t *testing.T) {
-	if testDevice == nil {
-		t.Skip("the test device couldn't have been created - skipping...")
-	}
-
-	cl := new(&Opts{
-		User:   apiuser,
-		APIKey: apikey,
-	})
-
-	// Devices currently being provisioned can't be deleted. After it's
-	// provisioned, device's state will match either "active", or "failed".
-	if err := awaitDeviceState(ctx, t, cl, testDevice.ID, "active", "failed"); err != nil {
-		t.Errorf("while waiting for device to be provisioned: %v", err)
-	}
-	t.Logf("Deleting the test device (ID: %s)", testDevice.ID)
-	if err := cl.deleteDevice(ctx, testDevice.ID); err != nil {
-		t.Errorf("while deleting a device: %v", err)
-	}
-	d, err := cl.GetDevice(ctx, apipid, testDevice.ID)
-	if err != nil && !IsNotFound(err) {
-		t.Errorf("while fetching device info: %v", err)
-	}
-	if d != nil {
-		t.Errorf("device should not exist.")
-	}
-	t.Logf("Deleted the test device (ID: %s)", testDevice.ID)
-}
-
-func TestDeleteSSHKey(t *testing.T) {
-	if sshKeyID == "" {
-		t.Skip("SSH key couldn't have been created - skipping...")
-	}
-
-	cl := new(&Opts{
-		User:   apiuser,
-		APIKey: apikey,
-	})
-
-	t.Logf("Deleting the test SSH key (ID: %s)", sshKeyID)
-	if err := cl.deleteSSHKey(ctx, sshKeyID); err != nil {
-		t.Errorf("couldn't delete an SSH key: %v", err)
-	}
-	_, err := cl.getSSHKey(ctx, sshKeyID)
-	if err == nil {
-		t.Errorf("SSH key should not exist")
-	}
-	t.Logf("Deleted the test SSH key (ID: %s)", sshKeyID)
-}