Skip to content

Commit

Permalink
feat: Run database commands in a separate pod
Browse files Browse the repository at this point in the history
  • Loading branch information
gabe565 committed Oct 4, 2023
1 parent 3beb8cf commit 0640dad
Show file tree
Hide file tree
Showing 24 changed files with 382 additions and 174 deletions.
8 changes: 8 additions & 0 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package cmd
import (
"fmt"
"os"
"os/signal"
"strings"
"syscall"

"github.com/clevyr/kubedb/cmd/dump"
"github.com/clevyr/kubedb/cmd/exec"
Expand Down Expand Up @@ -47,6 +49,8 @@ Dynamic Env Var Variables:
flags.Namespace(cmd)
flags.Dialect(cmd)
flags.Pod(cmd)
flags.JobPodLabels(cmd)
flags.NoJob(cmd)
flags.LogLevel(cmd)
flags.LogFormat(cmd)
flags.GitHubActions(cmd)
Expand Down Expand Up @@ -78,6 +82,10 @@ Dynamic Env Var Variables:
}

func preRun(cmd *cobra.Command, args []string) error {
ctx, cancel := signal.NotifyContext(cmd.Context(), os.Interrupt, os.Kill, syscall.SIGTERM)
cmd.PersistentPostRun = func(cmd *cobra.Command, args []string) { cancel() }
cmd.SetContext(ctx)

kubeconfig, err := cmd.Flags().GetString("kubeconfig")
if err != nil {
panic(err)
Expand Down
5 changes: 4 additions & 1 deletion cmd/dump/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func preRun(cmd *cobra.Command, args []string) (err error) {
cmd.SilenceUsage = false
}

if err := util.DefaultSetup(cmd, &action.Global); err != nil {
if err := util.DefaultSetup(cmd, &action.Global, util.SetupOptions{Name: "dump"}); err != nil {
return err
}

Expand All @@ -99,5 +99,8 @@ func preRun(cmd *cobra.Command, args []string) (err error) {
}

func run(cmd *cobra.Command, args []string) (err error) {
defer func() {
util.Teardown(cmd, &action.Global)
}()
return action.Run(cmd.Context())
}
10 changes: 9 additions & 1 deletion cmd/exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ func NewCommand() *cobra.Command {
RunE: run,
PreRunE: preRun,
}

return cmd
}

Expand All @@ -27,9 +28,16 @@ func preRun(cmd *cobra.Command, args []string) error {
return err
}

return util.DefaultSetup(cmd, &action.Global)
if err := util.DefaultSetup(cmd, &action.Global, util.SetupOptions{Name: "exec"}); err != nil {
return err
}

return nil
}

func run(cmd *cobra.Command, args []string) (err error) {
defer func() {
util.Teardown(cmd, &action.Global)
}()
return action.Run(cmd.Context())
}
6 changes: 5 additions & 1 deletion cmd/port_forward/port_forward.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func preRun(cmd *cobra.Command, args []string) error {
return err
}

err := util.DefaultSetup(cmd, &action.Global)
err := util.DefaultSetup(cmd, &action.Global, util.SetupOptions{DisableJob: true})
if err != nil {
return err
}
Expand All @@ -59,6 +59,7 @@ func preRun(cmd *cobra.Command, args []string) error {
} else {
port, err := strconv.ParseUint(args[0], 10, 16)
if err != nil {
util.Teardown(cmd, &action.Global)
return err
}
action.LocalPort = uint16(port)
Expand All @@ -67,5 +68,8 @@ func preRun(cmd *cobra.Command, args []string) error {
}

func run(cmd *cobra.Command, args []string) (err error) {
defer func() {
util.Teardown(cmd, &action.Global)
}()
return action.Run(cmd.Context())
}
6 changes: 5 additions & 1 deletion cmd/restore/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func preRun(cmd *cobra.Command, args []string) (err error) {
action.Filename = args[0]
}

if err := util.DefaultSetup(cmd, &action.Global); err != nil {
if err := util.DefaultSetup(cmd, &action.Global, util.SetupOptions{Name: "restore"}); err != nil {
return err
}

Expand All @@ -88,6 +88,10 @@ func preRun(cmd *cobra.Command, args []string) (err error) {
}

func run(cmd *cobra.Command, args []string) (err error) {
defer func() {
util.Teardown(cmd, &action.Global)
}()

if !action.Force {
tty := term.TTY{In: os.Stdin}.IsTerminalIn()
if tty {
Expand Down
26 changes: 14 additions & 12 deletions docs/kubedb.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,20 @@ Dynamic Env Var Variables:
### Options

```
--context string The name of the kubeconfig context to use
-d, --dbname string Database name to connect to
--dialect string Database dialect. Detected if not set. (postgres, mariadb, mongodb)
-h, --help help for kubedb
--kubeconfig string Path to the kubeconfig file (default "$HOME/.kube/config")
--log-format string Log formatter (text, json) (default "text")
--log-level string Log level (trace, debug, info, warning, error, fatal, panic) (default "info")
-n, --namespace string The Kubernetes namespace scope
-p, --password string Database password
--pod string Force a specific pod. If this flag is set, dialect is required.
-U, --username string Database username
-v, --version version for kubedb
--context string The name of the kubeconfig context to use
-d, --dbname string Database name to connect to
--dialect string Database dialect. Detected if not set. (postgres, mariadb, mongodb)
-h, --help help for kubedb
--job-pod-labels stringToString Pod labels to add to the job (default [])
--kubeconfig string Path to the kubeconfig file (default "$HOME/.kube/config")
--log-format string Log formatter (text, json) (default "text")
--log-level string Log level (trace, debug, info, warning, error, fatal, panic) (default "info")
-n, --namespace string The Kubernetes namespace scope
--no-job Database commands will be run in the database pod instead of a dedicated job
-p, --password string Database password
--pod string Force a specific pod. If this flag is set, dialect is required.
-U, --username string Database username
-v, --version version for kubedb
```

### SEE ALSO
Expand Down
22 changes: 12 additions & 10 deletions docs/kubedb_dump.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,18 @@ kubedb dump [filename] [flags]
### Options inherited from parent commands

```
--context string The name of the kubeconfig context to use
-d, --dbname string Database name to connect to
--dialect string Database dialect. Detected if not set. (postgres, mariadb, mongodb)
--kubeconfig string Path to the kubeconfig file (default "$HOME/.kube/config")
--log-format string Log formatter (text, json) (default "text")
--log-level string Log level (trace, debug, info, warning, error, fatal, panic) (default "info")
-n, --namespace string The Kubernetes namespace scope
-p, --password string Database password
--pod string Force a specific pod. If this flag is set, dialect is required.
-U, --username string Database username
--context string The name of the kubeconfig context to use
-d, --dbname string Database name to connect to
--dialect string Database dialect. Detected if not set. (postgres, mariadb, mongodb)
--job-pod-labels stringToString Pod labels to add to the job (default [])
--kubeconfig string Path to the kubeconfig file (default "$HOME/.kube/config")
--log-format string Log formatter (text, json) (default "text")
--log-level string Log level (trace, debug, info, warning, error, fatal, panic) (default "info")
-n, --namespace string The Kubernetes namespace scope
--no-job Database commands will be run in the database pod instead of a dedicated job
-p, --password string Database password
--pod string Force a specific pod. If this flag is set, dialect is required.
-U, --username string Database username
```

### SEE ALSO
Expand Down
22 changes: 12 additions & 10 deletions docs/kubedb_exec.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,18 @@ kubedb exec [flags]
### Options inherited from parent commands

```
--context string The name of the kubeconfig context to use
-d, --dbname string Database name to connect to
--dialect string Database dialect. Detected if not set. (postgres, mariadb, mongodb)
--kubeconfig string Path to the kubeconfig file (default "$HOME/.kube/config")
--log-format string Log formatter (text, json) (default "text")
--log-level string Log level (trace, debug, info, warning, error, fatal, panic) (default "info")
-n, --namespace string The Kubernetes namespace scope
-p, --password string Database password
--pod string Force a specific pod. If this flag is set, dialect is required.
-U, --username string Database username
--context string The name of the kubeconfig context to use
-d, --dbname string Database name to connect to
--dialect string Database dialect. Detected if not set. (postgres, mariadb, mongodb)
--job-pod-labels stringToString Pod labels to add to the job (default [])
--kubeconfig string Path to the kubeconfig file (default "$HOME/.kube/config")
--log-format string Log formatter (text, json) (default "text")
--log-level string Log level (trace, debug, info, warning, error, fatal, panic) (default "info")
-n, --namespace string The Kubernetes namespace scope
--no-job Database commands will be run in the database pod instead of a dedicated job
-p, --password string Database password
--pod string Force a specific pod. If this flag is set, dialect is required.
-U, --username string Database username
```

### SEE ALSO
Expand Down
22 changes: 12 additions & 10 deletions docs/kubedb_port-forward.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,18 @@ kubedb port-forward [local_port] [flags]
### Options inherited from parent commands

```
--context string The name of the kubeconfig context to use
-d, --dbname string Database name to connect to
--dialect string Database dialect. Detected if not set. (postgres, mariadb, mongodb)
--kubeconfig string Path to the kubeconfig file (default "$HOME/.kube/config")
--log-format string Log formatter (text, json) (default "text")
--log-level string Log level (trace, debug, info, warning, error, fatal, panic) (default "info")
-n, --namespace string The Kubernetes namespace scope
-p, --password string Database password
--pod string Force a specific pod. If this flag is set, dialect is required.
-U, --username string Database username
--context string The name of the kubeconfig context to use
-d, --dbname string Database name to connect to
--dialect string Database dialect. Detected if not set. (postgres, mariadb, mongodb)
--job-pod-labels stringToString Pod labels to add to the job (default [])
--kubeconfig string Path to the kubeconfig file (default "$HOME/.kube/config")
--log-format string Log formatter (text, json) (default "text")
--log-level string Log level (trace, debug, info, warning, error, fatal, panic) (default "info")
-n, --namespace string The Kubernetes namespace scope
--no-job Database commands will be run in the database pod instead of a dedicated job
-p, --password string Database password
--pod string Force a specific pod. If this flag is set, dialect is required.
-U, --username string Database username
```

### SEE ALSO
Expand Down
22 changes: 12 additions & 10 deletions docs/kubedb_restore.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,18 @@ kubedb restore filename [flags]
### Options inherited from parent commands

```
--context string The name of the kubeconfig context to use
-d, --dbname string Database name to connect to
--dialect string Database dialect. Detected if not set. (postgres, mariadb, mongodb)
--kubeconfig string Path to the kubeconfig file (default "$HOME/.kube/config")
--log-format string Log formatter (text, json) (default "text")
--log-level string Log level (trace, debug, info, warning, error, fatal, panic) (default "info")
-n, --namespace string The Kubernetes namespace scope
-p, --password string Database password
--pod string Force a specific pod. If this flag is set, dialect is required.
-U, --username string Database username
--context string The name of the kubeconfig context to use
-d, --dbname string Database name to connect to
--dialect string Database dialect. Detected if not set. (postgres, mariadb, mongodb)
--job-pod-labels stringToString Pod labels to add to the job (default [])
--kubeconfig string Path to the kubeconfig file (default "$HOME/.kube/config")
--log-format string Log formatter (text, json) (default "text")
--log-level string Log level (trace, debug, info, warning, error, fatal, panic) (default "info")
-n, --namespace string The Kubernetes namespace scope
--no-job Database commands will be run in the database pod instead of a dedicated job
-p, --password string Database password
--pod string Force a specific pod. If this flag is set, dialect is required.
-U, --username string Database username
```

### SEE ALSO
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ require (
k8s.io/apimachinery v0.28.2
k8s.io/client-go v0.28.2
k8s.io/kubectl v0.28.2
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2
)

require (
Expand Down Expand Up @@ -81,7 +82,6 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog/v2 v2.100.1 // indirect
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
Expand Down
20 changes: 10 additions & 10 deletions internal/actions/dump/dump_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,28 @@ func Test_buildCommand(t *testing.T) {
}{
{
"postgres-gzip",
args{Dump{Dump: config.Dump{Global: config.Global{Dialect: dialect.Postgres{}, Database: "d", Username: "u", RemoteGzip: true}}}},
command.NewBuilder(pgpassword, "pg_dump", "--host=127.0.0.1", "--username=u", "--dbname=d", "--verbose", command.Pipe, "gzip", "--force"),
args{Dump{Dump: config.Dump{Global: config.Global{Dialect: dialect.Postgres{}, Host: "1.1.1.1", Database: "d", Username: "u", RemoteGzip: true}}}},
command.NewBuilder(pgpassword, "pg_dump", "--host=1.1.1.1", "--username=u", "--dbname=d", "--verbose", command.Pipe, "gzip", "--force"),
},
{
"postgres-gzip-no-compression",
args{Dump{Dump: config.Dump{Global: config.Global{Dialect: dialect.Postgres{}, Database: "d", Username: "u"}}}},
command.NewBuilder(pgpassword, "pg_dump", "--host=127.0.0.1", "--username=u", "--dbname=d", "--verbose"),
args{Dump{Dump: config.Dump{Global: config.Global{Dialect: dialect.Postgres{}, Host: "1.1.1.1", Database: "d", Username: "u"}}}},
command.NewBuilder(pgpassword, "pg_dump", "--host=1.1.1.1", "--username=u", "--dbname=d", "--verbose"),
},
{
"postgres-plain",
args{Dump{Dump: config.Dump{Files: config.Files{Format: sqlformat.Plain}, Global: config.Global{Dialect: dialect.Postgres{}, Database: "d", Username: "u", RemoteGzip: true}}}},
command.NewBuilder(pgpassword, "pg_dump", "--host=127.0.0.1", "--username=u", "--dbname=d", "--verbose", command.Pipe, "gzip", "--force"),
args{Dump{Dump: config.Dump{Files: config.Files{Format: sqlformat.Plain}, Global: config.Global{Dialect: dialect.Postgres{}, Host: "1.1.1.1", Database: "d", Username: "u", RemoteGzip: true}}}},
command.NewBuilder(pgpassword, "pg_dump", "--host=1.1.1.1", "--username=u", "--dbname=d", "--verbose", command.Pipe, "gzip", "--force"),
},
{
"postgres-custom",
args{Dump{Dump: config.Dump{Files: config.Files{Format: sqlformat.Custom}, Global: config.Global{Dialect: dialect.Postgres{}, Database: "d", Username: "u", RemoteGzip: true}}}},
command.NewBuilder(pgpassword, "pg_dump", "--host=127.0.0.1", "--username=u", "--dbname=d", "--format=c", "--verbose"),
args{Dump{Dump: config.Dump{Files: config.Files{Format: sqlformat.Custom}, Global: config.Global{Dialect: dialect.Postgres{}, Host: "1.1.1.1", Database: "d", Username: "u", RemoteGzip: true}}}},
command.NewBuilder(pgpassword, "pg_dump", "--host=1.1.1.1", "--username=u", "--dbname=d", "--format=c", "--verbose"),
},
{
"mariadb-gzip",
args{Dump{Dump: config.Dump{Files: config.Files{Format: sqlformat.Gzip}, Global: config.Global{Dialect: dialect.MariaDB{}, Database: "d", Username: "u", RemoteGzip: true}}}},
command.NewBuilder(mysql_pwd, "mysqldump", "--host=127.0.0.1", "--user=u", "d", "--verbose", command.Pipe, "gzip", "--force"),
args{Dump{Dump: config.Dump{Files: config.Files{Format: sqlformat.Gzip}, Global: config.Global{Dialect: dialect.MariaDB{}, Host: "1.1.1.1", Database: "d", Username: "u", RemoteGzip: true}}}},
command.NewBuilder(mysql_pwd, "mysqldump", "--host=1.1.1.1", "--user=u", "d", "--verbose", command.Pipe, "gzip", "--force"),
},
}
for _, tt := range tests {
Expand Down
12 changes: 6 additions & 6 deletions internal/actions/restore/restore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,26 +29,26 @@ func Test_buildCommand(t *testing.T) {
{
"postgres-gzip",
args{
config.Restore{Global: config.Global{Dialect: dialect.Postgres{}, Database: "d", Username: "u"}},
config.Restore{Global: config.Global{Dialect: dialect.Postgres{}, Host: "1.1.1.1", Database: "d", Username: "u"}},
sqlformat.Gzip,
},
command.NewBuilder("gunzip", "--force", command.Pipe, pgpassword, "psql", "--host=127.0.0.1", "--username=u", "--dbname=d"),
command.NewBuilder("gunzip", "--force", command.Pipe, pgpassword, "psql", "--host=1.1.1.1", "--username=u", "--dbname=d"),
},
{
"postgres-plain",
args{
config.Restore{Global: config.Global{Dialect: dialect.Postgres{}, Database: "d", Username: "u"}},
config.Restore{Global: config.Global{Dialect: dialect.Postgres{}, Host: "1.1.1.1", Database: "d", Username: "u"}},
sqlformat.Gzip,
},
command.NewBuilder("gunzip", "--force", command.Pipe, pgpassword, "psql", "--host=127.0.0.1", "--username=u", "--dbname=d"),
command.NewBuilder("gunzip", "--force", command.Pipe, pgpassword, "psql", "--host=1.1.1.1", "--username=u", "--dbname=d"),
},
{
"postgres-custom",
args{
config.Restore{Global: config.Global{Dialect: dialect.Postgres{}, Database: "d", Username: "u"}},
config.Restore{Global: config.Global{Dialect: dialect.Postgres{}, Host: "1.1.1.1", Database: "d", Username: "u"}},
sqlformat.Gzip,
},
command.NewBuilder("gunzip", "--force", command.Pipe, pgpassword, "psql", "--host=127.0.0.1", "--username=u", "--dbname=d"),
command.NewBuilder("gunzip", "--force", command.Pipe, pgpassword, "psql", "--host=1.1.1.1", "--username=u", "--dbname=d"),
},
}
for _, tt := range tests {
Expand Down
4 changes: 2 additions & 2 deletions internal/config/flags/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ func listTables(cmd *cobra.Command, args []string, toComplete string) ([]string,
return nil, cobra.ShellCompDirectiveError
}

err := util.DefaultSetup(cmd, &conf.Global)
err := util.DefaultSetup(cmd, &conf.Global, util.SetupOptions{DisableJob: true})
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
Expand All @@ -173,7 +173,7 @@ func listDatabases(cmd *cobra.Command, args []string, toComplete string) ([]stri
return nil, cobra.ShellCompDirectiveError
}

err := util.DefaultSetup(cmd, &conf.Global)
err := util.DefaultSetup(cmd, &conf.Global, util.SetupOptions{DisableJob: true})
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
Expand Down
14 changes: 14 additions & 0 deletions internal/config/flags/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,17 @@ func Pod(cmd *cobra.Command) {
panic(err)
}
}

func JobPodLabels(cmd *cobra.Command) {
cmd.PersistentFlags().StringToString("job-pod-labels", map[string]string{}, "Pod labels to add to the job")
if err := viper.BindPFlag("kubernetes.job-pod-labels", cmd.PersistentFlags().Lookup("job-pod-labels")); err != nil {
panic(err)
}
}

func NoJob(cmd *cobra.Command) {
cmd.PersistentFlags().Bool("no-job", false, "Database commands will be run in the database pod instead of a dedicated job")
if err := viper.BindPFlag("kubernetes.no-job", cmd.PersistentFlags().Lookup("no-job")); err != nil {
panic(err)
}
}
Loading

0 comments on commit 0640dad

Please sign in to comment.