diff --git a/README.md b/README.md index 1764fdc..2b9a8b5 100644 --- a/README.md +++ b/README.md @@ -55,15 +55,14 @@ Usage: cain backup [flags] Flags: - -b, --buffer-size float in memory buffer size (MB) to use for files copy (buffer per file) (default 6.75) + -b, --buffer-size float in memory buffer size (MB) to use for files copy (buffer per file). Overrides $CAIN_BUFFER_SIZE (default 6.75) --cassandra-data-dir string cassandra data directory. Overrides $CAIN_CASSANDRA_DATA_DIR (default "/var/lib/cassandra/data") - -c, --container string container name to act on (default "cassandra") - --dst string destination to backup to. Example: s3://bucket/cassandra - -h, --help help for backup - -k, --keyspace string keyspace to act on - -n, --namespace string namespace to find cassandra cluster - -p, --parallel int number of files to copy in parallel. set this flag to 0 for full parallelism (default 1) - -l, --selector string selector to filter on + -c, --container string container name to act on. Overrides $CAIN_CONTAINER (default "cassandra") + --dst string destination to backup to. Example: s3://bucket/cassandra. Overrides $CAIN_DST + -k, --keyspace string keyspace to act on. Overrides $CAIN_KEYSPACE + -n, --namespace string namespace to find cassandra cluster. Overrides $CAIN_NAMESPACE (default "default") + -p, --parallel int number of files to copy in parallel. set this flag to 0 for full parallelism. Overrides $CAIN_PARALLEL (default 1) + -l, --selector string selector to filter on. Overrides $CAIN_SELECTOR (default "app=cassandra") ``` #### Examples @@ -106,18 +105,17 @@ Usage: cain restore [flags] Flags: - -b, --buffer-size float in memory buffer size (MB) to use for files copy (buffer per file) (default 6.75) + -b, --buffer-size float in memory buffer size (MB) to use for files copy (buffer per file). Overrides $CAIN_BUFFER_SIZE (default 6.75) --cassandra-data-dir string cassandra data directory. Overrides $CAIN_CASSANDRA_DATA_DIR (default "/var/lib/cassandra/data") - -c, --container string container name to act on (default "cassandra") - -h, --help help for restore - -k, --keyspace string keyspace to act on - -n, --namespace string namespace to find cassandra cluster - -p, --parallel int number of files to copy in parallel. set this flag to 0 for full parallelism (default 1) - -s, --schema string schema version to restore (optional) - -l, --selector string selector to filter on - --src string source to restore from. Example: s3://bucket/cassandra/namespace/cluster-name - -t, --tag string tag to restore - --user-group string user and group who should own restored files (default "cassandra:cassandra") + -c, --container string container name to act on. Overrides $CAIN_CONTAINER (default "cassandra") + -k, --keyspace string keyspace to act on. Overrides $CAIN_KEYSPACE + -n, --namespace string namespace to find cassandra cluster. Overrides $CAIN_NAMESPACE (default "default") + -p, --parallel int number of files to copy in parallel. set this flag to 0 for full parallelism. Overrides $CAIN_PARALLEL (default 1) + -s, --schema string schema version to restore (optional). Overrides $CAIN_SCHEMA + -l, --selector string selector to filter on. Overrides $CAIN_SELECTOR (default "app=cassandra") + --src string source to restore from. Example: s3://bucket/cassandra/namespace/cluster-name. Overrides $CAIN_SRC + -t, --tag string tag to restore. Overrides $CAIN_TAG + --user-group string user and group who should own restored files. Overrides $CAIN_USER_GROUP (default "cassandra:cassandra") ``` #### Examples @@ -158,12 +156,11 @@ Usage: cain schema [flags] Flags: - -c, --container string container name to act on (default "cassandra") - -h, --help help for schema - -k, --keyspace string keyspace to act on - -n, --namespace string namespace to find cassandra cluster - -l, --selector string selector to filter on - --sum print only checksum + -c, --container string container name to act on. Overrides $CAIN_CONTAINER (default "cassandra") + -k, --keyspace string keyspace to act on. Overrides $CAIN_KEYSPACE + -n, --namespace string namespace to find cassandra cluster. Overrides $CAIN_NAMESPACE (default "default") + -l, --selector string selector to filter on. Overrides $CAIN_SELECTOR (default "app=cassandra") + --sum print only checksum. Overrides $CAIN_SUM ``` #### Examples @@ -182,6 +179,30 @@ cain schema \ --sum ``` +## Environment variables support + +Cain commands support the usage of environment variables instead of flags. For example: +The `backup` command can be executed as mentioned in the example: + +``` +cain backup \ + -n default \ + -l release=cassandra \ + -k keyspace \ + --dst s3://db-backup/cassandra +``` + +You can also set the appropriate envrionment variables (CAIN_FLAG, _ instead of -): + +``` +export CAIN_NAMESPACE=default +export CAIN_SELECTOR=release=cassandra +export CAIN_KEYSPACE=keyspace +export CAIN_DST=s3://db-backup/cassandra + +cain backup +``` + ## Support for additional storage services Since Cain uses [Skbn](https://github.com/nuvo/skbn), adding support for additional storage services is simple. Read [this post](https://medium.com/nuvo-group-tech/copy-files-and-directories-between-kubernetes-and-s3-d290ded9a5e0) for more information. diff --git a/cmd/cain.go b/cmd/cain.go index 6379f17..6fb56e0 100644 --- a/cmd/cain.go +++ b/cmd/cain.go @@ -89,14 +89,14 @@ func NewBackupCmd(out io.Writer) *cobra.Command { } f := cmd.Flags() - f.StringVarP(&b.namespace, "namespace", "n", "", "namespace to find cassandra cluster") - f.StringVarP(&b.selector, "selector", "l", "", "selector to filter on") - f.StringVarP(&b.container, "container", "c", "cassandra", "container name to act on") - f.StringVarP(&b.keyspace, "keyspace", "k", "", "keyspace to act on") - f.StringVar(&b.dst, "dst", "", "destination to backup to. Example: s3://bucket/cassandra") - f.IntVarP(&b.parallel, "parallel", "p", 1, "number of files to copy in parallel. set this flag to 0 for full parallelism") - f.Float64VarP(&b.bufferSize, "buffer-size", "b", 6.75, "in memory buffer size (MB) to use for files copy (buffer per file)") - f.StringVarP(&b.cassandraDataDir, "cassandra-data-dir", "", utils.GetStringEnvVar("CAIN_CASSANDRA_DATA_DIR", "/var/lib/cassandra/data"), "cassandra data directory. Overrides $CAIN_CASSANDRA_DATA_DIR") + f.StringVarP(&b.namespace, "namespace", "n", utils.GetStringEnvVar("CAIN_NAMESPACE", "default"), "namespace to find cassandra cluster. Overrides $CAIN_NAMESPACE") + f.StringVarP(&b.selector, "selector", "l", utils.GetStringEnvVar("CAIN_SELECTOR", "app=cassandra"), "selector to filter on. Overrides $CAIN_SELECTOR") + f.StringVarP(&b.container, "container", "c", utils.GetStringEnvVar("CAIN_CONTAINER", "cassandra"), "container name to act on. Overrides $CAIN_CONTAINER") + f.StringVarP(&b.keyspace, "keyspace", "k", utils.GetStringEnvVar("CAIN_KEYSPACE", ""), "keyspace to act on. Overrides $CAIN_KEYSPACE") + f.StringVar(&b.dst, "dst", utils.GetStringEnvVar("CAIN_DST", ""), "destination to backup to. Example: s3://bucket/cassandra. Overrides $CAIN_DST") + f.IntVarP(&b.parallel, "parallel", "p", utils.GetIntEnvVar("CAIN_PARALLEL", 1), "number of files to copy in parallel. set this flag to 0 for full parallelism. Overrides $CAIN_PARALLEL") + f.Float64VarP(&b.bufferSize, "buffer-size", "b", utils.GetFloat64EnvVar("CAIN_BUFFER_SIZE", 6.75), "in memory buffer size (MB) to use for files copy (buffer per file). Overrides $CAIN_BUFFER_SIZE") + f.StringVar(&b.cassandraDataDir, "cassandra-data-dir", utils.GetStringEnvVar("CAIN_CASSANDRA_DATA_DIR", "/var/lib/cassandra/data"), "cassandra data directory. Overrides $CAIN_CASSANDRA_DATA_DIR") return cmd } @@ -161,17 +161,17 @@ func NewRestoreCmd(out io.Writer) *cobra.Command { } f := cmd.Flags() - f.StringVar(&r.src, "src", "", "source to restore from. Example: s3://bucket/cassandra/namespace/cluster-name") - f.StringVarP(&r.keyspace, "keyspace", "k", "", "keyspace to act on") - f.StringVarP(&r.tag, "tag", "t", "", "tag to restore") - f.StringVarP(&r.schema, "schema", "s", "", "schema version to restore (optional)") - f.StringVarP(&r.namespace, "namespace", "n", "", "namespace to find cassandra cluster") - f.StringVarP(&r.selector, "selector", "l", "", "selector to filter on") - f.StringVarP(&r.container, "container", "c", "cassandra", "container name to act on") - f.IntVarP(&r.parallel, "parallel", "p", 1, "number of files to copy in parallel. set this flag to 0 for full parallelism") - f.Float64VarP(&r.bufferSize, "buffer-size", "b", 6.75, "in memory buffer size (MB) to use for files copy (buffer per file)") - f.StringVar(&r.userGroup, "user-group", "cassandra:cassandra", "user and group who should own restored files") - f.StringVarP(&r.cassandraDataDir, "cassandra-data-dir", "", utils.GetStringEnvVar("CAIN_CASSANDRA_DATA_DIR", "/var/lib/cassandra/data"), "cassandra data directory. Overrides $CAIN_CASSANDRA_DATA_DIR") + f.StringVar(&r.src, "src", utils.GetStringEnvVar("CAIN_SRC", ""), "source to restore from. Example: s3://bucket/cassandra/namespace/cluster-name. Overrides $CAIN_SRC") + f.StringVarP(&r.keyspace, "keyspace", "k", utils.GetStringEnvVar("CAIN_KEYSPACE", ""), "keyspace to act on. Overrides $CAIN_KEYSPACE") + f.StringVarP(&r.tag, "tag", "t", utils.GetStringEnvVar("CAIN_TAG", ""), "tag to restore. Overrides $CAIN_TAG") + f.StringVarP(&r.schema, "schema", "s", utils.GetStringEnvVar("CAIN_SCHEMA", ""), "schema version to restore (optional). Overrides $CAIN_SCHEMA") + f.StringVarP(&r.namespace, "namespace", "n", utils.GetStringEnvVar("CAIN_NAMESPACE", "default"), "namespace to find cassandra cluster. Overrides $CAIN_NAMESPACE") + f.StringVarP(&r.selector, "selector", "l", utils.GetStringEnvVar("CAIN_SELECTOR", "app=cassandra"), "selector to filter on. Overrides $CAIN_SELECTOR") + f.StringVarP(&r.container, "container", "c", utils.GetStringEnvVar("CAIN_CONTAINER", "cassandra"), "container name to act on. Overrides $CAIN_CONTAINER") + f.IntVarP(&r.parallel, "parallel", "p", utils.GetIntEnvVar("CAIN_PARALLEL", 1), "number of files to copy in parallel. set this flag to 0 for full parallelism. Overrides $CAIN_PARALLEL") + f.Float64VarP(&r.bufferSize, "buffer-size", "b", utils.GetFloat64EnvVar("CAIN_BUFFER_SIZE", 6.75), "in memory buffer size (MB) to use for files copy (buffer per file). Overrides $CAIN_BUFFER_SIZE") + f.StringVar(&r.userGroup, "user-group", utils.GetStringEnvVar("CAIN_USER_GROUP", "cassandra:cassandra"), "user and group who should own restored files. Overrides $CAIN_USER_GROUP") + f.StringVar(&r.cassandraDataDir, "cassandra-data-dir", utils.GetStringEnvVar("CAIN_CASSANDRA_DATA_DIR", "/var/lib/cassandra/data"), "cassandra data directory. Overrides $CAIN_CASSANDRA_DATA_DIR") return cmd } @@ -221,14 +221,11 @@ func NewSchemaCmd(out io.Writer) *cobra.Command { } f := cmd.Flags() - f.StringVarP(&s.namespace, "namespace", "n", "", "namespace to find cassandra cluster") - f.StringVarP(&s.selector, "selector", "l", "", "selector to filter on") - f.StringVarP(&s.container, "container", "c", "cassandra", "container name to act on") - f.StringVarP(&s.keyspace, "keyspace", "k", "", "keyspace to act on") - f.BoolVar(&s.sum, "sum", false, "print only checksum") - - cmd.MarkFlagRequired("namespace") - cmd.MarkFlagRequired("selector") + f.StringVarP(&s.namespace, "namespace", "n", utils.GetStringEnvVar("CAIN_NAMESPACE", "default"), "namespace to find cassandra cluster. Overrides $CAIN_NAMESPACE") + f.StringVarP(&s.selector, "selector", "l", utils.GetStringEnvVar("CAIN_SELECTOR", "app=cassandra"), "selector to filter on. Overrides $CAIN_SELECTOR") + f.StringVarP(&s.container, "container", "c", utils.GetStringEnvVar("CAIN_CONTAINER", "cassandra"), "container name to act on. Overrides $CAIN_CONTAINER") + f.StringVarP(&s.keyspace, "keyspace", "k", utils.GetStringEnvVar("CAIN_KEYSPACE", ""), "keyspace to act on. Overrides $CAIN_KEYSPACE") + f.BoolVar(&s.sum, "sum", utils.GetBoolEnvVar("CAIN_SUM", false), "print only checksum. Overrides $CAIN_SUM") return cmd } diff --git a/pkg/utils/env.go b/pkg/utils/env.go index 3fadd02..ec74b02 100644 --- a/pkg/utils/env.go +++ b/pkg/utils/env.go @@ -39,3 +39,16 @@ func GetBoolEnvVar(name string, defVal bool) bool { } return defVal } + +// GetFloat64EnvVar returns the default value if the variable is empty, else the value +func GetFloat64EnvVar(name string, defVal float64) float64 { + val := os.Getenv(name) + if val == "" { + return defVal + } + iVal, err := strconv.ParseFloat(val, 64) + if err != nil { + return defVal + } + return iVal +}