detached e555572

feat(adapters/docker): add RenameContainer method to runtime

Add RenameContainer to ContainerRuntime interface and implement
in Docker adapter. This enables renaming containers after
zero-downtime deployment to restore canonical naming.
commit
e555572296dc08d0c9142320cfcfeca8b48bfea1
author
brice · · 2026-01-12 21:07 UTC
committer
brice · · 2026-01-12 18:34 UTC
parent
22299cc
signature
unsigned
3 files · +84 -0
M internal/adapters/out/docker/runtime.go +20 -0
@@ -208,6 +208,26 @@ func (r *Runtime) RemoveContainer(ctx context.Context, containerID string, force
208208 return nil
209209 }
210210
211+// RenameContainer renames a container.
212+func (r *Runtime) RenameContainer(ctx context.Context, containerID, newName string) error {
213+ ctx = zerowrap.CtxWithFields(ctx, map[string]any{
214+ zerowrap.FieldLayer: "adapter",
215+ zerowrap.FieldAdapter: "docker",
216+ zerowrap.FieldAction: "RenameContainer",
217+ zerowrap.FieldEntityID: containerID,
218+ "new_name": newName,
219+ })
220+ log := zerowrap.FromCtx(ctx)
221+
222+ err := r.client.ContainerRename(ctx, containerID, newName)
223+ if err != nil {
224+ return log.WrapErr(err, "failed to rename container")
225+ }
226+
227+ log.Info().Msg("container renamed")
228+ return nil
229+}
230+
211231 // ListContainers lists containers.
212232 func (r *Runtime) ListContainers(ctx context.Context, all bool) ([]*domain.Container, error) {
213233 ctx = zerowrap.CtxWithFields(ctx, map[string]any{
@@ -208,6 +208,26 @@ func (r *Runtime) RemoveContainer(ctx context.Context, containerID string, force
208 return nil208 return nil
209 }209 }
210 210
211+// RenameContainer renames a container.
212+func (r *Runtime) RenameContainer(ctx context.Context, containerID, newName string) error {
213+ ctx = zerowrap.CtxWithFields(ctx, map[string]any{
214+ zerowrap.FieldLayer: "adapter",
215+ zerowrap.FieldAdapter: "docker",
216+ zerowrap.FieldAction: "RenameContainer",
217+ zerowrap.FieldEntityID: containerID,
218+ "new_name": newName,
219+ })
220+ log := zerowrap.FromCtx(ctx)
221+
222+ err := r.client.ContainerRename(ctx, containerID, newName)
223+ if err != nil {
224+ return log.WrapErr(err, "failed to rename container")
225+ }
226+
227+ log.Info().Msg("container renamed")
228+ return nil
229+}
230+
211 // ListContainers lists containers.231 // ListContainers lists containers.
212 func (r *Runtime) ListContainers(ctx context.Context, all bool) ([]*domain.Container, error) {232 func (r *Runtime) ListContainers(ctx context.Context, all bool) ([]*domain.Container, error) {
213 ctx = zerowrap.CtxWithFields(ctx, map[string]any{233 ctx = zerowrap.CtxWithFields(ctx, map[string]any{
M internal/boundaries/out/mocks/mock_container_runtime.go +63 -0
@@ -1658,6 +1658,69 @@ func (_c *MockContainerRuntime_RemoveVolume_Call) RunAndReturn(run func(ctx cont
16581658 return _c
16591659 }
16601660
1661+// RenameContainer provides a mock function for the type MockContainerRuntime
1662+func (_mock *MockContainerRuntime) RenameContainer(ctx context.Context, containerID string, newName string) error {
1663+ ret := _mock.Called(ctx, containerID, newName)
1664+
1665+ if len(ret) == 0 {
1666+ panic("no return value specified for RenameContainer")
1667+ }
1668+
1669+ var r0 error
1670+ if returnFunc, ok := ret.Get(0).(func(context.Context, string, string) error); ok {
1671+ r0 = returnFunc(ctx, containerID, newName)
1672+ } else {
1673+ r0 = ret.Error(0)
1674+ }
1675+ return r0
1676+}
1677+
1678+// MockContainerRuntime_RenameContainer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RenameContainer'
1679+type MockContainerRuntime_RenameContainer_Call struct {
1680+ *mock.Call
1681+}
1682+
1683+// RenameContainer is a helper method to define mock.On call
1684+// - ctx context.Context
1685+// - containerID string
1686+// - newName string
1687+func (_e *MockContainerRuntime_Expecter) RenameContainer(ctx interface{}, containerID interface{}, newName interface{}) *MockContainerRuntime_RenameContainer_Call {
1688+ return &MockContainerRuntime_RenameContainer_Call{Call: _e.mock.On("RenameContainer", ctx, containerID, newName)}
1689+}
1690+
1691+func (_c *MockContainerRuntime_RenameContainer_Call) Run(run func(ctx context.Context, containerID string, newName string)) *MockContainerRuntime_RenameContainer_Call {
1692+ _c.Call.Run(func(args mock.Arguments) {
1693+ var arg0 context.Context
1694+ if args[0] != nil {
1695+ arg0 = args[0].(context.Context)
1696+ }
1697+ var arg1 string
1698+ if args[1] != nil {
1699+ arg1 = args[1].(string)
1700+ }
1701+ var arg2 string
1702+ if args[2] != nil {
1703+ arg2 = args[2].(string)
1704+ }
1705+ run(
1706+ arg0,
1707+ arg1,
1708+ arg2,
1709+ )
1710+ })
1711+ return _c
1712+}
1713+
1714+func (_c *MockContainerRuntime_RenameContainer_Call) Return(err error) *MockContainerRuntime_RenameContainer_Call {
1715+ _c.Call.Return(err)
1716+ return _c
1717+}
1718+
1719+func (_c *MockContainerRuntime_RenameContainer_Call) RunAndReturn(run func(ctx context.Context, containerID string, newName string) error) *MockContainerRuntime_RenameContainer_Call {
1720+ _c.Call.Return(run)
1721+ return _c
1722+}
1723+
16611724 // RestartContainer provides a mock function for the type MockContainerRuntime
16621725 func (_mock *MockContainerRuntime) RestartContainer(ctx context.Context, containerID string) error {
16631726 ret := _mock.Called(ctx, containerID)
@@ -1658,6 +1658,69 @@ func (_c *MockContainerRuntime_RemoveVolume_Call) RunAndReturn(run func(ctx cont
1658 return _c1658 return _c
1659 }1659 }
1660 1660
1661+// RenameContainer provides a mock function for the type MockContainerRuntime
1662+func (_mock *MockContainerRuntime) RenameContainer(ctx context.Context, containerID string, newName string) error {
1663+ ret := _mock.Called(ctx, containerID, newName)
1664+
1665+ if len(ret) == 0 {
1666+ panic("no return value specified for RenameContainer")
1667+ }
1668+
1669+ var r0 error
1670+ if returnFunc, ok := ret.Get(0).(func(context.Context, string, string) error); ok {
1671+ r0 = returnFunc(ctx, containerID, newName)
1672+ } else {
1673+ r0 = ret.Error(0)
1674+ }
1675+ return r0
1676+}
1677+
1678+// MockContainerRuntime_RenameContainer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RenameContainer'
1679+type MockContainerRuntime_RenameContainer_Call struct {
1680+ *mock.Call
1681+}
1682+
1683+// RenameContainer is a helper method to define mock.On call
1684+// - ctx context.Context
1685+// - containerID string
1686+// - newName string
1687+func (_e *MockContainerRuntime_Expecter) RenameContainer(ctx interface{}, containerID interface{}, newName interface{}) *MockContainerRuntime_RenameContainer_Call {
1688+ return &MockContainerRuntime_RenameContainer_Call{Call: _e.mock.On("RenameContainer", ctx, containerID, newName)}
1689+}
1690+
1691+func (_c *MockContainerRuntime_RenameContainer_Call) Run(run func(ctx context.Context, containerID string, newName string)) *MockContainerRuntime_RenameContainer_Call {
1692+ _c.Call.Run(func(args mock.Arguments) {
1693+ var arg0 context.Context
1694+ if args[0] != nil {
1695+ arg0 = args[0].(context.Context)
1696+ }
1697+ var arg1 string
1698+ if args[1] != nil {
1699+ arg1 = args[1].(string)
1700+ }
1701+ var arg2 string
1702+ if args[2] != nil {
1703+ arg2 = args[2].(string)
1704+ }
1705+ run(
1706+ arg0,
1707+ arg1,
1708+ arg2,
1709+ )
1710+ })
1711+ return _c
1712+}
1713+
1714+func (_c *MockContainerRuntime_RenameContainer_Call) Return(err error) *MockContainerRuntime_RenameContainer_Call {
1715+ _c.Call.Return(err)
1716+ return _c
1717+}
1718+
1719+func (_c *MockContainerRuntime_RenameContainer_Call) RunAndReturn(run func(ctx context.Context, containerID string, newName string) error) *MockContainerRuntime_RenameContainer_Call {
1720+ _c.Call.Return(run)
1721+ return _c
1722+}
1723+
1661 // RestartContainer provides a mock function for the type MockContainerRuntime1724 // RestartContainer provides a mock function for the type MockContainerRuntime
1662 func (_mock *MockContainerRuntime) RestartContainer(ctx context.Context, containerID string) error {1725 func (_mock *MockContainerRuntime) RestartContainer(ctx context.Context, containerID string) error {
1663 ret := _mock.Called(ctx, containerID)1726 ret := _mock.Called(ctx, containerID)
M internal/boundaries/out/runtime.go +1 -0
@@ -19,6 +19,7 @@ type ContainerRuntime interface {
1919 StopContainer(ctx context.Context, containerID string) error
2020 RestartContainer(ctx context.Context, containerID string) error
2121 RemoveContainer(ctx context.Context, containerID string, force bool) error
22+ RenameContainer(ctx context.Context, containerID, newName string) error
2223
2324 // Container inspection
2425 ListContainers(ctx context.Context, all bool) ([]*domain.Container, error)
@@ -19,6 +19,7 @@ type ContainerRuntime interface {
19 StopContainer(ctx context.Context, containerID string) error19 StopContainer(ctx context.Context, containerID string) error
20 RestartContainer(ctx context.Context, containerID string) error20 RestartContainer(ctx context.Context, containerID string) error
21 RemoveContainer(ctx context.Context, containerID string, force bool) error21 RemoveContainer(ctx context.Context, containerID string, force bool) error
22+ RenameContainer(ctx context.Context, containerID, newName string) error
22 23
23 // Container inspection24 // Container inspection
24 ListContainers(ctx context.Context, all bool) ([]*domain.Container, error)25 ListContainers(ctx context.Context, all bool) ([]*domain.Container, error)

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