From 1040f20e4e9f6f5ff77cb771e41c353ee6a88e61 Mon Sep 17 00:00:00 2001 From: Garrett Squire Date: Mon, 21 Oct 2024 08:29:14 -0700 Subject: [PATCH] Add Database Replica Integration Tests (#1596) This patch adds the remaining database replica integration tests. It also corrects some of the parameters for the replica promote test. Co-authored-by: Anna Lushnikova --- integration/database_replica_create_test.go | 80 ++++++++++++++++ integration/database_replica_delete_test.go | 70 ++++++++++++++ .../database_replica_get_and_list_test.go | 91 +++++++++++++++++++ integration/database_replica_promote_test.go | 7 +- 4 files changed, 245 insertions(+), 3 deletions(-) create mode 100644 integration/database_replica_create_test.go create mode 100644 integration/database_replica_delete_test.go create mode 100644 integration/database_replica_get_and_list_test.go diff --git a/integration/database_replica_create_test.go b/integration/database_replica_create_test.go new file mode 100644 index 000000000..7838651c8 --- /dev/null +++ b/integration/database_replica_create_test.go @@ -0,0 +1,80 @@ +package integration + +import ( + "fmt" + "io" + "net/http" + "net/http/httptest" + "net/http/httputil" + "os/exec" + "testing" + + "github.com/sclevine/spec" + "github.com/stretchr/testify/require" +) + +var _ = suite("database/replica", func(t *testing.T, when spec.G, it spec.S) { + var ( + expect *require.Assertions + server *httptest.Server + ) + + it.Before(func() { + expect = require.New(t) + + server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + switch req.URL.Path { + case "/v2/databases/1111/replicas": + auth := req.Header.Get("Authorization") + if auth != "Bearer some-magic-token" { + w.WriteHeader(http.StatusUnauthorized) + return + } + + if req.Method != http.MethodPost { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + + body, err := io.ReadAll(req.Body) + expect.NoError(err) + + expect.JSONEq(databaseReplicaCreateRequest, string(body)) + + w.WriteHeader(http.StatusCreated) + w.Write([]byte(databaseReplicaCreateResponse)) + default: + dump, err := httputil.DumpRequest(req, true) + if err != nil { + t.Fatal("failed to dump request") + } + + t.Fatalf("received unknown request: %s", dump) + } + })) + }) + + when("command is create", func() { + it("create a read-only replica database", func() { + cmd := exec.Command(builtBinaryPath, + "-t", "some-magic-token", + "-u", server.URL, + "databases", + "replica", + "create", + "1111", + "2222", + ) + + output, err := cmd.CombinedOutput() + expect.NoError(err, fmt.Sprintf("received error output: %s", output)) + }) + + }) +}) + +const ( + // All of the values are default except for the name. + databaseReplicaCreateRequest = `{"name":"2222","private_network_uuid":"","region":"nyc1","size":"db-s-1vcpu-1gb"}` + databaseReplicaCreateResponse = `{"replica":{"name":"2222","connection":{"uri":"","database":"defaultdb","host":"","port":25060,"user":"doadmin","password":"","ssl":true},"private_connection":{"uri":"","database":"","host":"","port":25060,"user":"doadmin","password":"","ssl":true},"region":"nyc1","status":"online","created_at":"2019-01-11T18:37:36Z"}}` +) diff --git a/integration/database_replica_delete_test.go b/integration/database_replica_delete_test.go new file mode 100644 index 000000000..8384c52ee --- /dev/null +++ b/integration/database_replica_delete_test.go @@ -0,0 +1,70 @@ +package integration + +import ( + "fmt" + "net/http" + "net/http/httptest" + "net/http/httputil" + "os/exec" + "testing" + + "github.com/sclevine/spec" + "github.com/stretchr/testify/require" +) + +var _ = suite("database/replica", func(t *testing.T, when spec.G, it spec.S) { + var ( + expect *require.Assertions + server *httptest.Server + ) + + it.Before(func() { + expect = require.New(t) + + server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + switch req.URL.Path { + case "/v2/databases/1111/replicas/2222": + auth := req.Header.Get("Authorization") + if auth != "Bearer some-magic-token" { + w.WriteHeader(http.StatusUnauthorized) + return + } + + if req.Method != http.MethodDelete { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + + w.WriteHeader(http.StatusNoContent) + w.Write([]byte(``)) + default: + dump, err := httputil.DumpRequest(req, true) + if err != nil { + t.Fatal("failed to dump request") + } + + t.Fatalf("received unknown request: %s", dump) + } + })) + }) + + when("command is delete", func() { + it("delete a replica database", func() { + cmd := exec.Command(builtBinaryPath, + "-t", "some-magic-token", + "-u", server.URL, + "databases", + "replica", + "delete", + // Need to force to forego the prompt. + "--force", + "1111", + "2222", + ) + + output, err := cmd.CombinedOutput() + expect.NoError(err, fmt.Sprintf("received error output: %s", output)) + }) + + }) +}) diff --git a/integration/database_replica_get_and_list_test.go b/integration/database_replica_get_and_list_test.go new file mode 100644 index 000000000..4c5adf20e --- /dev/null +++ b/integration/database_replica_get_and_list_test.go @@ -0,0 +1,91 @@ +package integration + +import ( + "fmt" + "net/http" + "net/http/httptest" + "net/http/httputil" + "os/exec" + "testing" + + "github.com/sclevine/spec" + "github.com/stretchr/testify/require" +) + +var _ = suite("database/replica", func(t *testing.T, when spec.G, it spec.S) { + var ( + expect *require.Assertions + server *httptest.Server + ) + + it.Before(func() { + expect = require.New(t) + + server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + auth := req.Header.Get("Authorization") + if auth != "Bearer some-magic-token" { + w.WriteHeader(http.StatusUnauthorized) + return + } + + if req.Method != http.MethodGet { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + switch req.URL.Path { + case "/v2/databases/1111/replicas/2222": + w.Write([]byte(`{"replica":`)) + w.Write([]byte(replicaMetadata)) + w.Write([]byte(`}`)) + case "/v2/databases/1111/replicas": + w.Write([]byte(`{"replicas":[`)) + w.Write([]byte(replicaMetadata)) + w.Write([]byte(`]}`)) + default: + dump, err := httputil.DumpRequest(req, true) + if err != nil { + t.Fatal("failed to dump request") + } + + t.Fatalf("received unknown request: %s", dump) + } + })) + }) + + when("command is get", func() { + it("return metadata about a replica database", func() { + cmd := exec.Command(builtBinaryPath, + "-t", "some-magic-token", + "-u", server.URL, + "databases", + "replica", + "get", + "1111", + "2222", + ) + + output, err := cmd.CombinedOutput() + expect.NoError(err, fmt.Sprintf("received error output: %s", output)) + }) + + }) + + when("command is list", func() { + it("list all of the replica databases", func() { + cmd := exec.Command(builtBinaryPath, + "-t", "some-magic-token", + "-u", server.URL, + "databases", + "replica", + "list", + "1111", + ) + + output, err := cmd.CombinedOutput() + expect.NoError(err, fmt.Sprintf("received error output: %s", output)) + }) + + }) +}) + +const replicaMetadata = `{"name":"read-nyc3-01","connection":{"uri":"","database":"defaultdb","host":"read-nyc3-01-do-user-19081923-0.db.ondigitalocean.com","port":25060,"user":"doadmin","password":"","ssl":true},"private_connection":{"uri":"","database":"","host":"private-read-nyc3-01-do-user-19081923-0.db.ondigitalocean.com","port":25060,"user":"doadmin","password":"","ssl":true},"region":"nyc3","status":"online","created_at":"2019-01-11T18:37:36Z"}` diff --git a/integration/database_replica_promote_test.go b/integration/database_replica_promote_test.go index 601b182c7..29cfcb0f5 100644 --- a/integration/database_replica_promote_test.go +++ b/integration/database_replica_promote_test.go @@ -23,20 +23,20 @@ var _ = suite("database/replica", func(t *testing.T, when spec.G, it spec.S) { server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { switch req.URL.Path { - case "v2/databases/1111/replicas/2222/promote": + case "/v2/databases/1111/replicas/2222/promote": auth := req.Header.Get("Authorization") if auth != "Bearer some-magic-token" { w.WriteHeader(http.StatusUnauthorized) return } - if req.Method != http.MethodGet { + if req.Method != http.MethodPut { w.WriteHeader(http.StatusMethodNotAllowed) return } - w.Write([]byte(``)) w.WriteHeader(http.StatusNoContent) + w.Write([]byte(``)) default: dump, err := httputil.DumpRequest(req, true) if err != nil { @@ -54,6 +54,7 @@ var _ = suite("database/replica", func(t *testing.T, when spec.G, it spec.S) { "-t", "some-magic-token", "-u", server.URL, "databases", + "replica", "promote", "1111", "2222",