feat(docker): implement GetImageID and populate ImageID in ListContainers and InspectContainer
- commit
- e057b287afbc13dcdd44c0aa07e4309b740fee4f
- author
- bnema · · 2026-02-09 20:41 UTC
- parent
- 24d79bf
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
2 files · +92 -6
M internal/adapters/out/docker/runtime.go +26 -6
| @@ -305,12 +305,13 @@ func (r *Runtime) ListContainers(ctx context.Context, all bool) ([]*domain.Conta | |||
| 305 | 305 | } | |
| 306 | 306 | ||
| 307 | 307 | result = append(result, &domain.Container{ | |
| 308 | - | ID: c.ID, | |
| 309 | - | Image: c.Image, | |
| 310 | - | Name: name, | |
| 311 | - | Status: c.State, // Use State (e.g., "running") not Status (e.g., "Up 2 days") | |
| 312 | - | Ports: ports, | |
| 313 | - | Labels: c.Labels, | |
| 308 | + | ID: c.ID, | |
| 309 | + | Image: c.Image, | |
| 310 | + | ImageID: c.ImageID, | |
| 311 | + | Name: name, | |
| 312 | + | Status: c.State, // Use State (e.g., "running") not Status (e.g., "Up 2 days") | |
| 313 | + | Ports: ports, | |
| 314 | + | Labels: c.Labels, | |
| 314 | 315 | }) | |
| 315 | 316 | } | |
| 316 | 317 | ||
| @@ -352,6 +353,7 @@ func (r *Runtime) InspectContainer(ctx context.Context, containerID string) (*do | |||
| 352 | 353 | return &domain.Container{ | |
| 353 | 354 | ID: resp.ID, | |
| 354 | 355 | Image: resp.Config.Image, | |
| 356 | + | ImageID: resp.Image, | |
| 355 | 357 | Name: name, | |
| 356 | 358 | Status: resp.State.Status, | |
| 357 | 359 | ExitCode: resp.State.ExitCode, | |
| @@ -1103,6 +1105,24 @@ func (r *Runtime) GetImageLabels(ctx context.Context, imageRef string) (map[stri | |||
| 1103 | 1105 | return labels, nil | |
| 1104 | 1106 | } | |
| 1105 | 1107 | ||
| 1108 | + | // GetImageID returns the unique image ID (sha256 digest) for the given image reference. | |
| 1109 | + | func (r *Runtime) GetImageID(ctx context.Context, imageRef string) (string, error) { | |
| 1110 | + | ctx = zerowrap.CtxWithFields(ctx, map[string]any{ | |
| 1111 | + | zerowrap.FieldLayer: "adapter", | |
| 1112 | + | zerowrap.FieldAdapter: "docker", | |
| 1113 | + | zerowrap.FieldAction: "GetImageID", | |
| 1114 | + | "image": imageRef, | |
| 1115 | + | }) | |
| 1116 | + | log := zerowrap.FromCtx(ctx) | |
| 1117 | + | ||
| 1118 | + | imageInspect, err := r.client.ImageInspect(ctx, imageRef) | |
| 1119 | + | if err != nil { | |
| 1120 | + | return "", log.WrapErr(err, "failed to inspect image") | |
| 1121 | + | } | |
| 1122 | + | ||
| 1123 | + | return imageInspect.ID, nil | |
| 1124 | + | } | |
| 1125 | + | ||
| 1106 | 1126 | // CreateNetwork creates a new Docker network. | |
| 1107 | 1127 | func (r *Runtime) CreateNetwork(ctx context.Context, name string, options map[string]string) error { | |
| 1108 | 1128 | ctx = zerowrap.CtxWithFields(ctx, map[string]any{ | |
| @@ -305,12 +305,13 @@ func (r *Runtime) ListContainers(ctx context.Context, all bool) ([]*domain.Conta | |||||
| 305 | } | 305 | } | ||
| 306 | 306 | ||||
| 307 | result = append(result, &domain.Container{ | 307 | result = append(result, &domain.Container{ | ||
| 308 | - | ID: c.ID, | 308 | + | ID: c.ID, |
| 309 | - | Image: c.Image, | 309 | + | Image: c.Image, |
| 310 | - | Name: name, | 310 | + | ImageID: c.ImageID, |
| 311 | - | Status: c.State, // Use State (e.g., "running") not Status (e.g., "Up 2 days") | 311 | + | Name: name, |
| 312 | - | Ports: ports, | 312 | + | Status: c.State, // Use State (e.g., "running") not Status (e.g., "Up 2 days") |
| 313 | - | Labels: c.Labels, | 313 | + | Ports: ports, |
| 314 | + | Labels: c.Labels, | |||
| 314 | }) | 315 | }) | ||
| 315 | } | 316 | } | ||
| 316 | 317 | ||||
| @@ -352,6 +353,7 @@ func (r *Runtime) InspectContainer(ctx context.Context, containerID string) (*do | |||||
| 352 | return &domain.Container{ | 353 | return &domain.Container{ | ||
| 353 | ID: resp.ID, | 354 | ID: resp.ID, | ||
| 354 | Image: resp.Config.Image, | 355 | Image: resp.Config.Image, | ||
| 356 | + | ImageID: resp.Image, | |||
| 355 | Name: name, | 357 | Name: name, | ||
| 356 | Status: resp.State.Status, | 358 | Status: resp.State.Status, | ||
| 357 | ExitCode: resp.State.ExitCode, | 359 | ExitCode: resp.State.ExitCode, | ||
| @@ -1103,6 +1105,24 @@ func (r *Runtime) GetImageLabels(ctx context.Context, imageRef string) (map[stri | |||||
| 1103 | return labels, nil | 1105 | return labels, nil | ||
| 1104 | } | 1106 | } | ||
| 1105 | 1107 | ||||
| 1108 | + | // GetImageID returns the unique image ID (sha256 digest) for the given image reference. | |||
| 1109 | + | func (r *Runtime) GetImageID(ctx context.Context, imageRef string) (string, error) { | |||
| 1110 | + | ctx = zerowrap.CtxWithFields(ctx, map[string]any{ | |||
| 1111 | + | zerowrap.FieldLayer: "adapter", | |||
| 1112 | + | zerowrap.FieldAdapter: "docker", | |||
| 1113 | + | zerowrap.FieldAction: "GetImageID", | |||
| 1114 | + | "image": imageRef, | |||
| 1115 | + | }) | |||
| 1116 | + | log := zerowrap.FromCtx(ctx) | |||
| 1117 | + | ||||
| 1118 | + | imageInspect, err := r.client.ImageInspect(ctx, imageRef) | |||
| 1119 | + | if err != nil { | |||
| 1120 | + | return "", log.WrapErr(err, "failed to inspect image") | |||
| 1121 | + | } | |||
| 1122 | + | ||||
| 1123 | + | return imageInspect.ID, nil | |||
| 1124 | + | } | |||
| 1125 | + | ||||
| 1106 | // CreateNetwork creates a new Docker network. | 1126 | // CreateNetwork creates a new Docker network. | ||
| 1107 | func (r *Runtime) CreateNetwork(ctx context.Context, name string, options map[string]string) error { | 1127 | func (r *Runtime) CreateNetwork(ctx context.Context, name string, options map[string]string) error { | ||
| 1108 | ctx = zerowrap.CtxWithFields(ctx, map[string]any{ | 1128 | ctx = zerowrap.CtxWithFields(ctx, map[string]any{ | ||
M internal/boundaries/out/mocks/mock_container_runtime.go +66 -0
| @@ -994,6 +994,72 @@ func (_c *MockContainerRuntime_GetImageExposedPorts_Call) RunAndReturn(run func( | |||
| 994 | 994 | return _c | |
| 995 | 995 | } | |
| 996 | 996 | ||
| 997 | + | // GetImageID provides a mock function for the type MockContainerRuntime | |
| 998 | + | func (_mock *MockContainerRuntime) GetImageID(ctx context.Context, imageRef string) (string, error) { | |
| 999 | + | ret := _mock.Called(ctx, imageRef) | |
| 1000 | + | ||
| 1001 | + | if len(ret) == 0 { | |
| 1002 | + | panic("no return value specified for GetImageID") | |
| 1003 | + | } | |
| 1004 | + | ||
| 1005 | + | var r0 string | |
| 1006 | + | var r1 error | |
| 1007 | + | if returnFunc, ok := ret.Get(0).(func(context.Context, string) (string, error)); ok { | |
| 1008 | + | return returnFunc(ctx, imageRef) | |
| 1009 | + | } | |
| 1010 | + | if returnFunc, ok := ret.Get(0).(func(context.Context, string) string); ok { | |
| 1011 | + | r0 = returnFunc(ctx, imageRef) | |
| 1012 | + | } else { | |
| 1013 | + | r0 = ret.Get(0).(string) | |
| 1014 | + | } | |
| 1015 | + | if returnFunc, ok := ret.Get(1).(func(context.Context, string) error); ok { | |
| 1016 | + | r1 = returnFunc(ctx, imageRef) | |
| 1017 | + | } else { | |
| 1018 | + | r1 = ret.Error(1) | |
| 1019 | + | } | |
| 1020 | + | return r0, r1 | |
| 1021 | + | } | |
| 1022 | + | ||
| 1023 | + | // MockContainerRuntime_GetImageID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetImageID' | |
| 1024 | + | type MockContainerRuntime_GetImageID_Call struct { | |
| 1025 | + | *mock.Call | |
| 1026 | + | } | |
| 1027 | + | ||
| 1028 | + | // GetImageID is a helper method to define mock.On call | |
| 1029 | + | // - ctx context.Context | |
| 1030 | + | // - imageRef string | |
| 1031 | + | func (_e *MockContainerRuntime_Expecter) GetImageID(ctx interface{}, imageRef interface{}) *MockContainerRuntime_GetImageID_Call { | |
| 1032 | + | return &MockContainerRuntime_GetImageID_Call{Call: _e.mock.On("GetImageID", ctx, imageRef)} | |
| 1033 | + | } | |
| 1034 | + | ||
| 1035 | + | func (_c *MockContainerRuntime_GetImageID_Call) Run(run func(ctx context.Context, imageRef string)) *MockContainerRuntime_GetImageID_Call { | |
| 1036 | + | _c.Call.Run(func(args mock.Arguments) { | |
| 1037 | + | var arg0 context.Context | |
| 1038 | + | if args[0] != nil { | |
| 1039 | + | arg0 = args[0].(context.Context) | |
| 1040 | + | } | |
| 1041 | + | var arg1 string | |
| 1042 | + | if args[1] != nil { | |
| 1043 | + | arg1 = args[1].(string) | |
| 1044 | + | } | |
| 1045 | + | run( | |
| 1046 | + | arg0, | |
| 1047 | + | arg1, | |
| 1048 | + | ) | |
| 1049 | + | }) | |
| 1050 | + | return _c | |
| 1051 | + | } | |
| 1052 | + | ||
| 1053 | + | func (_c *MockContainerRuntime_GetImageID_Call) Return(s string, err error) *MockContainerRuntime_GetImageID_Call { | |
| 1054 | + | _c.Call.Return(s, err) | |
| 1055 | + | return _c | |
| 1056 | + | } | |
| 1057 | + | ||
| 1058 | + | func (_c *MockContainerRuntime_GetImageID_Call) RunAndReturn(run func(ctx context.Context, imageRef string) (string, error)) *MockContainerRuntime_GetImageID_Call { | |
| 1059 | + | _c.Call.Return(run) | |
| 1060 | + | return _c | |
| 1061 | + | } | |
| 1062 | + | ||
| 997 | 1063 | // GetImageLabels provides a mock function for the type MockContainerRuntime | |
| 998 | 1064 | func (_mock *MockContainerRuntime) GetImageLabels(ctx context.Context, imageRef string) (map[string]string, error) { | |
| 999 | 1065 | ret := _mock.Called(ctx, imageRef) | |
| @@ -994,6 +994,72 @@ func (_c *MockContainerRuntime_GetImageExposedPorts_Call) RunAndReturn(run func( | |||||
| 994 | return _c | 994 | return _c | ||
| 995 | } | 995 | } | ||
| 996 | 996 | ||||
| 997 | + | // GetImageID provides a mock function for the type MockContainerRuntime | |||
| 998 | + | func (_mock *MockContainerRuntime) GetImageID(ctx context.Context, imageRef string) (string, error) { | |||
| 999 | + | ret := _mock.Called(ctx, imageRef) | |||
| 1000 | + | ||||
| 1001 | + | if len(ret) == 0 { | |||
| 1002 | + | panic("no return value specified for GetImageID") | |||
| 1003 | + | } | |||
| 1004 | + | ||||
| 1005 | + | var r0 string | |||
| 1006 | + | var r1 error | |||
| 1007 | + | if returnFunc, ok := ret.Get(0).(func(context.Context, string) (string, error)); ok { | |||
| 1008 | + | return returnFunc(ctx, imageRef) | |||
| 1009 | + | } | |||
| 1010 | + | if returnFunc, ok := ret.Get(0).(func(context.Context, string) string); ok { | |||
| 1011 | + | r0 = returnFunc(ctx, imageRef) | |||
| 1012 | + | } else { | |||
| 1013 | + | r0 = ret.Get(0).(string) | |||
| 1014 | + | } | |||
| 1015 | + | if returnFunc, ok := ret.Get(1).(func(context.Context, string) error); ok { | |||
| 1016 | + | r1 = returnFunc(ctx, imageRef) | |||
| 1017 | + | } else { | |||
| 1018 | + | r1 = ret.Error(1) | |||
| 1019 | + | } | |||
| 1020 | + | return r0, r1 | |||
| 1021 | + | } | |||
| 1022 | + | ||||
| 1023 | + | // MockContainerRuntime_GetImageID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetImageID' | |||
| 1024 | + | type MockContainerRuntime_GetImageID_Call struct { | |||
| 1025 | + | *mock.Call | |||
| 1026 | + | } | |||
| 1027 | + | ||||
| 1028 | + | // GetImageID is a helper method to define mock.On call | |||
| 1029 | + | // - ctx context.Context | |||
| 1030 | + | // - imageRef string | |||
| 1031 | + | func (_e *MockContainerRuntime_Expecter) GetImageID(ctx interface{}, imageRef interface{}) *MockContainerRuntime_GetImageID_Call { | |||
| 1032 | + | return &MockContainerRuntime_GetImageID_Call{Call: _e.mock.On("GetImageID", ctx, imageRef)} | |||
| 1033 | + | } | |||
| 1034 | + | ||||
| 1035 | + | func (_c *MockContainerRuntime_GetImageID_Call) Run(run func(ctx context.Context, imageRef string)) *MockContainerRuntime_GetImageID_Call { | |||
| 1036 | + | _c.Call.Run(func(args mock.Arguments) { | |||
| 1037 | + | var arg0 context.Context | |||
| 1038 | + | if args[0] != nil { | |||
| 1039 | + | arg0 = args[0].(context.Context) | |||
| 1040 | + | } | |||
| 1041 | + | var arg1 string | |||
| 1042 | + | if args[1] != nil { | |||
| 1043 | + | arg1 = args[1].(string) | |||
| 1044 | + | } | |||
| 1045 | + | run( | |||
| 1046 | + | arg0, | |||
| 1047 | + | arg1, | |||
| 1048 | + | ) | |||
| 1049 | + | }) | |||
| 1050 | + | return _c | |||
| 1051 | + | } | |||
| 1052 | + | ||||
| 1053 | + | func (_c *MockContainerRuntime_GetImageID_Call) Return(s string, err error) *MockContainerRuntime_GetImageID_Call { | |||
| 1054 | + | _c.Call.Return(s, err) | |||
| 1055 | + | return _c | |||
| 1056 | + | } | |||
| 1057 | + | ||||
| 1058 | + | func (_c *MockContainerRuntime_GetImageID_Call) RunAndReturn(run func(ctx context.Context, imageRef string) (string, error)) *MockContainerRuntime_GetImageID_Call { | |||
| 1059 | + | _c.Call.Return(run) | |||
| 1060 | + | return _c | |||
| 1061 | + | } | |||
| 1062 | + | ||||
| 997 | // GetImageLabels provides a mock function for the type MockContainerRuntime | 1063 | // GetImageLabels provides a mock function for the type MockContainerRuntime | ||
| 998 | func (_mock *MockContainerRuntime) GetImageLabels(ctx context.Context, imageRef string) (map[string]string, error) { | 1064 | func (_mock *MockContainerRuntime) GetImageLabels(ctx context.Context, imageRef string) (map[string]string, error) { | ||
| 999 | ret := _mock.Called(ctx, imageRef) | 1065 | ret := _mock.Called(ctx, imageRef) | ||