Skip to content

Commit b2c201b

Browse files
pooknullgkechhors
authored
K8SPS-400: custom options for xtrabackup, xbstream, xbcloud (#986)
* K8SPS-400: custom options for xtrabackup, xbstream, xbcloud https://perconadev.atlassian.net/browse/K8SPS-400 * fix sidecar * add e2e test * fix unit test * use slices.IndexFunc * address comments * make generate * fix quoting in restore script * update crd --------- Co-authored-by: George Kechagias <[email protected]> Co-authored-by: Viacheslav Sarzhan <[email protected]>
1 parent 168c12a commit b2c201b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+2404
-389
lines changed

api/v1alpha1/perconaservermysql_types.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import (
3939

4040
"github.com/percona/percona-server-mysql-operator/pkg/naming"
4141
"github.com/percona/percona-server-mysql-operator/pkg/platform"
42+
"github.com/percona/percona-server-mysql-operator/pkg/util"
4243
"github.com/percona/percona-server-mysql-operator/pkg/version"
4344
)
4445

@@ -326,6 +327,62 @@ type BackupStorageSpec struct {
326327
ContainerSecurityContext *corev1.SecurityContext `json:"containerSecurityContext,omitempty"`
327328
RuntimeClassName *string `json:"runtimeClassName,omitempty"`
328329
VerifyTLS *bool `json:"verifyTLS,omitempty"`
330+
ContainerOptions *BackupContainerOptions `json:"containerOptions,omitempty"`
331+
}
332+
333+
type BackupContainerOptions struct {
334+
// +optional
335+
Env []corev1.EnvVar `json:"env,omitempty"`
336+
// +optional
337+
Args BackupContainerArgs `json:"args"`
338+
}
339+
340+
func (b *BackupContainerOptions) GetEnv() []corev1.EnvVar {
341+
if b == nil {
342+
return nil
343+
}
344+
return util.MergeEnvLists(b.Env, b.Args.Env())
345+
}
346+
347+
func (b *BackupContainerOptions) GetEnvVar(storage *BackupStorageSpec) []corev1.EnvVar {
348+
if b != nil {
349+
return b.GetEnv()
350+
}
351+
352+
if storage == nil || storage.ContainerOptions == nil {
353+
return nil
354+
}
355+
356+
return storage.ContainerOptions.GetEnv()
357+
}
358+
359+
type BackupContainerArgs struct {
360+
Xtrabackup []string `json:"xtrabackup,omitempty"`
361+
Xbcloud []string `json:"xbcloud,omitempty"`
362+
Xbstream []string `json:"xbstream,omitempty"`
363+
}
364+
365+
func (b *BackupContainerArgs) Env() []corev1.EnvVar {
366+
envs := []corev1.EnvVar{}
367+
if len(b.Xtrabackup) > 0 {
368+
envs = append(envs, corev1.EnvVar{
369+
Name: "XB_EXTRA_ARGS",
370+
Value: strings.Join(b.Xtrabackup, " "),
371+
})
372+
}
373+
if len(b.Xbcloud) > 0 {
374+
envs = append(envs, corev1.EnvVar{
375+
Name: "XBCLOUD_EXTRA_ARGS",
376+
Value: strings.Join(b.Xbcloud, " "),
377+
})
378+
}
379+
if len(b.Xbstream) > 0 {
380+
envs = append(envs, corev1.EnvVar{
381+
Name: "XBSTREAM_EXTRA_ARGS",
382+
Value: strings.Join(b.Xbstream, " "),
383+
})
384+
}
385+
return envs
329386
}
330387

331388
type BackupStorageS3Spec struct {

api/v1alpha1/perconaservermysqlbackup_types.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@ import (
2727

2828
// PerconaServerMySQLBackupSpec defines the desired state of PerconaServerMySQLBackup
2929
type PerconaServerMySQLBackupSpec struct {
30-
ClusterName string `json:"clusterName"`
31-
StorageName string `json:"storageName"`
30+
ClusterName string `json:"clusterName"`
31+
StorageName string `json:"storageName"`
32+
ContainerOptions *BackupContainerOptions `json:"containerOptions,omitempty"`
3233
}
3334

3435
type BackupState string

api/v1alpha1/perconaservermysqlrestore_types.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ import (
2727

2828
// PerconaServerMySQLRestoreSpec defines the desired state of PerconaServerMySQLRestore
2929
type PerconaServerMySQLRestoreSpec struct {
30-
ClusterName string `json:"clusterName"`
31-
BackupName string `json:"backupName,omitempty"`
32-
BackupSource *PerconaServerMySQLBackupStatus `json:"backupSource,omitempty"`
30+
ClusterName string `json:"clusterName"`
31+
BackupName string `json:"backupName,omitempty"`
32+
BackupSource *PerconaServerMySQLBackupStatus `json:"backupSource,omitempty"`
33+
ContainerOptions *BackupContainerOptions `json:"containerOptions,omitempty"`
3334
}
3435

3536
type RestoreState string

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 69 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build/run-backup.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ request_data() {
1111
{
1212
"destination": "$(json_escape "${BACKUP_DEST}")",
1313
"type": "$(json_escape "${STORAGE_TYPE}")",
14+
"containerOptions": ${CONTAINER_OPTIONS},
1415
"verifyTLS": $(json_escape "${VERIFY_TLS}"),
1516
"s3": {
1617
"bucket": "$(json_escape "${S3_BUCKET}")",
@@ -29,6 +30,7 @@ request_data() {
2930
"destination": "$(json_escape "${BACKUP_DEST}")",
3031
"verifyTLS": $(json_escape "${VERIFY_TLS}"),
3132
"type": "$(json_escape "${STORAGE_TYPE}")",
33+
"containerOptions": ${CONTAINER_OPTIONS},
3234
"gcs": {
3335
"bucket": "$(json_escape "${GCS_BUCKET}")",
3436
"endpointUrl": "$(json_escape "${GCS_ENDPOINT}")",
@@ -45,6 +47,7 @@ request_data() {
4547
"destination": "$(json_escape "${BACKUP_DEST}")",
4648
"verifyTLS": $(json_escape "${VERIFY_TLS}"),
4749
"type": "$(json_escape "${STORAGE_TYPE}")",
50+
"containerOptions": ${CONTAINER_OPTIONS},
4851
"azure": {
4952
"containerName": "$(json_escape "${AZURE_CONTAINER_NAME}")",
5053
"storageAccount": "$(json_escape "${AZURE_STORAGE_ACCOUNT}")",

build/run-restore.sh

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,28 @@ set -o xtrace
55

66
DATADIR=${DATADIR:-/var/lib/mysql}
77
PARALLEL=$(grep -c processor /proc/cpuinfo)
8-
XBCLOUD_ARGS="--curl-retriable-errors=7 --parallel=${PARALLEL}"
8+
XBCLOUD_ARGS="--curl-retriable-errors=7 --parallel=${PARALLEL} ${XBCLOUD_EXTRA_ARGS}"
99
if [ -n "$VERIFY_TLS" ] && [[ $VERIFY_TLS == "false" ]]; then
1010
XBCLOUD_ARGS="${XBCLOUD_ARGS} --insecure"
1111
fi
1212

1313
run_s3() {
14-
xbcloud get "${XBCLOUD_ARGS}" "${BACKUP_DEST}" --storage=s3 --s3-bucket="${S3_BUCKET}"
14+
xbcloud get ${XBCLOUD_ARGS} "${BACKUP_DEST}" --storage=s3 --s3-bucket="${S3_BUCKET}"
1515
}
1616

1717
run_gcs() {
18-
xbcloud get "${XBCLOUD_ARGS}" "${BACKUP_DEST}" --storage=google --google-bucket="${GCS_BUCKET}"
18+
xbcloud get ${XBCLOUD_ARGS} "${BACKUP_DEST}" --storage=google --google-bucket="${GCS_BUCKET}"
1919
}
2020

2121
run_azure() {
22-
xbcloud get "${XBCLOUD_ARGS}" "${BACKUP_DEST}" --storage=azure
22+
xbcloud get ${XBCLOUD_ARGS} "${BACKUP_DEST}" --storage=azure
2323
}
2424

2525
extract() {
2626
local targetdir=$1
2727

28-
xbstream -xv -C "${targetdir}" --parallel="${PARALLEL}"
28+
# shellcheck disable=SC2086
29+
xbstream -xv -C "${targetdir}" --parallel="${PARALLEL}" ${XBSTREAM_EXTRA_ARGS}
2930
}
3031

3132
main() {
@@ -47,8 +48,10 @@ main() {
4748
keyring="--keyring-vault-config=${KEYRING_VAULT_PATH}"
4849
fi
4950

50-
xtrabackup --prepare --rollback-prepared-trx --target-dir="${tmpdir}" ${keyring}
51-
xtrabackup --datadir="${DATADIR}" --move-back --force-non-empty-directories --target-dir="${tmpdir}"
51+
# shellcheck disable=SC2086
52+
xtrabackup --prepare --rollback-prepared-trx --target-dir="${tmpdir}" ${XB_EXTRA_ARGS} ${keyring}
53+
# shellcheck disable=SC2086
54+
xtrabackup --datadir="${DATADIR}" --move-back --force-non-empty-directories --target-dir="${tmpdir}" ${XB_EXTRA_ARGS}
5255

5356
rm -rf "${tmpdir}"
5457

cmd/sidecar/main.go

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,11 @@ import (
1919
"syscall"
2020
"time"
2121

22+
"github.com/pkg/errors"
2223
"golang.org/x/sync/errgroup"
2324
logf "sigs.k8s.io/controller-runtime/pkg/log"
2425
"sigs.k8s.io/controller-runtime/pkg/log/zap"
2526

26-
"github.com/pkg/errors"
27-
2827
apiv1alpha1 "github.com/percona/percona-server-mysql-operator/api/v1alpha1"
2928
"github.com/percona/percona-server-mysql-operator/pkg/mysql"
3029
xb "github.com/percona/percona-server-mysql-operator/pkg/xtrabackup"
@@ -148,8 +147,8 @@ func getNamespace() (string, error) {
148147
return string(ns), nil
149148
}
150149

151-
func xtrabackupArgs(user, pass string) []string {
152-
return []string{
150+
func xtrabackupArgs(user, pass string, conf *xb.BackupConfig) []string {
151+
args := []string{
153152
"--backup",
154153
"--stream=xbstream",
155154
"--safe-slave-backup",
@@ -158,6 +157,10 @@ func xtrabackupArgs(user, pass string) []string {
158157
fmt.Sprintf("--user=%s", user),
159158
fmt.Sprintf("--password=%s", pass),
160159
}
160+
if conf != nil && conf.ContainerOptions != nil {
161+
args = append(args, conf.ContainerOptions.Args.Xtrabackup...)
162+
}
163+
return args
161164
}
162165

163166
func backupHandler(w http.ResponseWriter, req *http.Request) {
@@ -247,6 +250,7 @@ func deleteBackup(ctx context.Context, cfg *xb.BackupConfig, backupName string)
247250
logWriter = io.MultiWriter(backupLog, os.Stderr)
248251
}
249252
xbcloud := exec.CommandContext(ctx, "xbcloud", xb.XBCloudArgs(xb.XBCloudActionDelete, cfg)...)
253+
xbcloud.Env = envs(*cfg)
250254
xbcloudErr, err := xbcloud.StderrPipe()
251255
if err != nil {
252256
return errors.Wrap(err, "xbcloud stderr pipe failed")
@@ -393,7 +397,8 @@ func createBackupHandler(w http.ResponseWriter, req *http.Request) {
393397
}
394398
g, gCtx := errgroup.WithContext(req.Context())
395399

396-
xtrabackup := exec.CommandContext(gCtx, "xtrabackup", xtrabackupArgs(string(backupUser), backupPass)...)
400+
xtrabackup := exec.CommandContext(gCtx, "xtrabackup", xtrabackupArgs(string(backupUser), backupPass, &backupConf)...)
401+
xtrabackup.Env = envs(backupConf)
397402

398403
xbOut, err := xtrabackup.StdoutPipe()
399404
if err != nil {
@@ -421,6 +426,7 @@ func createBackupHandler(w http.ResponseWriter, req *http.Request) {
421426
logWriter := io.MultiWriter(backupLog, os.Stderr)
422427

423428
xbcloud := exec.CommandContext(gCtx, "xbcloud", xb.XBCloudArgs(xb.XBCloudActionPut, &backupConf)...)
429+
xbcloud.Env = envs(backupConf)
424430
xbcloud.Stdin = xbOut
425431

426432
xbcloudErr, err := xbcloud.StderrPipe()
@@ -514,3 +520,13 @@ func logHandler(w http.ResponseWriter, req *http.Request) {
514520
return
515521
}
516522
}
523+
524+
func envs(cfg xb.BackupConfig) []string {
525+
envs := os.Environ()
526+
if cfg.ContainerOptions != nil {
527+
for _, env := range cfg.ContainerOptions.Env {
528+
envs = append(envs, fmt.Sprintf("%s=%s", env.Name, env.Value))
529+
}
530+
}
531+
return envs
532+
}

0 commit comments

Comments
 (0)