diff --git a/internal/backups/list/list_test.go b/internal/backups/list/list_test.go index a236959aa..70285ec6b 100644 --- a/internal/backups/list/list_test.go +++ b/internal/backups/list/list_test.go @@ -72,6 +72,28 @@ func TestListBackup(t *testing.T) { assert.NoError(t, err) }) + t.Run("encodes json output", func(t *testing.T) { + utils.OutputFormat.Value = utils.OutputJson + t.Cleanup(func() { utils.OutputFormat.Value = utils.OutputPretty }) + t.Cleanup(fstest.MockStdout(t, `{ + "backups": null, + "physical_backup_data": {}, + "pitr_enabled": false, + "region": "ap-southeast-1", + "walg_enabled": false +} +`)) + t.Cleanup(apitest.MockPlatformAPI(t)) + // Setup mock api + gock.New(utils.DefaultApiHost). + Get("/v1/projects/" + flags.ProjectRef + "/database/backups"). + Reply(http.StatusOK). + JSON(api.V1BackupsResponse{Region: "ap-southeast-1"}) + // Run test + err := Run(context.Background()) + assert.NoError(t, err) + }) + t.Run("throws error on network error", func(t *testing.T) { errNetwork := errors.New("network error") t.Cleanup(apitest.MockPlatformAPI(t)) diff --git a/internal/branches/update/update_test.go b/internal/branches/update/update_test.go index 070d82c9f..18382e94e 100644 --- a/internal/branches/update/update_test.go +++ b/internal/branches/update/update_test.go @@ -77,10 +77,10 @@ func TestUpdateBranch(t *testing.T) { t.Cleanup(apitest.MockPlatformAPI(t)) // Setup mock api gock.New(utils.DefaultApiHost). - Patch("/v1/branches/" + flags.ProjectRef). + Get("/v1/projects/" + flags.ProjectRef + "/branches/missing"). ReplyError(errNetwork) // Run test - err := Run(context.Background(), flags.ProjectRef, api.UpdateBranchBody{}, nil) + err := Run(context.Background(), "missing", api.UpdateBranchBody{}, nil) assert.ErrorIs(t, err, errNetwork) }) diff --git a/internal/ssl_enforcement/get/get.go b/internal/ssl_enforcement/get/get.go index e6d58693e..e16a6f29b 100644 --- a/internal/ssl_enforcement/get/get.go +++ b/internal/ssl_enforcement/get/get.go @@ -3,29 +3,32 @@ package get import ( "context" "fmt" + "os" "github.com/go-errors/errors" "github.com/spf13/afero" "github.com/supabase/cli/internal/utils" + "github.com/supabase/cli/pkg/api" ) func Run(ctx context.Context, projectRef string, fsys afero.Fs) error { - // 1. Sanity checks. - // 2. get ssl enforcement config - { - resp, err := utils.GetSupabase().V1GetSslEnforcementConfigWithResponse(ctx, projectRef) - if err != nil { - return errors.Errorf("failed to retrieve SSL enforcement config: %w", err) - } - if resp.JSON200 == nil { - return errors.New("failed to retrieve SSL enforcement config; received: " + string(resp.Body)) - } + resp, err := utils.GetSupabase().V1GetSslEnforcementConfigWithResponse(ctx, projectRef) + if err != nil { + return errors.Errorf("failed to retrieve SSL enforcement config: %w", err) + } else if resp.JSON200 == nil { + return errors.Errorf("unexpected SSL enforcement status %d: %s", resp.StatusCode(), string(resp.Body)) + } + if utils.OutputFormat.Value != utils.OutputPretty { + return utils.EncodeOutput(utils.OutputFormat.Value, os.Stdout, *resp.JSON200) + } + return PrintSSLStatus(*resp.JSON200) +} - if resp.JSON200.CurrentConfig.Database && resp.JSON200.AppliedSuccessfully { - fmt.Println("SSL is being enforced.") - } else { - fmt.Println("SSL is *NOT* being enforced.") - } - return nil +func PrintSSLStatus(ssl api.SslEnforcementResponse) error { + if ssl.CurrentConfig.Database && ssl.AppliedSuccessfully { + fmt.Println("SSL is being enforced.") + } else { + fmt.Println("SSL is *NOT* being enforced.") } + return nil } diff --git a/internal/ssl_enforcement/get/get_test.go b/internal/ssl_enforcement/get/get_test.go new file mode 100644 index 000000000..7ec99b9d7 --- /dev/null +++ b/internal/ssl_enforcement/get/get_test.go @@ -0,0 +1,82 @@ +package get + +import ( + "context" + "errors" + "net/http" + "testing" + + "github.com/h2non/gock" + "github.com/stretchr/testify/assert" + "github.com/supabase/cli/internal/testing/apitest" + "github.com/supabase/cli/internal/testing/fstest" + "github.com/supabase/cli/internal/utils" + "github.com/supabase/cli/internal/utils/flags" + "github.com/supabase/cli/pkg/api" +) + +func TestSSLEnforcement(t *testing.T) { + flags.ProjectRef = apitest.RandomProjectRef() + + t.Run("get ssl enforcement", func(t *testing.T) { + t.Cleanup(fstest.MockStdout(t, "SSL is *NOT* being enforced.\n")) + t.Cleanup(apitest.MockPlatformAPI(t)) + // Setup mock api + gock.New(utils.DefaultApiHost). + Get("v1/projects/" + flags.ProjectRef + "/ssl-enforcement"). + Reply(http.StatusOK). + JSON(api.SslEnforcementResponse{}) + // Run test + err := Run(context.Background(), flags.ProjectRef, nil) + assert.NoError(t, err) + }) + + t.Run("encodes env output", func(t *testing.T) { + utils.OutputFormat.Value = utils.OutputEnv + t.Cleanup(func() { utils.OutputFormat.Value = utils.OutputPretty }) + t.Cleanup(fstest.MockStdout(t, `APPLIEDSUCCESSFULLY="true" +CURRENTCONFIG_DATABASE="true" +`)) + t.Cleanup(apitest.MockPlatformAPI(t)) + // Setup mock api + gock.New(utils.DefaultApiHost). + Get("v1/projects/" + flags.ProjectRef + "/ssl-enforcement"). + Reply(http.StatusOK). + JSON(api.SslEnforcementResponse{ + AppliedSuccessfully: true, + CurrentConfig: struct { + Database bool `json:"database"` + }{ + Database: true, + }, + }) + // Run test + err := Run(context.Background(), flags.ProjectRef, nil) + assert.NoError(t, err) + }) + + t.Run("throws error on network error", func(t *testing.T) { + errNetwork := errors.New("network error") + t.Cleanup(apitest.MockPlatformAPI(t)) + // Setup mock api + gock.New(utils.DefaultApiHost). + Get("/v1/projects/" + flags.ProjectRef + "/ssl-enforcement"). + ReplyError(errNetwork) + // Run test + err := Run(context.Background(), flags.ProjectRef, nil) + assert.ErrorIs(t, err, errNetwork) + }) + + t.Run("throws error on service unavailable", func(t *testing.T) { + utils.OutputFormat.Value = utils.OutputEnv + t.Cleanup(func() { utils.OutputFormat.Value = utils.OutputPretty }) + t.Cleanup(apitest.MockPlatformAPI(t)) + // Setup mock api + gock.New(utils.DefaultApiHost). + Get("/v1/projects/" + flags.ProjectRef + "/ssl-enforcement"). + Reply(http.StatusServiceUnavailable) + // Run test + err := Run(context.Background(), flags.ProjectRef, nil) + assert.ErrorContains(t, err, "unexpected SSL enforcement status 503:") + }) +} diff --git a/internal/ssl_enforcement/update/update.go b/internal/ssl_enforcement/update/update.go index 8f1b5f56d..7f0525136 100644 --- a/internal/ssl_enforcement/update/update.go +++ b/internal/ssl_enforcement/update/update.go @@ -2,32 +2,26 @@ package update import ( "context" - "fmt" + "os" "github.com/go-errors/errors" "github.com/spf13/afero" + "github.com/supabase/cli/internal/ssl_enforcement/get" "github.com/supabase/cli/internal/utils" "github.com/supabase/cli/pkg/api" ) func Run(ctx context.Context, projectRef string, enforceDbSsl bool, fsys afero.Fs) error { - // 1. sanity checks - // 2. update restrictions - { - body := api.V1UpdateSslEnforcementConfigJSONRequestBody{} - body.RequestedConfig.Database = enforceDbSsl - resp, err := utils.GetSupabase().V1UpdateSslEnforcementConfigWithResponse(ctx, projectRef, body) - if err != nil { - return errors.Errorf("failed to update ssl enforcement: %w", err) - } - if resp.JSON200 == nil { - return errors.New("failed to update SSL enforcement confnig: " + string(resp.Body)) - } - if resp.JSON200.CurrentConfig.Database && resp.JSON200.AppliedSuccessfully { - fmt.Println("SSL is now being enforced.") - } else { - fmt.Println("SSL is *NOT* being enforced.") - } - return nil + body := api.V1UpdateSslEnforcementConfigJSONRequestBody{} + body.RequestedConfig.Database = enforceDbSsl + resp, err := utils.GetSupabase().V1UpdateSslEnforcementConfigWithResponse(ctx, projectRef, body) + if err != nil { + return errors.Errorf("failed to update ssl enforcement: %w", err) + } else if resp.JSON200 == nil { + return errors.Errorf("unexpected update SSL status %d: %s", resp.StatusCode(), string(resp.Body)) } + if utils.OutputFormat.Value != utils.OutputPretty { + return utils.EncodeOutput(utils.OutputFormat.Value, os.Stdout, *resp.JSON200) + } + return get.PrintSSLStatus(*resp.JSON200) } diff --git a/internal/ssl_enforcement/update/update_test.go b/internal/ssl_enforcement/update/update_test.go new file mode 100644 index 000000000..92a406a39 --- /dev/null +++ b/internal/ssl_enforcement/update/update_test.go @@ -0,0 +1,82 @@ +package update + +import ( + "context" + "errors" + "net/http" + "testing" + + "github.com/h2non/gock" + "github.com/stretchr/testify/assert" + "github.com/supabase/cli/internal/testing/apitest" + "github.com/supabase/cli/internal/testing/fstest" + "github.com/supabase/cli/internal/utils" + "github.com/supabase/cli/internal/utils/flags" + "github.com/supabase/cli/pkg/api" +) + +func TestUpdateSSL(t *testing.T) { + flags.ProjectRef = apitest.RandomProjectRef() + + t.Run("enable ssl enforcement", func(t *testing.T) { + t.Cleanup(fstest.MockStdout(t, "SSL is being enforced.\n")) + t.Cleanup(apitest.MockPlatformAPI(t)) + // Setup mock api + gock.New(utils.DefaultApiHost). + Put("v1/projects/" + flags.ProjectRef + "/ssl-enforcement"). + Reply(http.StatusOK). + JSON(api.SslEnforcementResponse{ + AppliedSuccessfully: true, + CurrentConfig: struct { + Database bool `json:"database"` + }{ + Database: true, + }, + }) + // Run test + err := Run(context.Background(), flags.ProjectRef, true, nil) + assert.NoError(t, err) + }) + + t.Run("encodes toml format", func(t *testing.T) { + utils.OutputFormat.Value = utils.OutputEnv + t.Cleanup(func() { utils.OutputFormat.Value = utils.OutputPretty }) + t.Cleanup(fstest.MockStdout(t, `APPLIEDSUCCESSFULLY="false" +CURRENTCONFIG_DATABASE="false" +`)) + t.Cleanup(apitest.MockPlatformAPI(t)) + // Setup mock api + gock.New(utils.DefaultApiHost). + Put("v1/projects/" + flags.ProjectRef + "/ssl-enforcement"). + Reply(http.StatusOK). + JSON(api.SslEnforcementResponse{}) + // Run test + err := Run(context.Background(), flags.ProjectRef, false, nil) + assert.NoError(t, err) + }) + + t.Run("throws error on network error", func(t *testing.T) { + errNetwork := errors.New("network error") + t.Cleanup(apitest.MockPlatformAPI(t)) + // Setup mock api + gock.New(utils.DefaultApiHost). + Put("/v1/projects/" + flags.ProjectRef + "/ssl-enforcement"). + ReplyError(errNetwork) + // Run test + err := Run(context.Background(), flags.ProjectRef, false, nil) + assert.ErrorIs(t, err, errNetwork) + }) + + t.Run("throws error on service unavailable", func(t *testing.T) { + utils.OutputFormat.Value = utils.OutputEnv + t.Cleanup(func() { utils.OutputFormat.Value = utils.OutputPretty }) + t.Cleanup(apitest.MockPlatformAPI(t)) + // Setup mock api + gock.New(utils.DefaultApiHost). + Put("/v1/projects/" + flags.ProjectRef + "/ssl-enforcement"). + Reply(http.StatusServiceUnavailable) + // Run test + err := Run(context.Background(), flags.ProjectRef, false, nil) + assert.ErrorContains(t, err, "unexpected update SSL status 503:") + }) +}