diff --git a/CHANGELOG.md b/CHANGELOG.md index 63022806..7ed608fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## To Be Released +* fix(dbng): allow `database-destroy` to resolve databases by name + ## 1.51.1 * chore(go): update Go to 1.27.3 diff --git a/cmd/databases_ng.go b/cmd/databases_ng.go index 5e821053..8c90393d 100644 --- a/cmd/databases_ng.go +++ b/cmd/databases_ng.go @@ -278,30 +278,31 @@ var ( Name: "database-destroy", Category: "Databases DR", Usage: "Delete database Dedicated Resources", - ArgsUsage: "database-id", + ArgsUsage: "database-id-or-name", Flags: []cli.Flag{databaseFlag()}, Description: CommandDescription{ Description: "Delete database Dedicated Resources", Examples: []string{ "scalingo database-destroy database_id", - "scalingo database-destroy --database database_id", + "scalingo database-destroy database_name", + "scalingo database-destroy --database database_name", }, SeeAlso: []string{"databases", "database-info", "database-create", "database-upgrade"}, }.Render(), Action: func(ctx context.Context, c *cli.Command) error { - databaseID := c.Args().First() - if databaseID == "" { - databaseID, _ = detect.GetCurrentDatabase(ctx, c) + databaseIdentifier := c.Args().First() + if databaseIdentifier == "" { + databaseIdentifier, _ = detect.GetCurrentDatabase(ctx, c) } - if databaseID == "" { - io.Error("Please provide a database ID or use --database flag") + if databaseIdentifier == "" { + io.Error("Please provide a database ID or name, or use --database flag") return cli.ShowCommandHelp(ctx, c, "database-destroy") } - utils.CheckForConsent(ctx, databaseID, utils.ConsentTypeDBs) + utils.CheckForConsent(ctx, databaseIdentifier, utils.ConsentTypeDBs) - err := dbng.Destroy(ctx, databaseID) + err := dbng.Destroy(ctx, databaseIdentifier) if err != nil { errorQuit(ctx, err) } diff --git a/dbng/destroy.go b/dbng/destroy.go index bfde4631..971eb21f 100644 --- a/dbng/destroy.go +++ b/dbng/destroy.go @@ -6,18 +6,24 @@ import ( "github.com/Scalingo/cli/config" "github.com/Scalingo/cli/io" + scalingo "github.com/Scalingo/go-scalingo/v11" "github.com/Scalingo/go-utils/errors/v3" ) -func Destroy(ctx context.Context, appID string) error { +func Destroy(ctx context.Context, databaseIdentifier string) error { c, err := config.ScalingoClient(ctx) if err != nil { return errors.Wrap(ctx, err, "get Scalingo client") } - db, err := c.Preview().DatabaseShow(ctx, appID) + databases, err := c.Preview().DatabasesList(ctx) if err != nil { - return errors.Wrap(ctx, err, "show database") + return errors.Wrap(ctx, err, "list databases") + } + + db, found := findDatabaseByNameOrID(databases, databaseIdentifier) + if !found { + return errors.Wrap(ctx, scalingo.ErrDatabaseNotFound, "show database") } io.Warningf("You're going to delete database %s ('%s'),\n", db.ID, db.Name) @@ -36,7 +42,7 @@ func Destroy(ctx context.Context, appID string) error { return errors.Newf(ctx, "'%s' is not the ID or the name of the database, aborting…\n", validationID) } - err = c.Preview().DatabaseDestroy(ctx, appID) + err = c.Preview().DatabaseDestroy(ctx, db.ID) if err != nil { return errors.Wrap(ctx, err, "destroy database") } @@ -45,3 +51,19 @@ func Destroy(ctx context.Context, appID string) error { return nil } + +func findDatabaseByNameOrID(databases []scalingo.DatabaseNG, identifier string) (scalingo.DatabaseNG, bool) { + for _, database := range databases { + if database.ID == identifier { + return database, true + } + } + + for _, database := range databases { + if database.Name == identifier { + return database, true + } + } + + return scalingo.DatabaseNG{}, false +} diff --git a/dbng/destroy_test.go b/dbng/destroy_test.go new file mode 100644 index 00000000..b99b7679 --- /dev/null +++ b/dbng/destroy_test.go @@ -0,0 +1,46 @@ +package dbng + +import ( + "testing" + + scalingo "github.com/Scalingo/go-scalingo/v11" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestFindDatabaseByNameOrID(t *testing.T) { + database := scalingo.DatabaseNG{ID: "6acf7671db2f9ad09ad5a692", Name: "binioudbdr2"} + databases := []scalingo.DatabaseNG{database} + + for _, identifier := range []string{database.ID, database.Name} { + t.Run(identifier, func(t *testing.T) { + result, found := findDatabaseByNameOrID(databases, identifier) + + require.True(t, found) + assert.Equal(t, database, result) + }) + } +} + +func TestFindDatabaseByNameOrIDNotFound(t *testing.T) { + result, found := findDatabaseByNameOrID( + []scalingo.DatabaseNG{{ID: "database-id", Name: "database-name"}}, + "missing", + ) + + assert.False(t, found) + assert.Empty(t, result) +} + +func TestFindDatabaseByNameOrIDPrioritizesID(t *testing.T) { + nameMatch := scalingo.DatabaseNG{ID: "other-id", Name: "shared-identifier"} + idMatch := scalingo.DatabaseNG{ID: "shared-identifier", Name: "id-match"} + + result, found := findDatabaseByNameOrID( + []scalingo.DatabaseNG{nameMatch, idMatch}, + "shared-identifier", + ) + + require.True(t, found) + assert.Equal(t, idMatch, result) +}