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

dbaas: database management for mysql, pg #661

Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

- storage: Adding recursive feature to the storage command #653
- Update help for instance protection #658
- dbaas: database management for mysql, pg #661

### Bug fixes

Expand Down
14 changes: 14 additions & 0 deletions cmd/dbaas_database.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package cmd

import (
"github.com/spf13/cobra"
)

var dbaasDatabaseCmd = &cobra.Command{
Use: "database",
Short: "Manage DBaaS databases",
}

func init() {
dbaasCmd.AddCommand(dbaasDatabaseCmd)
}
72 changes: 72 additions & 0 deletions cmd/dbaas_database_create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package cmd

import (
"fmt"
"os"

"github.com/spf13/cobra"
)

type dbaasDatabaseCreateCmd struct {
cliCommandSettings `cli-cmd:"-"`

_ bool `cli-cmd:"create"`

Name string `cli-arg:"#"`
Database string `cli-arg:"#"`

HelpPg bool `cli-usage:"show usage for flags specific to the pg type"`
Zone string `cli-short:"z" cli-usage:"Database Service zone"`

// "pg" type specific flags
PgLcCollate string `cli-usage:"Default string sort order (LC_COLLATE) for PostgreSQL database" cli-hidden:""`
PgLcCtype string `cli-usage:"Default character classification (LC_CTYPE) for PostgreSQL database" cli-hidden:""`
}

func (c *dbaasDatabaseCreateCmd) cmdAliases() []string { return nil }

func (c *dbaasDatabaseCreateCmd) cmdShort() string { return "Create DBAAS database" }

func (c *dbaasDatabaseCreateCmd) cmdLong() string {
return `This command creates a DBAAS database for the specified service.`
}

func (c *dbaasDatabaseCreateCmd) cmdPreRun(cmd *cobra.Command, args []string) error {
switch {

case cmd.Flags().Changed("help-mysql"):
cmdShowHelpFlags(cmd.Flags(), "mysql-")
os.Exit(0)
case cmd.Flags().Changed("help-pg"):
cmdShowHelpFlags(cmd.Flags(), "pg-")
os.Exit(0)
}

cmdSetZoneFlagFromDefault(cmd)
return cliCommandDefaultPreRun(c, cmd, args)
}

func (c *dbaasDatabaseCreateCmd) cmdRun(cmd *cobra.Command, args []string) error {

ctx := gContext
db, err := dbaasGetV3(ctx, c.Name, c.Zone)
if err != nil {
return err
}

switch db.Type {
case "mysql":
return c.createMysql(cmd, args)
case "pg":
return c.createPg(cmd, args)
default:
return fmt.Errorf("creating database unsupported for service of type %q", db.Type)
}

}

func init() {
cobra.CheckErr(registerCLICommand(dbaasDatabaseCmd, &dbaasDatabaseCreateCmd{
cliCommandSettings: defaultCLICmdSettings(),
}))
}
55 changes: 55 additions & 0 deletions cmd/dbaas_database_create_mysql.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package cmd

import (
"fmt"

"github.com/exoscale/cli/pkg/account"
"github.com/exoscale/cli/pkg/globalstate"
exoapi "github.com/exoscale/egoscale/v2/api"
v3 "github.com/exoscale/egoscale/v3"
"github.com/spf13/cobra"
)

func (c dbaasDatabaseCreateCmd) createMysql(cmd *cobra.Command, _ []string) error {

ctx := gContext

client, err := switchClientZoneV3(ctx, globalstate.EgoscaleV3Client, v3.ZoneName(c.Zone))
if err != nil {
return err
}

s, err := client.GetDBAASServiceMysql(ctx, c.Name)
if err != nil {
return err
}

if len(s.Databases) == 0 {
return fmt.Errorf("service %q is not ready for database creation", c.Name)
}

req := v3.CreateDBAASMysqlDatabaseRequest{
DatabaseName: v3.DBAASDatabaseName(c.Database),
}

op, err := client.CreateDBAASMysqlDatabase(ctx, c.Name, req)
if err != nil {
return err
}

decorateAsyncOperation(fmt.Sprintf("Creating DBaaS database %q", c.Database), func() {
op, err = client.Wait(ctx, op, v3.OperationStateSuccess)
})
if err != nil {
return err
}

if !globalstate.Quiet {
return c.outputFunc((&dbaasServiceShowCmd{
Name: c.Name,
Zone: c.Zone,
}).showDatabaseServiceMysql(exoapi.WithEndpoint(gContext, exoapi.NewReqEndpoint(account.CurrentAccount.Environment, c.Zone))))
}

return err
}
61 changes: 61 additions & 0 deletions cmd/dbaas_database_create_pg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package cmd

import (
"fmt"

"github.com/exoscale/cli/pkg/account"
"github.com/exoscale/cli/pkg/globalstate"
exoapi "github.com/exoscale/egoscale/v2/api"
v3 "github.com/exoscale/egoscale/v3"
"github.com/spf13/cobra"
)

func (c dbaasDatabaseCreateCmd) createPg(cmd *cobra.Command, _ []string) error {
ctx := gContext

client, err := switchClientZoneV3(ctx, globalstate.EgoscaleV3Client, v3.ZoneName(c.Zone))
if err != nil {
return err
}
s, err := client.GetDBAASServicePG(ctx, c.Name)
if err != nil {
return err
}

if len(s.Databases) == 0 {
return fmt.Errorf("service %q is not ready for database creation", c.Name)
}

req := v3.CreateDBAASPGDatabaseRequest{
DatabaseName: v3.DBAASDatabaseName(c.Database),
}

if c.PgLcCollate != "" {
req.LCCollate = c.PgLcCollate
}

if c.PgLcCtype != "" {
req.LCCtype = c.PgLcCtype
}

op, err := client.CreateDBAASPGDatabase(ctx, c.Name, req)
if err != nil {
return err
}

decorateAsyncOperation(fmt.Sprintf("Creating DBaaS database %q", c.Database), func() {
op, err = client.Wait(ctx, op, v3.OperationStateSuccess)
})
if err != nil {
return err
}

if !globalstate.Quiet {
return c.outputFunc((&dbaasServiceShowCmd{
Name: c.Name,
Zone: c.Zone,
}).showDatabaseServicePG(exoapi.WithEndpoint(gContext, exoapi.NewReqEndpoint(account.CurrentAccount.Environment, c.Zone))))
}

return err
}
59 changes: 59 additions & 0 deletions cmd/dbaas_database_delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package cmd

import (
"fmt"

"github.com/spf13/cobra"
)

type dbaasDatabaseDeleteCmd struct {
cliCommandSettings `cli-cmd:"-"`

_ bool `cli-cmd:"delete"`

Name string `cli-arg:"#"`
Database string `cli-arg:"#"`

Zone string `cli-short:"z" cli-usage:"Database Service zone"`

Force bool `cli-short:"f" cli-usage:"don't prompt for confirmation"`
}

func (c *dbaasDatabaseDeleteCmd) cmdAliases() []string { return nil }

func (c *dbaasDatabaseDeleteCmd) cmdShort() string { return "Delete DBAAS database" }

func (c *dbaasDatabaseDeleteCmd) cmdLong() string {
return `This command deletes a DBAAS database for the specified service.`
}

func (c *dbaasDatabaseDeleteCmd) cmdPreRun(cmd *cobra.Command, args []string) error {

cmdSetZoneFlagFromDefault(cmd)
return cliCommandDefaultPreRun(c, cmd, args)
}

func (c *dbaasDatabaseDeleteCmd) cmdRun(cmd *cobra.Command, args []string) error {

ctx := gContext
db, err := dbaasGetV3(ctx, c.Name, c.Zone)
if err != nil {
return err
}

switch db.Type {
case "mysql":
return c.deleteMysql(cmd, args)
case "pg":
return c.deletePg(cmd, args)
default:
return fmt.Errorf("creating database unsupported for service of type %q", db.Type)
}

}

func init() {
cobra.CheckErr(registerCLICommand(dbaasDatabaseCmd, &dbaasDatabaseDeleteCmd{
cliCommandSettings: defaultCLICmdSettings(),
}))
}
64 changes: 64 additions & 0 deletions cmd/dbaas_database_delete_mysql.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package cmd

import (
"fmt"

"github.com/exoscale/cli/pkg/account"
"github.com/exoscale/cli/pkg/globalstate"
exoapi "github.com/exoscale/egoscale/v2/api"
v3 "github.com/exoscale/egoscale/v3"
"github.com/spf13/cobra"
)

func (c dbaasDatabaseDeleteCmd) deleteMysql(cmd *cobra.Command, _ []string) error {
ctx := gContext

client, err := switchClientZoneV3(ctx, globalstate.EgoscaleV3Client, v3.ZoneName(c.Zone))
if err != nil {
return err
}

s, err := client.GetDBAASServiceMysql(ctx, c.Name)
if err != nil {
return err
}

dbFound := false
for _, db := range s.Databases {
if db == v3.DBAASMysqlDatabaseName(c.Database) {
dbFound = true
break
}
}

if !dbFound {
return fmt.Errorf("database %q not found for service %q", c.Database, c.Name)
}
if !c.Force {
if !askQuestion(fmt.Sprintf(
"Are you sure you want to delete database %q", c.Database)) {
return nil
}
}

op, err := client.DeleteDBAASMysqlDatabase(ctx, c.Name, c.Database)
if err != nil {
return err
}

decorateAsyncOperation(fmt.Sprintf("Deleting DBaaS database %q", c.Database), func() {
op, err = client.Wait(ctx, op, v3.OperationStateSuccess)
})
if err != nil {
return err
}

if !globalstate.Quiet {
return c.outputFunc((&dbaasServiceShowCmd{
Name: c.Name,
Zone: c.Zone,
}).showDatabaseServiceMysql(exoapi.WithEndpoint(gContext, exoapi.NewReqEndpoint(account.CurrentAccount.Environment, c.Zone))))
}

return err
}
Loading
Loading