v2.31.0-dev2 4b72742

attachments_push_test.go RawHistoryFolder

1package cli
2
3import (
4	"bytes"
5	"context"
6	"testing"
7
8	"github.com/bnema/gordon/internal/adapters/dto"
9	climocks "github.com/bnema/gordon/internal/adapters/in/cli/mocks"
10	"github.com/bnema/gordon/internal/adapters/in/cli/remote"
11	"github.com/bnema/gordon/internal/domain"
12	"github.com/stretchr/testify/assert"
13	"github.com/stretchr/testify/mock"
14	"github.com/stretchr/testify/require"
15)
16
17type attachmentPushTestControlPlane struct {
18	findAttachmentTargets func(context.Context, string) ([]string, error)
19	getStatus             func(context.Context) (*remote.Status, error)
20}
21
22var _ ControlPlane = (*attachmentPushTestControlPlane)(nil)
23
24func (c *attachmentPushTestControlPlane) ListRoutesWithDetails(context.Context) ([]remote.RouteInfo, error) {
25	panic("unexpected call")
26}
27
28func (c *attachmentPushTestControlPlane) GetHealth(context.Context) (map[string]*remote.RouteHealth, error) {
29	panic("unexpected call")
30}
31
32func (c *attachmentPushTestControlPlane) GetRoute(context.Context, string) (*domain.Route, error) {
33	panic("unexpected call")
34}
35
36func (c *attachmentPushTestControlPlane) FindRoutesByImage(context.Context, string) ([]domain.Route, error) {
37	panic("unexpected call")
38}
39
40func (c *attachmentPushTestControlPlane) AddRoute(context.Context, domain.Route) error {
41	panic("unexpected call")
42}
43
44func (c *attachmentPushTestControlPlane) UpdateRoute(context.Context, domain.Route) error {
45	panic("unexpected call")
46}
47
48func (c *attachmentPushTestControlPlane) RemoveRoute(context.Context, string) error {
49	panic("unexpected call")
50}
51
52func (c *attachmentPushTestControlPlane) Bootstrap(context.Context, dto.BootstrapRequest) (*dto.BootstrapResponse, error) {
53	panic("unexpected call")
54}
55
56func (c *attachmentPushTestControlPlane) ListSecretsWithAttachments(context.Context, string) (*remote.SecretsListResult, error) {
57	panic("unexpected call")
58}
59
60func (c *attachmentPushTestControlPlane) SetSecrets(context.Context, string, map[string]string) error {
61	panic("unexpected call")
62}
63
64func (c *attachmentPushTestControlPlane) DeleteSecret(context.Context, string, string) error {
65	panic("unexpected call")
66}
67
68func (c *attachmentPushTestControlPlane) SetAttachmentSecrets(context.Context, string, string, map[string]string) error {
69	panic("unexpected call")
70}
71
72func (c *attachmentPushTestControlPlane) DeleteAttachmentSecret(context.Context, string, string, string) error {
73	panic("unexpected call")
74}
75
76func (c *attachmentPushTestControlPlane) GetAllAttachmentsConfig(context.Context) (map[string][]string, error) {
77	panic("unexpected call")
78}
79
80func (c *attachmentPushTestControlPlane) GetAttachmentsConfig(context.Context, string) ([]string, error) {
81	panic("unexpected call")
82}
83
84func (c *attachmentPushTestControlPlane) FindAttachmentTargetsByImage(ctx context.Context, imageName string) ([]string, error) {
85	if c.findAttachmentTargets != nil {
86		return c.findAttachmentTargets(ctx, imageName)
87	}
88	return nil, nil
89}
90
91func (c *attachmentPushTestControlPlane) AddAttachment(context.Context, string, string) error {
92	panic("unexpected call")
93}
94
95func (c *attachmentPushTestControlPlane) RemoveAttachment(context.Context, string, string) error {
96	panic("unexpected call")
97}
98
99func (c *attachmentPushTestControlPlane) GetAutoRouteAllowedDomains(context.Context) ([]string, error) {
100	panic("unexpected call")
101}
102
103func (c *attachmentPushTestControlPlane) AddAutoRouteAllowedDomain(context.Context, string) error {
104	panic("unexpected call")
105}
106
107func (c *attachmentPushTestControlPlane) RemoveAutoRouteAllowedDomain(context.Context, string) error {
108	panic("unexpected call")
109}
110
111func (c *attachmentPushTestControlPlane) GetStatus(ctx context.Context) (*remote.Status, error) {
112	if c.getStatus != nil {
113		return c.getStatus(ctx)
114	}
115	panic("unexpected call")
116}
117
118func (c *attachmentPushTestControlPlane) Reload(context.Context) error {
119	panic("unexpected call")
120}
121
122func (c *attachmentPushTestControlPlane) ListNetworks(context.Context) ([]*domain.NetworkInfo, error) {
123	panic("unexpected call")
124}
125
126func (c *attachmentPushTestControlPlane) GetConfig(context.Context) (*remote.Config, error) {
127	panic("unexpected call")
128}
129
130func (c *attachmentPushTestControlPlane) DeployIntent(context.Context, string) error {
131	panic("unexpected call")
132}
133
134func (c *attachmentPushTestControlPlane) Deploy(context.Context, string) (*remote.DeployResult, error) {
135	panic("unexpected call")
136}
137
138func (c *attachmentPushTestControlPlane) Restart(context.Context, string, bool) (*remote.RestartResult, error) {
139	panic("unexpected call")
140}
141
142func (c *attachmentPushTestControlPlane) ListTags(context.Context, string) ([]string, error) {
143	panic("unexpected call")
144}
145
146func (c *attachmentPushTestControlPlane) ListBackups(context.Context, string) ([]dto.BackupJob, error) {
147	panic("unexpected call")
148}
149
150func (c *attachmentPushTestControlPlane) BackupStatus(context.Context) ([]dto.BackupJob, error) {
151	panic("unexpected call")
152}
153
154func (c *attachmentPushTestControlPlane) RunBackup(context.Context, string, string) (*dto.BackupRunResponse, error) {
155	panic("unexpected call")
156}
157
158func (c *attachmentPushTestControlPlane) DetectDatabases(context.Context, string) ([]dto.DatabaseInfo, error) {
159	panic("unexpected call")
160}
161
162func (c *attachmentPushTestControlPlane) GetProcessLogs(context.Context, int) ([]string, error) {
163	panic("unexpected call")
164}
165
166func (c *attachmentPushTestControlPlane) GetContainerLogs(context.Context, string, int) ([]string, error) {
167	panic("unexpected call")
168}
169
170func (c *attachmentPushTestControlPlane) StreamProcessLogs(context.Context, int) (<-chan string, error) {
171	panic("unexpected call")
172}
173
174func (c *attachmentPushTestControlPlane) StreamContainerLogs(context.Context, string, int) (<-chan string, error) {
175	panic("unexpected call")
176}
177
178func (c *attachmentPushTestControlPlane) ListVolumes(context.Context) ([]dto.Volume, error) {
179	panic("unexpected call")
180}
181
182func (c *attachmentPushTestControlPlane) PruneVolumes(context.Context, dto.VolumePruneRequest) (*dto.VolumePruneResponse, error) {
183	panic("unexpected call")
184}
185
186func TestResolveAttachmentImage_OneTarget(t *testing.T) {
187	cp := &attachmentPushTestControlPlane{
188		findAttachmentTargets: func(context.Context, string) ([]string, error) {
189			return []string{"app.example.com"}, nil
190		},
191		getStatus: func(context.Context) (*remote.Status, error) {
192			return &remote.Status{RegistryDomain: "registry.example.com"}, nil
193		},
194	}
195
196	registry, imageName, targets, err := resolveAttachmentImage(context.Background(), cp, "postgres")
197
198	require.NoError(t, err)
199	assert.Equal(t, "registry.example.com", registry)
200	assert.Equal(t, "postgres", imageName)
201	assert.Equal(t, []string{"app.example.com"}, targets)
202}
203
204func TestResolveAttachmentImage_MultipleTargets(t *testing.T) {
205	cp := &attachmentPushTestControlPlane{
206		findAttachmentTargets: func(context.Context, string) ([]string, error) {
207			return []string{"app.example.com", "backend"}, nil
208		},
209		getStatus: func(context.Context) (*remote.Status, error) {
210			return &remote.Status{RegistryDomain: "registry.example.com"}, nil
211		},
212	}
213
214	registry, imageName, targets, err := resolveAttachmentImage(context.Background(), cp, "redis")
215
216	require.NoError(t, err)
217	assert.Equal(t, "registry.example.com", registry)
218	assert.Equal(t, "redis", imageName)
219	assert.Equal(t, []string{"app.example.com", "backend"}, targets)
220}
221
222func TestResolveAttachmentImage_NotConfigured(t *testing.T) {
223	cp := &attachmentPushTestControlPlane{
224		findAttachmentTargets: func(context.Context, string) ([]string, error) {
225			return nil, nil
226		},
227	}
228
229	_, _, _, err := resolveAttachmentImage(context.Background(), cp, "postgres")
230
231	require.Error(t, err)
232	assert.Contains(t, err.Error(), "not configured as an attachment")
233}
234
235func TestAttachmentPushCmd_NoDeploy(t *testing.T) {
236	origResolveControlPlane := resolveControlPlaneFn
237	origDetermineVersion := determineVersionFn
238	origNewImageOps := newImageOpsFn
239	t.Cleanup(func() {
240		resolveControlPlaneFn = origResolveControlPlane
241		determineVersionFn = origDetermineVersion
242		newImageOpsFn = origNewImageOps
243	})
244
245	cp := &attachmentPushTestControlPlane{
246		findAttachmentTargets: func(context.Context, string) ([]string, error) {
247			return []string{"app.example.com"}, nil
248		},
249		getStatus: func(context.Context) (*remote.Status, error) {
250			return &remote.Status{RegistryDomain: "registry.example.com"}, nil
251		},
252	}
253
254	resolveControlPlaneFn = func(string) (*controlPlaneHandle, error) {
255		return &controlPlaneHandle{plane: cp}, nil
256	}
257	determineVersionFn = func(context.Context, string) string { return "v1.2.3" }
258	pushCalled := false
259	newImageOpsFn = func() (pushImageOps, error) {
260		m := climocks.NewMockpushImageOps(t)
261		m.On("Tag", mock.Anything, mock.Anything, mock.Anything).Return(nil)
262		m.On("Exists", mock.Anything, mock.Anything).Return(true, nil)
263		m.On("Push", mock.Anything, mock.Anything).Run(func(mock.Arguments) {
264			pushCalled = true
265		}).Return(nil)
266		return m, nil
267	}
268
269	cmd := newAttachmentsPushCmd()
270	out := new(bytes.Buffer)
271	cmd.SetOut(out)
272	cmd.SetErr(out)
273	cmd.SetArgs([]string{"postgres"})
274
275	err := cmd.Execute()
276
277	require.NoError(t, err)
278	assert.True(t, pushCalled)
279	assert.Contains(t, out.String(), "Push complete")
280}
281
282func TestAttachmentPushCmd_TaggedImageInputBuildsValidRefs(t *testing.T) {
283	origResolveControlPlane := resolveControlPlaneFn
284	origDetermineVersion := determineVersionFn
285	origNewImageOps := newImageOpsFn
286	t.Cleanup(func() {
287		resolveControlPlaneFn = origResolveControlPlane
288		determineVersionFn = origDetermineVersion
289		newImageOpsFn = origNewImageOps
290	})
291
292	cp := &attachmentPushTestControlPlane{
293		findAttachmentTargets: func(context.Context, string) ([]string, error) {
294			return []string{"app.example.com"}, nil
295		},
296		getStatus: func(context.Context) (*remote.Status, error) {
297			return &remote.Status{RegistryDomain: "registry.example.com"}, nil
298		},
299	}
300
301	resolveControlPlaneFn = func(string) (*controlPlaneHandle, error) {
302		return &controlPlaneHandle{plane: cp}, nil
303	}
304	determineVersionFn = func(context.Context, string) string { return "v1.2.3" }
305
306	var gotVersionRef string
307	var gotLatestRef string
308	newImageOpsFn = func() (pushImageOps, error) {
309		m := climocks.NewMockpushImageOps(t)
310		m.On("Tag", mock.Anything, mock.Anything, mock.Anything).Return(nil)
311		m.On("Exists", mock.Anything, mock.Anything).Return(true, nil)
312		m.On("Push", mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
313			ref := args.Get(1).(string)
314			if gotVersionRef == "" {
315				gotVersionRef = ref
316			} else if gotLatestRef == "" {
317				gotLatestRef = ref
318			}
319		}).Return(nil)
320		return m, nil
321	}
322
323	cmd := newAttachmentsPushCmd()
324	cmd.SetOut(new(bytes.Buffer))
325	cmd.SetErr(new(bytes.Buffer))
326	cmd.SetArgs([]string{"postgres:18"})
327
328	err := cmd.Execute()
329
330	require.NoError(t, err)
331	assert.Equal(t, "registry.example.com/postgres:v1.2.3", gotVersionRef)
332	assert.Equal(t, "registry.example.com/postgres:latest", gotLatestRef)
333}
334
335func TestNormalizeAttachmentImageName_PreservesNamespaceWithoutRegistryHost(t *testing.T) {
336	got := normalizeAttachmentImageName("myorg/postgres:18")
337
338	assert.Equal(t, "myorg/postgres", got)
339}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close