feat(cli): add transactional installation backups
This commit is contained in:
@@ -12,6 +12,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/aritmolab/thothii/tools/tht/internal/backup"
|
||||
"github.com/aritmolab/thothii/tools/tht/internal/compose"
|
||||
"github.com/aritmolab/thothii/tools/tht/internal/config"
|
||||
"github.com/aritmolab/thothii/tools/tht/internal/doctor"
|
||||
@@ -20,6 +21,80 @@ import (
|
||||
"github.com/aritmolab/thothii/tools/tht/internal/testsupport"
|
||||
)
|
||||
|
||||
func TestBackupCommandParsesSafeTransactionalOptions(t *testing.T) {
|
||||
request, err := parseBackupArgs([]string{"--output", "backup.zip", "--include-secrets", "--yes", "--drain"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if request.Output != "backup.zip" || !request.IncludeSecrets || !request.Confirm || !request.Drain {
|
||||
t.Fatalf("backup request = %#v", request)
|
||||
}
|
||||
|
||||
for _, args := range [][]string{
|
||||
{"--include-secrets"},
|
||||
{"--yes"},
|
||||
{"--output"},
|
||||
{"--drain", "--drain"},
|
||||
{"--unknown"},
|
||||
} {
|
||||
if _, err := parseBackupArgs(args); err == nil {
|
||||
t.Errorf("parseBackupArgs(%v) succeeded", args)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBackupCommandDispatchesWithoutDockerAndPrintsCustodyWarning(t *testing.T) {
|
||||
installation := config.Installation{Path: "/tmp/thothii-installation.yaml"}
|
||||
var received backup.CreateRequest
|
||||
executor := func(_ context.Context, got config.Installation, request backup.CreateRequest) (backup.Result, error) {
|
||||
if got.Path != installation.Path {
|
||||
t.Fatalf("installation = %#v", got)
|
||||
}
|
||||
received = request
|
||||
return backup.Result{Path: "/tmp/backup.zip", Warning: "archive contains external secret files; protect its custody"}, nil
|
||||
}
|
||||
var stdout, stderr bytes.Buffer
|
||||
code := backupCommandWith(context.Background(), installation, []string{"--include-secrets", "--yes"}, executor, &stdout, &stderr)
|
||||
if code != 0 {
|
||||
t.Fatalf("backup exit = %d, stderr = %s", code, stderr.String())
|
||||
}
|
||||
if !received.IncludeSecrets || !received.Confirm || !strings.Contains(stdout.String(), "/tmp/backup.zip") || !strings.Contains(stderr.String(), "protect its custody") {
|
||||
t.Fatalf("request=%#v stdout=%q stderr=%q", received, stdout.String(), stderr.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestBackupCommandMapsSafetyRefusalsToUsageExit(t *testing.T) {
|
||||
executor := func(context.Context, config.Installation, backup.CreateRequest) (backup.Result, error) {
|
||||
return backup.Result{}, backup.ErrActiveSessions
|
||||
}
|
||||
var stdout, stderr bytes.Buffer
|
||||
if code := backupCommandWith(context.Background(), config.Installation{}, nil, executor, &stdout, &stderr); code != 2 {
|
||||
t.Fatalf("backup safety refusal exit = %d, stderr = %q", code, stderr.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestPiMutationsUseTheSharedInstallationLifecycleLock(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
args []string
|
||||
want bool
|
||||
}{
|
||||
{args: []string{"status"}, want: false},
|
||||
{args: []string{"doctor"}, want: false},
|
||||
{args: []string{"test"}, want: false},
|
||||
{args: []string{"logs"}, want: false},
|
||||
{args: []string{"configure"}, want: true},
|
||||
{args: []string{"restart"}, want: true},
|
||||
{args: []string{"update"}, want: true},
|
||||
{args: []string{"rollback"}, want: true},
|
||||
{args: []string{"maintenance", "recover"}, want: true},
|
||||
{args: []string{"maintenance", "status"}, want: false},
|
||||
} {
|
||||
if got := piMutationRequiresLifecycleLock(test.args); got != test.want {
|
||||
t.Errorf("piMutationRequiresLifecycleLock(%v) = %v, want %v", test.args, got, test.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInstallationRunnerMapsProfileToSessionInventoryScope(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
profile string
|
||||
|
||||
Reference in New Issue
Block a user