v2.30.0-pre4 15d9fe3

routes_test.go RawHistoryFolder

1package container
2
3import (
4	"testing"
5
6	"github.com/stretchr/testify/assert"
7	"github.com/stretchr/testify/mock"
8
9	"github.com/bnema/gordon/internal/boundaries/out/mocks"
10	"github.com/bnema/gordon/internal/domain"
11)
12
13func TestService_ListRoutesWithDetails(t *testing.T) {
14	runtime := mocks.NewMockContainerRuntime(t)
15	svc := NewService(runtime, nil, nil, nil, Config{NetworkPrefix: "gordon"}, nil)
16	ctx := testContext()
17
18	svc.containers["app.example.com"] = &domain.Container{
19		ID:     "container-1",
20		Image:  "registry/app:latest",
21		Status: "running",
22		Labels: map[string]string{
23			domain.LabelImage: "app:latest",
24		},
25	}
26
27	runtime.EXPECT().GetContainerNetwork(mock.Anything, "container-1").Return("gordon-app-example-com", nil)
28	// getAllAttachments calls GetContainerNetwork for each attachment
29	runtime.EXPECT().GetContainerNetwork(mock.Anything, "attach-1").Return("gordon-app-example-com", nil)
30	runtime.EXPECT().GetContainerNetwork(mock.Anything, "attach-2").Return("gordon-other-example-com", nil)
31	runtime.EXPECT().ListContainers(mock.Anything, true).Return([]*domain.Container{
32		{
33			ID:     "attach-1",
34			Name:   "gordon-app-example-com-postgres",
35			Image:  "postgres:15",
36			Status: "running",
37			Labels: map[string]string{
38				domain.LabelAttachment: "true",
39				domain.LabelAttachedTo: "app.example.com",
40				domain.LabelImage:      "postgres:15",
41			},
42		},
43		{
44			ID:     "attach-2",
45			Name:   "gordon-other-redis",
46			Image:  "redis:7",
47			Status: "running",
48			Labels: map[string]string{
49				domain.LabelAttachment: "true",
50				domain.LabelAttachedTo: "other.example.com",
51				domain.LabelImage:      "redis:7",
52			},
53		},
54		{
55			ID:     "other",
56			Name:   "gordon-other",
57			Image:  "busybox",
58			Status: "running",
59			Labels: map[string]string{
60				domain.LabelAttachment: "false",
61			},
62		},
63	}, nil)
64
65	results := svc.ListRoutesWithDetails(ctx)
66
67	assert.Len(t, results, 1)
68	assert.Equal(t, "app.example.com", results[0].Domain)
69	assert.Equal(t, "app:latest", results[0].Image)
70	assert.Equal(t, "container-1", results[0].ContainerID)
71	assert.Equal(t, "running", results[0].ContainerStatus)
72	assert.Equal(t, "gordon-app-example-com", results[0].Network)
73	if assert.Len(t, results[0].Attachments, 1) {
74		assert.Equal(t, "postgres", results[0].Attachments[0].Name)
75		assert.Equal(t, "postgres:15", results[0].Attachments[0].Image)
76		assert.Equal(t, "attach-1", results[0].Attachments[0].ContainerID)
77		assert.Equal(t, "gordon-app-example-com", results[0].Attachments[0].Network)
78	}
79}
80
81func TestService_ListRoutesWithDetails_Empty(t *testing.T) {
82	runtime := mocks.NewMockContainerRuntime(t)
83	svc := NewService(runtime, nil, nil, nil, Config{NetworkPrefix: "gordon"}, nil)
84	ctx := testContext()
85
86	// getAllAttachments is called even with empty containers
87	runtime.EXPECT().ListContainers(mock.Anything, true).Return([]*domain.Container{}, nil)
88
89	results := svc.ListRoutesWithDetails(ctx)
90
91	assert.Empty(t, results)
92}
93
94func TestService_ListRoutesWithDetails_NetworkError(t *testing.T) {
95	runtime := mocks.NewMockContainerRuntime(t)
96	svc := NewService(runtime, nil, nil, nil, Config{NetworkPrefix: "gordon"}, nil)
97	ctx := testContext()
98
99	svc.containers["app.example.com"] = &domain.Container{
100		ID:     "container-1",
101		Image:  "app:latest",
102		Status: "running",
103	}
104
105	runtime.EXPECT().GetContainerNetwork(mock.Anything, "container-1").Return("", assert.AnError)
106	runtime.EXPECT().ListContainers(mock.Anything, true).Return([]*domain.Container{}, nil)
107
108	results := svc.ListRoutesWithDetails(ctx)
109
110	assert.Len(t, results, 1)
111	assert.Equal(t, "", results[0].Network)
112}
113
114func TestService_ListAttachments(t *testing.T) {
115	runtime := mocks.NewMockContainerRuntime(t)
116	svc := NewService(runtime, nil, nil, nil, Config{}, nil)
117	ctx := testContext()
118
119	runtime.EXPECT().ListContainers(mock.Anything, true).Return([]*domain.Container{
120		{
121			ID:     "attach-1",
122			Name:   "gordon-app-example-com-postgres",
123			Image:  "postgres:15",
124			Status: "running",
125			Labels: map[string]string{
126				domain.LabelAttachment: "true",
127				domain.LabelAttachedTo: "app.example.com",
128				domain.LabelImage:      "postgres:15",
129			},
130		},
131		{
132			ID:     "attach-2",
133			Name:   "gordon-other-redis",
134			Image:  "redis:7",
135			Status: "running",
136			Labels: map[string]string{
137				domain.LabelAttachment: "true",
138				domain.LabelAttachedTo: "other.example.com",
139				domain.LabelImage:      "redis:7",
140			},
141		},
142	}, nil)
143	runtime.EXPECT().GetContainerNetwork(mock.Anything, "attach-1").Return("gordon-app-example-com", nil)
144
145	attachments := svc.ListAttachments(ctx, "app.example.com")
146
147	assert.Len(t, attachments, 1)
148	assert.Equal(t, "postgres", attachments[0].Name)
149	assert.Equal(t, "postgres:15", attachments[0].Image)
150	assert.Equal(t, "attach-1", attachments[0].ContainerID)
151	assert.Equal(t, "gordon-app-example-com", attachments[0].Network)
152}
153
154func TestService_ListNetworks(t *testing.T) {
155	runtime := mocks.NewMockContainerRuntime(t)
156	svc := NewService(runtime, nil, nil, nil, Config{NetworkPrefix: "gordon"}, nil)
157	ctx := testContext()
158
159	runtime.EXPECT().ListNetworks(mock.Anything).Return([]*domain.NetworkInfo{
160		{Name: "gordon-app", Labels: map[string]string{domain.LabelManaged: "true"}},
161		{Name: "bridge"},
162		{Name: "gordon-shared", Labels: map[string]string{domain.LabelManaged: "true"}},
163		{Name: "gordon-unmanaged"},
164	}, nil)
165
166	networks, err := svc.ListNetworks(ctx)
167
168	assert.NoError(t, err)
169	assert.Len(t, networks, 2)
170	assert.Equal(t, "gordon-app", networks[0].Name)
171	assert.Equal(t, "gordon-shared", networks[1].Name)
172	assert.NotContains(t, []string{networks[0].Name, networks[1].Name}, "gordon-unmanaged")
173}

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