Skip to content

Commit 0640dad

Browse files
committed
feat: Run database commands in a separate pod
1 parent 3beb8cf commit 0640dad

24 files changed

+382
-174
lines changed

cmd/cmd.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ package cmd
33
import (
44
"fmt"
55
"os"
6+
"os/signal"
67
"strings"
8+
"syscall"
79

810
"github.com/clevyr/kubedb/cmd/dump"
911
"github.com/clevyr/kubedb/cmd/exec"
@@ -47,6 +49,8 @@ Dynamic Env Var Variables:
4749
flags.Namespace(cmd)
4850
flags.Dialect(cmd)
4951
flags.Pod(cmd)
52+
flags.JobPodLabels(cmd)
53+
flags.NoJob(cmd)
5054
flags.LogLevel(cmd)
5155
flags.LogFormat(cmd)
5256
flags.GitHubActions(cmd)
@@ -78,6 +82,10 @@ Dynamic Env Var Variables:
7882
}
7983

8084
func preRun(cmd *cobra.Command, args []string) error {
85+
ctx, cancel := signal.NotifyContext(cmd.Context(), os.Interrupt, os.Kill, syscall.SIGTERM)
86+
cmd.PersistentPostRun = func(cmd *cobra.Command, args []string) { cancel() }
87+
cmd.SetContext(ctx)
88+
8189
kubeconfig, err := cmd.Flags().GetString("kubeconfig")
8290
if err != nil {
8391
panic(err)

cmd/dump/dump.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func preRun(cmd *cobra.Command, args []string) (err error) {
8787
cmd.SilenceUsage = false
8888
}
8989

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

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

101101
func run(cmd *cobra.Command, args []string) (err error) {
102+
defer func() {
103+
util.Teardown(cmd, &action.Global)
104+
}()
102105
return action.Run(cmd.Context())
103106
}

cmd/exec/exec.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ func NewCommand() *cobra.Command {
1919
RunE: run,
2020
PreRunE: preRun,
2121
}
22+
2223
return cmd
2324
}
2425

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

30-
return util.DefaultSetup(cmd, &action.Global)
31+
if err := util.DefaultSetup(cmd, &action.Global, util.SetupOptions{Name: "exec"}); err != nil {
32+
return err
33+
}
34+
35+
return nil
3136
}
3237

3338
func run(cmd *cobra.Command, args []string) (err error) {
39+
defer func() {
40+
util.Teardown(cmd, &action.Global)
41+
}()
3442
return action.Run(cmd.Context())
3543
}

cmd/port_forward/port_forward.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func preRun(cmd *cobra.Command, args []string) error {
4949
return err
5050
}
5151

52-
err := util.DefaultSetup(cmd, &action.Global)
52+
err := util.DefaultSetup(cmd, &action.Global, util.SetupOptions{DisableJob: true})
5353
if err != nil {
5454
return err
5555
}
@@ -59,6 +59,7 @@ func preRun(cmd *cobra.Command, args []string) error {
5959
} else {
6060
port, err := strconv.ParseUint(args[0], 10, 16)
6161
if err != nil {
62+
util.Teardown(cmd, &action.Global)
6263
return err
6364
}
6465
action.LocalPort = uint16(port)
@@ -67,5 +68,8 @@ func preRun(cmd *cobra.Command, args []string) error {
6768
}
6869

6970
func run(cmd *cobra.Command, args []string) (err error) {
71+
defer func() {
72+
util.Teardown(cmd, &action.Global)
73+
}()
7074
return action.Run(cmd.Context())
7175
}

cmd/restore/restore.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ func preRun(cmd *cobra.Command, args []string) (err error) {
7676
action.Filename = args[0]
7777
}
7878

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

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

9090
func run(cmd *cobra.Command, args []string) (err error) {
91+
defer func() {
92+
util.Teardown(cmd, &action.Global)
93+
}()
94+
9195
if !action.Force {
9296
tty := term.TTY{In: os.Stdin}.IsTerminalIn()
9397
if tty {

docs/kubedb.md

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,20 @@ Dynamic Env Var Variables:
2525
### Options
2626

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

4244
### SEE ALSO

docs/kubedb_dump.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,18 @@ kubedb dump [filename] [flags]
3333
### Options inherited from parent commands
3434

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

4850
### SEE ALSO

docs/kubedb_exec.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,18 @@ kubedb exec [flags]
1515
### Options inherited from parent commands
1616

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

3032
### SEE ALSO

docs/kubedb_port-forward.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,18 @@ kubedb port-forward [local_port] [flags]
1616
### Options inherited from parent commands
1717

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

3133
### SEE ALSO

docs/kubedb_restore.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,18 @@ kubedb restore filename [flags]
3232
### Options inherited from parent commands
3333

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

4749
### SEE ALSO

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ require (
1919
k8s.io/apimachinery v0.28.2
2020
k8s.io/client-go v0.28.2
2121
k8s.io/kubectl v0.28.2
22+
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2
2223
)
2324

2425
require (
@@ -81,7 +82,6 @@ require (
8182
gopkg.in/yaml.v3 v3.0.1 // indirect
8283
k8s.io/klog/v2 v2.100.1 // indirect
8384
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
84-
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect
8585
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
8686
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
8787
sigs.k8s.io/yaml v1.3.0 // indirect

internal/actions/dump/dump_test.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,28 +24,28 @@ func Test_buildCommand(t *testing.T) {
2424
}{
2525
{
2626
"postgres-gzip",
27-
args{Dump{Dump: config.Dump{Global: config.Global{Dialect: dialect.Postgres{}, Database: "d", Username: "u", RemoteGzip: true}}}},
28-
command.NewBuilder(pgpassword, "pg_dump", "--host=127.0.0.1", "--username=u", "--dbname=d", "--verbose", command.Pipe, "gzip", "--force"),
27+
args{Dump{Dump: config.Dump{Global: config.Global{Dialect: dialect.Postgres{}, Host: "1.1.1.1", Database: "d", Username: "u", RemoteGzip: true}}}},
28+
command.NewBuilder(pgpassword, "pg_dump", "--host=1.1.1.1", "--username=u", "--dbname=d", "--verbose", command.Pipe, "gzip", "--force"),
2929
},
3030
{
3131
"postgres-gzip-no-compression",
32-
args{Dump{Dump: config.Dump{Global: config.Global{Dialect: dialect.Postgres{}, Database: "d", Username: "u"}}}},
33-
command.NewBuilder(pgpassword, "pg_dump", "--host=127.0.0.1", "--username=u", "--dbname=d", "--verbose"),
32+
args{Dump{Dump: config.Dump{Global: config.Global{Dialect: dialect.Postgres{}, Host: "1.1.1.1", Database: "d", Username: "u"}}}},
33+
command.NewBuilder(pgpassword, "pg_dump", "--host=1.1.1.1", "--username=u", "--dbname=d", "--verbose"),
3434
},
3535
{
3636
"postgres-plain",
37-
args{Dump{Dump: config.Dump{Files: config.Files{Format: sqlformat.Plain}, Global: config.Global{Dialect: dialect.Postgres{}, Database: "d", Username: "u", RemoteGzip: true}}}},
38-
command.NewBuilder(pgpassword, "pg_dump", "--host=127.0.0.1", "--username=u", "--dbname=d", "--verbose", command.Pipe, "gzip", "--force"),
37+
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}}}},
38+
command.NewBuilder(pgpassword, "pg_dump", "--host=1.1.1.1", "--username=u", "--dbname=d", "--verbose", command.Pipe, "gzip", "--force"),
3939
},
4040
{
4141
"postgres-custom",
42-
args{Dump{Dump: config.Dump{Files: config.Files{Format: sqlformat.Custom}, Global: config.Global{Dialect: dialect.Postgres{}, Database: "d", Username: "u", RemoteGzip: true}}}},
43-
command.NewBuilder(pgpassword, "pg_dump", "--host=127.0.0.1", "--username=u", "--dbname=d", "--format=c", "--verbose"),
42+
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}}}},
43+
command.NewBuilder(pgpassword, "pg_dump", "--host=1.1.1.1", "--username=u", "--dbname=d", "--format=c", "--verbose"),
4444
},
4545
{
4646
"mariadb-gzip",
47-
args{Dump{Dump: config.Dump{Files: config.Files{Format: sqlformat.Gzip}, Global: config.Global{Dialect: dialect.MariaDB{}, Database: "d", Username: "u", RemoteGzip: true}}}},
48-
command.NewBuilder(mysql_pwd, "mysqldump", "--host=127.0.0.1", "--user=u", "d", "--verbose", command.Pipe, "gzip", "--force"),
47+
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}}}},
48+
command.NewBuilder(mysql_pwd, "mysqldump", "--host=1.1.1.1", "--user=u", "d", "--verbose", command.Pipe, "gzip", "--force"),
4949
},
5050
}
5151
for _, tt := range tests {

internal/actions/restore/restore_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,26 +29,26 @@ func Test_buildCommand(t *testing.T) {
2929
{
3030
"postgres-gzip",
3131
args{
32-
config.Restore{Global: config.Global{Dialect: dialect.Postgres{}, Database: "d", Username: "u"}},
32+
config.Restore{Global: config.Global{Dialect: dialect.Postgres{}, Host: "1.1.1.1", Database: "d", Username: "u"}},
3333
sqlformat.Gzip,
3434
},
35-
command.NewBuilder("gunzip", "--force", command.Pipe, pgpassword, "psql", "--host=127.0.0.1", "--username=u", "--dbname=d"),
35+
command.NewBuilder("gunzip", "--force", command.Pipe, pgpassword, "psql", "--host=1.1.1.1", "--username=u", "--dbname=d"),
3636
},
3737
{
3838
"postgres-plain",
3939
args{
40-
config.Restore{Global: config.Global{Dialect: dialect.Postgres{}, Database: "d", Username: "u"}},
40+
config.Restore{Global: config.Global{Dialect: dialect.Postgres{}, Host: "1.1.1.1", Database: "d", Username: "u"}},
4141
sqlformat.Gzip,
4242
},
43-
command.NewBuilder("gunzip", "--force", command.Pipe, pgpassword, "psql", "--host=127.0.0.1", "--username=u", "--dbname=d"),
43+
command.NewBuilder("gunzip", "--force", command.Pipe, pgpassword, "psql", "--host=1.1.1.1", "--username=u", "--dbname=d"),
4444
},
4545
{
4646
"postgres-custom",
4747
args{
48-
config.Restore{Global: config.Global{Dialect: dialect.Postgres{}, Database: "d", Username: "u"}},
48+
config.Restore{Global: config.Global{Dialect: dialect.Postgres{}, Host: "1.1.1.1", Database: "d", Username: "u"}},
4949
sqlformat.Gzip,
5050
},
51-
command.NewBuilder("gunzip", "--force", command.Pipe, pgpassword, "psql", "--host=127.0.0.1", "--username=u", "--dbname=d"),
51+
command.NewBuilder("gunzip", "--force", command.Pipe, pgpassword, "psql", "--host=1.1.1.1", "--username=u", "--dbname=d"),
5252
},
5353
}
5454
for _, tt := range tests {

internal/config/flags/database.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ func listTables(cmd *cobra.Command, args []string, toComplete string) ([]string,
159159
return nil, cobra.ShellCompDirectiveError
160160
}
161161

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

176-
err := util.DefaultSetup(cmd, &conf.Global)
176+
err := util.DefaultSetup(cmd, &conf.Global, util.SetupOptions{DisableJob: true})
177177
if err != nil {
178178
return nil, cobra.ShellCompDirectiveError
179179
}

internal/config/flags/kubernetes.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,17 @@ func Pod(cmd *cobra.Command) {
113113
panic(err)
114114
}
115115
}
116+
117+
func JobPodLabels(cmd *cobra.Command) {
118+
cmd.PersistentFlags().StringToString("job-pod-labels", map[string]string{}, "Pod labels to add to the job")
119+
if err := viper.BindPFlag("kubernetes.job-pod-labels", cmd.PersistentFlags().Lookup("job-pod-labels")); err != nil {
120+
panic(err)
121+
}
122+
}
123+
124+
func NoJob(cmd *cobra.Command) {
125+
cmd.PersistentFlags().Bool("no-job", false, "Database commands will be run in the database pod instead of a dedicated job")
126+
if err := viper.BindPFlag("kubernetes.no-job", cmd.PersistentFlags().Lookup("no-job")); err != nil {
127+
panic(err)
128+
}
129+
}

0 commit comments

Comments
 (0)