From dc1065c6a8992750e6ea38234ad8a6a800bdd81a Mon Sep 17 00:00:00 2001 From: Ching-Wei Kang Date: Wed, 28 Oct 2026 17:45:41 -0500 Subject: [PATCH 1/2] fix(dbng): resolve database names for destroy --- CHANGELOG.md | 2 ++ cmd/databases_ng.go | 19 ++++++++++--------- dbng/destroy.go | 24 ++++++++++++++++++++---- dbng/destroy_test.go | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 13 deletions(-) create mode 100644 dbng/destroy_test.go 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..14ae3986 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,13 @@ 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 || 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..0a1cdad0 --- /dev/null +++ b/dbng/destroy_test.go @@ -0,0 +1,33 @@ +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) +} From 596e9ae54a656c89f106d20fa257cea2a8af2c3b Mon Sep 17 00:00:00 2001 From: Ching-Wei Kang Date: Wed, 28 Oct 2026 17:49:28 -0500 Subject: [PATCH 2/2] fix(dbng): prioritize IDs when resolving destroy target --- dbng/destroy.go | 8 +++++++- dbng/destroy_test.go | 13 +++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/dbng/destroy.go b/dbng/destroy.go index 14ae3986..971eb21f 100644 --- a/dbng/destroy.go +++ b/dbng/destroy.go @@ -54,7 +54,13 @@ func Destroy(ctx context.Context, databaseIdentifier string) error { func findDatabaseByNameOrID(databases []scalingo.DatabaseNG, identifier string) (scalingo.DatabaseNG, bool) { for _, database := range databases { - if database.ID == identifier || database.Name == identifier { + if database.ID == identifier { + return database, true + } + } + + for _, database := range databases { + if database.Name == identifier { return database, true } } diff --git a/dbng/destroy_test.go b/dbng/destroy_test.go index 0a1cdad0..b99b7679 100644 --- a/dbng/destroy_test.go +++ b/dbng/destroy_test.go @@ -31,3 +31,16 @@ func TestFindDatabaseByNameOrIDNotFound(t *testing.T) { 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) +}