1package cli
2
3import (
4 "bytes"
5 "context"
6 "errors"
7 "testing"
8
9 "github.com/stretchr/testify/mock"
10 "github.com/stretchr/testify/require"
11
12 "github.com/bnema/gordon/internal/adapters/dto"
13 climocks "github.com/bnema/gordon/internal/adapters/in/cli/mocks"
14)
15
16func withBackupControlPlane(t *testing.T, plane ControlPlane) {
17 t.Helper()
18 old := backupResolveControlPlane
19 backupResolveControlPlane = func(context.Context, string, string) (*controlPlaneHandle, error) {
20 return &controlPlaneHandle{plane: plane}, nil
21 }
22 t.Cleanup(func() { backupResolveControlPlane = old })
23}
24
25func TestVolumeBackupRun_UsesDomainAwareResolver(t *testing.T) {
26 plane := climocks.NewMockControlPlane(t)
27 old := backupResolveControlPlane
28 var gotDomain string
29 backupResolveControlPlane = func(_ context.Context, _ string, domainName string) (*controlPlaneHandle, error) {
30 gotDomain = domainName
31 return &controlPlaneHandle{plane: plane}, nil
32 }
33 t.Cleanup(func() { backupResolveControlPlane = old })
34
35 plane.EXPECT().RunVolumeBackups(mock.Anything, "app.example.com", "").Return(&dto.VolumeBackupRunResponse{Status: "ok"}, nil)
36
37 cmd := newVolumeBackupRunCmd()
38 cmd.SetArgs([]string{"app.example.com"})
39
40 require.NoError(t, cmd.ExecuteContext(context.Background()))
41 require.Equal(t, "app.example.com", gotDomain)
42}
43
44func TestVolumeBackupRun_JSONFlag(t *testing.T) {
45 plane := climocks.NewMockControlPlane(t)
46 withBackupControlPlane(t, plane)
47
48 plane.EXPECT().RunVolumeBackups(mock.Anything, "app.example.com", "gordon-app-data").Return(&dto.VolumeBackupRunResponse{
49 Status: "ok",
50 Backups: []dto.VolumeBackupJob{{Domain: "app.example.com", VolumeName: "gordon-app-data", Status: "completed"}},
51 }, nil)
52
53 cmd := newVolumeBackupRunCmd()
54 var out bytes.Buffer
55 cmd.SetOut(&out)
56 cmd.SetArgs([]string{"app.example.com", "--volume", "gordon-app-data", "--json"})
57
58 require.NoError(t, cmd.ExecuteContext(context.Background()))
59 require.JSONEq(t, `[{"id":"","domain":"app.example.com","volume_name":"gordon-app-data","type":"","status":"completed","size_bytes":0}]`, out.String())
60}
61
62func TestVolumeBackupStatus_JSONFlag(t *testing.T) {
63 plane := climocks.NewMockControlPlane(t)
64 withBackupControlPlane(t, plane)
65
66 plane.EXPECT().VolumeBackupStatus(mock.Anything).Return([]dto.VolumeBackupJob{{Domain: "app.example.com", VolumeName: "gordon-app-data", Status: "running"}}, nil)
67
68 cmd := newVolumeBackupStatusCmd()
69 var out bytes.Buffer
70 cmd.SetOut(&out)
71 cmd.SetArgs([]string{"--json"})
72
73 require.NoError(t, cmd.ExecuteContext(context.Background()))
74 require.JSONEq(t, `[{"id":"","domain":"app.example.com","volume_name":"gordon-app-data","type":"","status":"running","size_bytes":0}]`, out.String())
75}
76
77func TestVolumeBackupRun_PrintsPartialJobsBeforeReturningError(t *testing.T) {
78 plane := climocks.NewMockControlPlane(t)
79 withBackupControlPlane(t, plane)
80
81 runErr := errors.New("one backup failed")
82 plane.EXPECT().RunVolumeBackups(mock.Anything, "app.example.com", "").Return(&dto.VolumeBackupRunResponse{
83 Status: "partial",
84 Backups: []dto.VolumeBackupJob{{Domain: "app.example.com", VolumeName: "gordon-app-data", Status: "completed"}},
85 Error: runErr.Error(),
86 }, runErr)
87
88 cmd := newVolumeBackupRunCmd()
89 cmd.SilenceUsage = true
90 var out bytes.Buffer
91 cmd.SetOut(&out)
92 cmd.SetArgs([]string{"app.example.com", "--json"})
93
94 err := cmd.ExecuteContext(context.Background())
95 require.Error(t, err)
96 require.ErrorIs(t, err, runErr)
97 require.JSONEq(t, `[{"id":"","domain":"app.example.com","volume_name":"gordon-app-data","type":"","status":"completed","size_bytes":0}]`, out.String())
98}