forked from wal-g/wal-g
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' of https://github.com/wal-g/wal-g into feature-…
…upload-time
- Loading branch information
Showing
21 changed files
with
1,295 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
package st | ||
|
||
import ( | ||
"fmt" | ||
"math" | ||
"time" | ||
|
||
"github.com/spf13/cobra" | ||
"github.com/wal-g/tracelog" | ||
"github.com/wal-g/wal-g/internal/storagetools" | ||
) | ||
|
||
const transferShortDescription = "Moves objects from one storage to another (Postgres only)" | ||
|
||
// transferCmd represents the transfer command | ||
var transferCmd = &cobra.Command{ | ||
Use: "transfer prefix --source='source_storage' [--target='target_storage']", | ||
Short: transferShortDescription, | ||
Long: "The command is usually used to move objects from a failover storage to the primary one, when it becomes alive. " + | ||
"By default, objects that exist in both storages are neither overwritten in the target storage nor deleted from the source one.", | ||
Args: cobra.ExactArgs(1), | ||
Run: func(cmd *cobra.Command, args []string) { | ||
err := validateFlags() | ||
if err != nil { | ||
tracelog.ErrorLogger.FatalError(fmt.Errorf("invalid flags: %w", err)) | ||
} | ||
|
||
cfg := &storagetools.TransferHandlerConfig{ | ||
Prefix: args[0], | ||
Overwrite: transferOverwrite, | ||
FailOnFirstErr: transferFailFast, | ||
Concurrency: transferConcurrency, | ||
MaxFiles: adjustMaxFiles(transferMax), | ||
AppearanceChecks: transferAppearanceChecks, | ||
AppearanceChecksInterval: transferAppearanceChecksInterval, | ||
} | ||
|
||
handler, err := storagetools.NewTransferHandler(transferSourceStorage, targetStorage, cfg) | ||
if err != nil { | ||
tracelog.ErrorLogger.FatalError(err) | ||
} | ||
|
||
err = handler.Handle() | ||
if err != nil { | ||
tracelog.ErrorLogger.FatalError(err) | ||
} | ||
}, | ||
} | ||
|
||
var ( | ||
transferSourceStorage string | ||
transferOverwrite bool | ||
transferFailFast bool | ||
transferConcurrency int | ||
transferMax int | ||
transferAppearanceChecks uint | ||
transferAppearanceChecksInterval time.Duration | ||
) | ||
|
||
func init() { | ||
transferCmd.Flags().StringVarP(&transferSourceStorage, "source", "s", "", | ||
"storage name to move files from. Use 'default' to select the primary storage") | ||
transferCmd.Flags().BoolVarP(&transferOverwrite, "overwrite", "o", false, | ||
"whether to overwrite already existing files in the target storage and remove them from the source one") | ||
transferCmd.Flags().BoolVar(&transferFailFast, "fail-fast", false, | ||
"if this flag is set, any error occurred with transferring a separate file will lead the whole command to stop immediately") | ||
transferCmd.Flags().IntVarP(&transferConcurrency, "concurrency", "c", 10, | ||
"number of concurrent workers to move files. Value 1 turns concurrency off") | ||
transferCmd.Flags().IntVarP(&transferMax, "max", "m", -1, | ||
"max number of files to move in this run. Negative numbers turn the limit off") | ||
transferCmd.Flags().UintVar(&transferAppearanceChecks, "appearance-checks", 3, | ||
"number of times to check if a file is appeared for reading in the target storage after writing it. Value 0 turns checking off") | ||
transferCmd.Flags().DurationVar(&transferAppearanceChecksInterval, "appearance-checks-interval", time.Second, | ||
"minimum time interval between performing checks for files to appear in the target storage") | ||
|
||
StorageToolsCmd.AddCommand(transferCmd) | ||
} | ||
|
||
func validateFlags() error { | ||
if transferSourceStorage == "" { | ||
return fmt.Errorf("source storage must be specified") | ||
} | ||
if transferSourceStorage == "all" { | ||
return fmt.Errorf("an explicit source storage must be specified instead of 'all'") | ||
} | ||
if targetStorage == "all" { | ||
return fmt.Errorf("an explicit target storage must be specified instead of 'all'") | ||
} | ||
if transferSourceStorage == targetStorage { | ||
return fmt.Errorf("source and target storages must be different") | ||
} | ||
if transferConcurrency < 1 { | ||
return fmt.Errorf("concurrency level must be >= 1 (which turns it off)") | ||
} | ||
return nil | ||
} | ||
|
||
func adjustMaxFiles(max int) int { | ||
if max < 0 { | ||
return math.MaxInt | ||
} | ||
return max | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package st | ||
|
||
import ( | ||
"math" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func Test_validateFlags(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
source, target string | ||
concurrency int | ||
wantErr bool | ||
}{ | ||
{"source empty", "", "abc", 1, true}, | ||
{"source all", "all", "abc", 1, true}, | ||
{"target all", "abc", "all", 1, true}, | ||
{"same storages", "abc", "abc", 1, true}, | ||
{"concurrency < 1", "source", "target", 0, true}, | ||
{"valid", "source", "target", 1, false}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
transferSourceStorage = tt.source | ||
targetStorage = tt.target | ||
transferConcurrency = tt.concurrency | ||
if err := validateFlags(); (err != nil) != tt.wantErr { | ||
t.Errorf("validateFlags() error = %v, wantErr %v", err, tt.wantErr) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func Test_adjustMaxFiles(t *testing.T) { | ||
assert.Equal(t, math.MaxInt, adjustMaxFiles(-1)) | ||
assert.Equal(t, 0, adjustMaxFiles(0)) | ||
assert.Equal(t, 123, adjustMaxFiles(123)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"WALE_S3_PREFIX": "s3://sttransferbucket", | ||
"WALG_FAILOVER_STORAGES": { | ||
"failover": { | ||
"WALE_S3_PREFIX": "s3://sttransferfailoverbucket", | ||
"AWS_ACCESS_KEY_ID": "AKIAIOSFODNN7EXAMPLE", | ||
"AWS_SECRET_ACCESS_KEY": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" | ||
} | ||
}, | ||
"WALG_FAILOVER_STORAGES_CHECK_TIMEOUT": "5s" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#!/bin/bash | ||
set -e -x | ||
|
||
pushd /tmp | ||
for i in tests/*.sh; do | ||
echo | ||
echo "===== RUNNING $i =====" | ||
set -x | ||
|
||
./"$i"; | ||
|
||
set +x | ||
echo "===== SUCCESS $i =====" | ||
echo | ||
done | ||
popd |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
#!/bin/bash | ||
set -e -x | ||
|
||
CONFIG="/tmp/configs/transfer_test_config.json" | ||
TESTDATA="transfer" | ||
|
||
echo "Upload 50 random files to the failover storage" | ||
mkdir transfer | ||
for i in {1..50} | ||
do | ||
head -c 1M </dev/urandom >"$TESTDATA/$i" | ||
wal-g --config=$CONFIG st put "$TESTDATA/$i" "a/b/$i" --target=failover | ||
done | ||
|
||
echo "Upload some garbage files to the failover storage, which aren't to be transferred" | ||
garbage=( "1" "a" "aa/3" "b/4" ) | ||
for file in "${garbage[@]}" | ||
do | ||
mkdir -p "$(dirname "$TESTDATA/garbage/$file")" | ||
head -c 1M </dev/urandom >"$TESTDATA/garbage/$file" | ||
wal-g --config=$CONFIG st put "$TESTDATA/garbage/$file" "$file" --target=failover | ||
done | ||
|
||
echo "Ensure there's no files in the primary storage initially" | ||
test "1" -eq "$(wal-g --config=$CONFIG st ls -r "a/" | wc -l)" | ||
|
||
echo "Also upload only some of the target files to the primary storage" | ||
for i in 1 3 7 15 25 34 50 | ||
do | ||
head -c 1M </dev/urandom >"$TESTDATA/$i" | ||
wal-g --config=$CONFIG st put "$TESTDATA/$i" "a/b/$i" | ||
done | ||
|
||
echo "Call the command to transfer files from the failover storage to the primary one" | ||
wal-g --config=$CONFIG st transfer "a/" --source=failover --target=default | ||
|
||
echo "Check that all the target files are moved to the primary storage" | ||
wal-g --config=$CONFIG st ls -r "a/b/" | ||
test "51" -eq "$(wal-g --config=$CONFIG st ls -r "a/b/" | wc -l)" | ||
|
||
echo "Check that garbage files aren't moved to the primary storage" | ||
for file in "${garbage[@]}" | ||
do | ||
wal-g --config=$CONFIG st check read "$file.br" && EXIT_STATUS=$? || EXIT_STATUS=$? | ||
test "1" -eq $EXIT_STATUS | ||
done |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.