Skip to content

Commit e3bb016

Browse files
1gtmEmruz Hossain
andauthored
[cherry-pick] Add TLS support for backup and Restore (#328) (#338)
Signed-off-by: suaas21 <sagor@appscode.com> Co-authored-by: Emruz Hossain <emruz@appscode.com>
1 parent c9a5ddf commit e3bb016

File tree

6 files changed

+59
-38
lines changed

6 files changed

+59
-38
lines changed

docs/examples/backup/sample-mysql.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
apiVersion: kubedb.com/v1alpha1
1+
apiVersion: kubedb.com/v1alpha2
22
kind: MySQL
33
metadata:
44
name: sample-mysql
55
namespace: demo
66
spec:
7-
version: "8.0.14"
7+
version: "8.0.21-v1"
88
replicas: 1
99
storageType: Durable
1010
storage:
Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
apiVersion: kubedb.com/v1alpha1
1+
apiVersion: kubedb.com/v1alpha2
22
kind: MySQL
33
metadata:
44
name: restored-mysql
55
namespace: demo
66
spec:
7-
version: "8.0.14"
8-
databaseSecret:
9-
secretName: sample-mysql-auth
7+
version: "8.0.21-v1"
8+
authSecret:
9+
name: sample-mysql-auth
1010
replicas: 1
1111
storageType: Durable
1212
storage:
@@ -15,7 +15,4 @@ spec:
1515
resources:
1616
requests:
1717
storage: 50Mi
18-
init:
19-
stashRestoreSession:
20-
name: restore-sample-mysql
2118
terminationPolicy: WipeOut

docs/mysql.md

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,13 @@ Let's deploy a sample MySQL database and insert some data into it.
5454
Below is the YAML of a sample MySQL CRD that we are going to create for this tutorial:
5555

5656
```yaml
57-
apiVersion: kubedb.com/v1alpha1
57+
apiVersion: kubedb.com/v1alpha2
5858
kind: MySQL
5959
metadata:
6060
name: sample-mysql
6161
namespace: demo
6262
spec:
63-
version: "8.0.14"
63+
version: "8.0.21-v1"
6464
replicas: 1
6565
storageType: Durable
6666
storage:
@@ -166,16 +166,16 @@ The following YAML shows a minimal AppBinding specification that you have to cre
166166
apiVersion: appcatalog.appscode.com/v1alpha1
167167
kind: AppBinding
168168
metadata:
169-
name: <my_custom_appbinding_name>
170-
namespace: <my_database_namespace>
169+
name: my-custom-appbinding-name
170+
namespace: my-database-namespace
171171
spec:
172172
clientConfig:
173173
service:
174-
name: <my_database_service_name>
175-
port: <my_database_port_number>
174+
name: my-database-service-name
175+
port: 3306 # my_database_port_number
176176
scheme: mysql
177177
secret:
178-
name: <my_database_credentials_secret_name>
178+
name: my-database-credentials-secret-name
179179
# type field is optional. you can keep it empty.
180180
# if you keep it empty then the value of TARGET_APP_RESOURCE variable
181181
# will be set to "appbinding" during auto-backup.
@@ -439,15 +439,15 @@ Now, we have to deploy the restored database similarly as we have deployed the o
439439
Below is the YAML for `MySQL` CRD we are going deploy to initialize from backup,
440440

441441
```yaml
442-
apiVersion: kubedb.com/v1alpha1
442+
apiVersion: kubedb.com/v1alpha2
443443
kind: MySQL
444444
metadata:
445445
name: restored-mysql
446446
namespace: demo
447447
spec:
448-
version: "8.0.14"
449-
databaseSecret:
450-
secretName: sample-mysql-auth
448+
version: "8.0.21-v1"
449+
authSecret:
450+
name: sample-mysql-auth
451451
replicas: 1
452452
storageType: Durable
453453
storage:
@@ -456,9 +456,6 @@ spec:
456456
resources:
457457
requests:
458458
storage: 50Mi
459-
init:
460-
stashRestoreSession:
461-
name: sample-mysql-restore
462459
terminationPolicy: WipeOut
463460
```
464461

pkg/backup.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ package pkg
1919
import (
2020
"context"
2121
"fmt"
22+
"io/ioutil"
23+
"os"
2224
"path/filepath"
2325
"strings"
2426

@@ -38,14 +40,17 @@ import (
3840
v1 "kmodules.xyz/offshoot-api/api/v1"
3941
)
4042

43+
const (
44+
MySQLTLSRootCA = "ca.crt"
45+
)
46+
4147
func NewCmdBackup() *cobra.Command {
4248
var (
4349
masterURL string
4450
kubeconfigPath string
4551
opt = mysqlOptions{
4652

47-
myArgs: "--all-databases",
48-
waitTimeout: 300,
53+
myArgs: "--all-databases",
4954
setupOptions: restic.SetupOptions{
5055
ScratchDir: restic.DefaultScratchDir,
5156
EnableCache: false,
@@ -221,8 +226,20 @@ func (opt *mysqlOptions) backupMySQL(targetRef api_v1beta1.TargetRef) (*restic.B
221226
opt.backupOptions.StdinPipeCommand.Args = append(opt.backupOptions.StdinPipeCommand.Args, arg)
222227
}
223228

229+
// if ssl enabled, add ca.crt in the arguments
230+
if appBinding.Spec.ClientConfig.CABundle != nil {
231+
if err := ioutil.WriteFile(filepath.Join(opt.setupOptions.ScratchDir, MySQLTLSRootCA), appBinding.Spec.ClientConfig.CABundle, os.ModePerm); err != nil {
232+
return nil, err
233+
}
234+
tlsCreds := []interface{}{
235+
fmt.Sprintf("--ssl-ca=%v", filepath.Join(opt.setupOptions.ScratchDir, MySQLTLSRootCA)),
236+
}
237+
238+
opt.backupOptions.StdinPipeCommand.Args = append(opt.backupOptions.StdinPipeCommand.Args, tlsCreds...)
239+
}
240+
224241
// wait for DB ready
225-
err = waitForDBReady(appBinding, appBindingSecret, opt.waitTimeout)
242+
err = opt.waitForDBReady(appBinding, appBindingSecret)
226243
if err != nil {
227244
return nil, err
228245
}

pkg/restore.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ package pkg
1919
import (
2020
"context"
2121
"fmt"
22+
"io/ioutil"
23+
"os"
2224
"path/filepath"
2325
"strings"
2426

@@ -190,8 +192,20 @@ func (opt *mysqlOptions) restoreMySQL(targetRef api_v1beta1.TargetRef) (*restic.
190192
opt.dumpOptions.StdoutPipeCommand.Args = append(opt.dumpOptions.StdoutPipeCommand.Args, arg)
191193
}
192194

195+
// if ssl enabled, add ca.crt in the arguments
196+
if appBinding.Spec.ClientConfig.CABundle != nil {
197+
if err := ioutil.WriteFile(filepath.Join(opt.setupOptions.ScratchDir, MySQLTLSRootCA), appBinding.Spec.ClientConfig.CABundle, os.ModePerm); err != nil {
198+
return nil, err
199+
}
200+
tlsCreds := []interface{}{
201+
fmt.Sprintf("--ssl-ca=%v", filepath.Join(opt.setupOptions.ScratchDir, MySQLTLSRootCA)),
202+
}
203+
204+
opt.dumpOptions.StdoutPipeCommand.Args = append(opt.dumpOptions.StdoutPipeCommand.Args, tlsCreds...)
205+
}
206+
193207
// wait for DB ready
194-
err = waitForDBReady(appBinding, appBindingSecret, opt.waitTimeout)
208+
err = opt.waitForDBReady(appBinding, appBindingSecret)
195209
if err != nil {
196210
return nil, err
197211
}

pkg/utils.go

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,14 @@ package pkg
1818

1919
import (
2020
"fmt"
21-
"time"
21+
"path/filepath"
2222

2323
stash "stash.appscode.dev/apimachinery/client/clientset/versioned"
2424
"stash.appscode.dev/apimachinery/pkg/restic"
2525

2626
"github.com/codeskyblue/go-sh"
2727
"gomodules.xyz/x/log"
2828
core "k8s.io/api/core/v1"
29-
"k8s.io/apimachinery/pkg/util/wait"
3029
"k8s.io/client-go/kubernetes"
3130
"kmodules.xyz/custom-resources/apis/appcatalog/v1alpha1"
3231
appcatalog_cs "kmodules.xyz/custom-resources/client/clientset/versioned"
@@ -58,7 +57,7 @@ type mysqlOptions struct {
5857
dumpOptions restic.DumpOptions
5958
}
6059

61-
func waitForDBReady(appBinding *v1alpha1.AppBinding, secret *core.Secret, waitTimeout int32) error {
60+
func (opt *mysqlOptions) waitForDBReady(appBinding *v1alpha1.AppBinding, secret *core.Secret) error {
6261
log.Infoln("Waiting for the database to be ready.....")
6362
shell := sh.NewSession()
6463
shell.SetEnv(EnvMySqlPassword, string(secret.Data[MySqlPassword]))
@@ -70,17 +69,14 @@ func waitForDBReady(appBinding *v1alpha1.AppBinding, secret *core.Secret, waitTi
7069
args = append(args, fmt.Sprintf("--port=%d", appBinding.Spec.ClientConfig.Service.Port))
7170
}
7271

72+
if appBinding.Spec.ClientConfig.CABundle != nil {
73+
args = append(args, fmt.Sprintf("--ssl-ca=%v", filepath.Join(opt.setupOptions.ScratchDir, MySQLTLSRootCA)))
74+
}
75+
7376
// Execute "SELECT 1" query to the database. It should return an error when mysqld is not ready.
7477
args = append(args, "-e", "SELECT 1;")
7578

7679
// don't show the output of the query
7780
shell.Stdout = nil
78-
return wait.PollImmediate(5*time.Second, time.Duration(waitTimeout)*time.Second, func() (done bool, err error) {
79-
if err := shell.Command("mysql", args...).Run(); err == nil {
80-
log.Infoln("Database is accepting connection....")
81-
return true, nil
82-
}
83-
log.Infoln("Retrying after 5 seconds....")
84-
return false, nil
85-
})
81+
return shell.Command("mysql", args...).Run()
8682
}

0 commit comments

Comments
 (0)