Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

databases: add get-ca to retrieve db certificate #1580

Merged
merged 7 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions commands/databases.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ func Databases() *Command {
- The date and time when the database cluster was created`+databaseListDetails, Writer, aliasOpt("g"), displayerType(&displayers.Databases{}))
cmdDatabaseGet.Example = `The following example retrieves the details for a database cluster with the ID ` + "`" + `f81d4fae-7dec-11d0-a765-00a0c91e6bf6` + "`" + ` and uses the ` + "`" + `--format` + "`" + ` flag to return only the database's ID, engine, and engine version: doctl databases get f81d4fae-7dec-11d0-a765-00a0c91e6bf6`

cmdDatabaseGetCA := CmdBuilder(cmd, RunDatabaseGetCA, "get-ca <database-cluster-id>", "Provides the CA certificate for a DigitalOcean database", `Retrieves a database certificate`, Writer, aliasOpt("gc"), displayerType(&displayers.DatabaseCA{}))
cmdDatabaseGetCA.Example = `Retrieves the database certificate for the cluster with the ID ` + "`" + `f81d4fae-7dec-11d0-a765-00a0c91e6bf6` + "`" + `: doctl databases get-ca f81d4fae-7dec-11d0-a765-00a0c91e6bf6
With the ` + "`" + `-o json flag` + "`" + `, the certificate to connect to the database is base64 encoded. To decode it: ` + "`" + `doctl databases get-ca <database-cluster-id> -o json | jq -r .certificate | base64 --decode` + "`"

nodeSizeDetails := "The size of the nodes in the database cluster, for example `db-s-1vcpu-1gb` indicates a 1 CPU, 1GB node. For a list of available size slugs, visit: https://docs.digitalocean.com/reference/api/api-reference/#tag/Databases"
nodeNumberDetails := "The number of nodes in the database cluster. Valid values are 1-3. In addition to the primary node, up to two standby nodes may be added for high availability."
storageSizeMiBDetails := "The amount of disk space allocated to the cluster. Applicable for PostgreSQL and MySQL clusters. Each plan size has a default value but can be increased in increments up to a maximum amount. For ranges, visit: https://www.digitalocean.com/pricing/managed-databases"
Expand Down Expand Up @@ -188,6 +192,21 @@ func RunDatabaseGet(c *CmdConfig) error {
return displayDatabases(c, false, *db)
}

// RunDatabaseGetCA returns a CA certificate for a database
func RunDatabaseGetCA(c *CmdConfig) error {
if len(c.Args) == 0 {
return doctl.NewMissingArgsErr(c.NS)
}

id := c.Args[0]
dbCA, err := c.Databases().GetCA(id)
if err != nil {
return err
}

return displayDatabaseCA(c, dbCA)
}

// RunDatabaseCreate creates a database cluster
func RunDatabaseCreate(c *CmdConfig) error {
if len(c.Args) == 0 {
Expand Down Expand Up @@ -906,6 +925,11 @@ func displayDatabaseUsers(c *CmdConfig, users ...do.DatabaseUser) error {
return c.Display(item)
}

func displayDatabaseCA(c *CmdConfig, dbCA *do.DatabaseCA) error {
item := &displayers.DatabaseCA{DatabaseCA: *dbCA}
return c.Display(item)
}

func databaseOptions() *Command {
cmd := &Command{
Command: &cobra.Command{
Expand Down
32 changes: 32 additions & 0 deletions commands/databases_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ var (
},
}

testDBClusterCA = do.DatabaseCA{
DatabaseCA: &godo.DatabaseCA{
Certificate: []byte("QQDDC9jMGIwYzNiZS0wZjY4LTRkY4OCCAaIwDQYJKoZIhvcNAQ"),
},
}

testKafkaDBCluster = do.Database{
Database: &godo.Database{
ID: "ea93928g-8se0-929e-m1ns-029daj2k3j12",
Expand Down Expand Up @@ -244,6 +250,7 @@ func TestDatabasesCommand(t *testing.T) {
assertCommandNames(t, cmd,
"list",
"get",
"get-ca",
"create",
"delete",
"connection",
Expand Down Expand Up @@ -378,6 +385,31 @@ func TestDatabasesGet(t *testing.T) {
})
}

func TestDatabasesGetCA(t *testing.T) {
// Successful call
withTestClient(t, func(config *CmdConfig, tm *tcMocks) {
tm.databases.EXPECT().GetCA(testDBCluster.ID).Return(&testDBClusterCA, nil)
config.Args = append(config.Args, testDBCluster.ID)
err := RunDatabaseGetCA(config)
assert.NoError(t, err)
})

// Error
notFound := "not-found"
withTestClient(t, func(config *CmdConfig, tm *tcMocks) {
tm.databases.EXPECT().GetCA(notFound).Return(nil, errTest)
config.Args = append(config.Args, notFound)
err := RunDatabaseGetCA(config)
assert.Error(t, err)
})

// ID not provided
withTestClient(t, func(config *CmdConfig, tm *tcMocks) {
err := RunDatabaseGetCA(config)
assert.EqualError(t, doctl.NewMissingArgsErr(config.NS), err.Error())
})
}

func TestDatabasesList(t *testing.T) {
// Successful call
withTestClient(t, func(config *CmdConfig, tm *tcMocks) {
Expand Down
30 changes: 30 additions & 0 deletions commands/displayers/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,36 @@ func (db *DatabaseBackups) KV() []map[string]any {
return out
}

type DatabaseCA struct {
DatabaseCA do.DatabaseCA
}

var _ Displayable = &DatabaseCA{}

func (dc *DatabaseCA) JSON(out io.Writer) error {
return writeJSON(dc.DatabaseCA, out)
}

func (dc *DatabaseCA) Cols() []string {
return []string{
"Certificate",
}
}

func (dc *DatabaseCA) ColMap() map[string]string {
return map[string]string{
"Certificate": "Certificate",
}
}

func (dc *DatabaseCA) KV() []map[string]any {
return []map[string]any{
{
"Certificate": string(dc.DatabaseCA.Certificate),
loosla marked this conversation as resolved.
Show resolved Hide resolved
},
}
}

type DatabaseUsers struct {
DatabaseUsers do.DatabaseUsers
}
Expand Down
18 changes: 18 additions & 0 deletions do/databases.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ type Database struct {
*godo.Database
}

// DatabaseCA is a wrapper for godo.DatabaseCA
type DatabaseCA struct {
*godo.DatabaseCA
}

// DatabaseCAs is a slice of DatabaseCA
type DatabaseCAs []DatabaseCA

// Databases is a slice of Database
type Databases []Database

Expand Down Expand Up @@ -145,6 +153,7 @@ type DatabaseIndex struct {
type DatabasesService interface {
List() (Databases, error)
Get(string) (*Database, error)
GetCA(string) (*DatabaseCA, error)
Create(*godo.DatabaseCreateRequest) (*Database, error)
Delete(string) error
GetConnection(string, bool) (*DatabaseConnection, error)
Expand Down Expand Up @@ -257,6 +266,15 @@ func (ds *databasesService) Get(databaseID string) (*Database, error) {
return &Database{Database: db}, nil
}

func (ds *databasesService) GetCA(databaseID string) (*DatabaseCA, error) {
dbCA, _, err := ds.client.Databases.GetCA(context.TODO(), databaseID)
if err != nil {
return nil, err
}

return &DatabaseCA{DatabaseCA: dbCA}, nil
}

func (ds *databasesService) Create(req *godo.DatabaseCreateRequest) (*Database, error) {
db, _, err := ds.client.Databases.Create(context.TODO(), req)
if err != nil {
Expand Down
15 changes: 15 additions & 0 deletions do/mocks/DatabasesService.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading