Add restart policy update runtime support
- commit
- d3752fd580200c875fd02b8a8523ae7c41160bfc
- author
- brice · · 2026-05-05 08:48 UTC
- parent
- 65d845e
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
4 files · +231 -0
M internal/adapters/out/docker/runtime.go +38 -0
| @@ -43,6 +43,8 @@ type Runtime struct { | |||
| 43 | 43 | client *client.Client | |
| 44 | 44 | } | |
| 45 | 45 | ||
| 46 | + | var _ out.ContainerRuntime = (*Runtime)(nil) | |
| 47 | + | ||
| 46 | 48 | type pipeReadCloser struct { | |
| 47 | 49 | pr *io.PipeReader | |
| 48 | 50 | pw *io.PipeWriter | |
| @@ -361,6 +363,42 @@ func (r *Runtime) RenameContainer(ctx context.Context, containerID, newName stri | |||
| 361 | 363 | return nil | |
| 362 | 364 | } | |
| 363 | 365 | ||
| 366 | + | // EnsureContainerRestartPolicy updates a container restart policy when it does not match. | |
| 367 | + | func (r *Runtime) EnsureContainerRestartPolicy(ctx context.Context, containerID, policy string) error { | |
| 368 | + | ctx = zerowrap.CtxWithFields(ctx, map[string]any{ | |
| 369 | + | zerowrap.FieldLayer: "adapter", | |
| 370 | + | zerowrap.FieldAdapter: "docker", | |
| 371 | + | zerowrap.FieldAction: "EnsureContainerRestartPolicy", | |
| 372 | + | zerowrap.FieldEntityID: containerID, | |
| 373 | + | "restart_policy": policy, | |
| 374 | + | }) | |
| 375 | + | log := zerowrap.FromCtx(ctx) | |
| 376 | + | ||
| 377 | + | inspect, err := r.client.ContainerInspect(ctx, containerID) | |
| 378 | + | if err != nil { | |
| 379 | + | return log.WrapErr(err, "failed to inspect container") | |
| 380 | + | } | |
| 381 | + | if inspect.HostConfig == nil { | |
| 382 | + | return fmt.Errorf("container inspect response missing host config: %s", containerID) | |
| 383 | + | } | |
| 384 | + | if string(inspect.HostConfig.RestartPolicy.Name) == policy { | |
| 385 | + | return nil | |
| 386 | + | } | |
| 387 | + | ||
| 388 | + | updateConfig := container.UpdateConfig{ | |
| 389 | + | Resources: inspect.HostConfig.Resources, | |
| 390 | + | RestartPolicy: container.RestartPolicy{Name: container.RestartPolicyMode(policy)}, | |
| 391 | + | } | |
| 392 | + | resp, err := r.client.ContainerUpdate(ctx, containerID, updateConfig) | |
| 393 | + | if err != nil { | |
| 394 | + | return log.WrapErr(err, "failed to update container restart policy") | |
| 395 | + | } | |
| 396 | + | for _, warning := range resp.Warnings { | |
| 397 | + | log.Warn().Str("warning", warning).Msg("container restart policy update warning") | |
| 398 | + | } | |
| 399 | + | return nil | |
| 400 | + | } | |
| 401 | + | ||
| 364 | 402 | // ListContainers lists containers. | |
| 365 | 403 | func (r *Runtime) ListContainers(ctx context.Context, all bool) ([]*domain.Container, error) { | |
| 366 | 404 | ctx = zerowrap.CtxWithFields(ctx, map[string]any{ | |
| @@ -43,6 +43,8 @@ type Runtime struct { | |||||
| 43 | client *client.Client | 43 | client *client.Client | ||
| 44 | } | 44 | } | ||
| 45 | 45 | ||||
| 46 | + | var _ out.ContainerRuntime = (*Runtime)(nil) | |||
| 47 | + | ||||
| 46 | type pipeReadCloser struct { | 48 | type pipeReadCloser struct { | ||
| 47 | pr *io.PipeReader | 49 | pr *io.PipeReader | ||
| 48 | pw *io.PipeWriter | 50 | pw *io.PipeWriter | ||
| @@ -361,6 +363,42 @@ func (r *Runtime) RenameContainer(ctx context.Context, containerID, newName stri | |||||
| 361 | return nil | 363 | return nil | ||
| 362 | } | 364 | } | ||
| 363 | 365 | ||||
| 366 | + | // EnsureContainerRestartPolicy updates a container restart policy when it does not match. | |||
| 367 | + | func (r *Runtime) EnsureContainerRestartPolicy(ctx context.Context, containerID, policy string) error { | |||
| 368 | + | ctx = zerowrap.CtxWithFields(ctx, map[string]any{ | |||
| 369 | + | zerowrap.FieldLayer: "adapter", | |||
| 370 | + | zerowrap.FieldAdapter: "docker", | |||
| 371 | + | zerowrap.FieldAction: "EnsureContainerRestartPolicy", | |||
| 372 | + | zerowrap.FieldEntityID: containerID, | |||
| 373 | + | "restart_policy": policy, | |||
| 374 | + | }) | |||
| 375 | + | log := zerowrap.FromCtx(ctx) | |||
| 376 | + | ||||
| 377 | + | inspect, err := r.client.ContainerInspect(ctx, containerID) | |||
| 378 | + | if err != nil { | |||
| 379 | + | return log.WrapErr(err, "failed to inspect container") | |||
| 380 | + | } | |||
| 381 | + | if inspect.HostConfig == nil { | |||
| 382 | + | return fmt.Errorf("container inspect response missing host config: %s", containerID) | |||
| 383 | + | } | |||
| 384 | + | if string(inspect.HostConfig.RestartPolicy.Name) == policy { | |||
| 385 | + | return nil | |||
| 386 | + | } | |||
| 387 | + | ||||
| 388 | + | updateConfig := container.UpdateConfig{ | |||
| 389 | + | Resources: inspect.HostConfig.Resources, | |||
| 390 | + | RestartPolicy: container.RestartPolicy{Name: container.RestartPolicyMode(policy)}, | |||
| 391 | + | } | |||
| 392 | + | resp, err := r.client.ContainerUpdate(ctx, containerID, updateConfig) | |||
| 393 | + | if err != nil { | |||
| 394 | + | return log.WrapErr(err, "failed to update container restart policy") | |||
| 395 | + | } | |||
| 396 | + | for _, warning := range resp.Warnings { | |||
| 397 | + | log.Warn().Str("warning", warning).Msg("container restart policy update warning") | |||
| 398 | + | } | |||
| 399 | + | return nil | |||
| 400 | + | } | |||
| 401 | + | ||||
| 364 | // ListContainers lists containers. | 402 | // ListContainers lists containers. | ||
| 365 | func (r *Runtime) ListContainers(ctx context.Context, all bool) ([]*domain.Container, error) { | 403 | func (r *Runtime) ListContainers(ctx context.Context, all bool) ([]*domain.Container, error) { | ||
| 366 | ctx = zerowrap.CtxWithFields(ctx, map[string]any{ | 404 | ctx = zerowrap.CtxWithFields(ctx, map[string]any{ | ||
A internal/adapters/out/docker/runtime_restart_policy_test.go +129 -0
| @@ -0,0 +1,129 @@ | |||
| 1 | + | package docker | |
| 2 | + | ||
| 3 | + | import ( | |
| 4 | + | "context" | |
| 5 | + | "encoding/json" | |
| 6 | + | "net/http" | |
| 7 | + | "net/http/httptest" | |
| 8 | + | "strings" | |
| 9 | + | "testing" | |
| 10 | + | ||
| 11 | + | "github.com/docker/docker/client" | |
| 12 | + | "github.com/stretchr/testify/assert" | |
| 13 | + | "github.com/stretchr/testify/require" | |
| 14 | + | ||
| 15 | + | "github.com/bnema/gordon/internal/domain" | |
| 16 | + | ) | |
| 17 | + | ||
| 18 | + | func TestRuntime_EnsureContainerRestartPolicy_SkipsWhenAlreadySet(t *testing.T) { | |
| 19 | + | var updateCalled bool | |
| 20 | + | server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
| 21 | + | switch { | |
| 22 | + | case r.Method == http.MethodGet && r.URL.Path == "/v1.41/containers/abc123/json": | |
| 23 | + | w.Header().Set("Content-Type", "application/json") | |
| 24 | + | _, _ = w.Write([]byte(`{ | |
| 25 | + | "Id": "abc123", | |
| 26 | + | "HostConfig": { | |
| 27 | + | "RestartPolicy": { | |
| 28 | + | "Name": "always" | |
| 29 | + | } | |
| 30 | + | } | |
| 31 | + | }`)) | |
| 32 | + | case r.Method == http.MethodPost && r.URL.Path == "/v1.41/containers/abc123/update": | |
| 33 | + | updateCalled = true | |
| 34 | + | w.WriteHeader(http.StatusInternalServerError) | |
| 35 | + | default: | |
| 36 | + | t.Fatalf("unexpected request: %s %s", r.Method, r.URL.Path) | |
| 37 | + | } | |
| 38 | + | })) | |
| 39 | + | defer server.Close() | |
| 40 | + | ||
| 41 | + | runtime := newRuntimeForRestartPolicyHTTPServer(t, server) | |
| 42 | + | err := runtime.EnsureContainerRestartPolicy(context.Background(), "abc123", domain.RestartPolicyAlways) | |
| 43 | + | require.NoError(t, err) | |
| 44 | + | assert.False(t, updateCalled, "update should not be called when restart policy is already set") | |
| 45 | + | } | |
| 46 | + | ||
| 47 | + | func TestRuntime_EnsureContainerRestartPolicy_UpdatesAndPreservesResources(t *testing.T) { | |
| 48 | + | var updateBody map[string]any | |
| 49 | + | server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
| 50 | + | switch { | |
| 51 | + | case r.Method == http.MethodGet && r.URL.Path == "/v1.41/containers/abc123/json": | |
| 52 | + | w.Header().Set("Content-Type", "application/json") | |
| 53 | + | _, _ = w.Write([]byte(`{ | |
| 54 | + | "Id": "abc123", | |
| 55 | + | "HostConfig": { | |
| 56 | + | "RestartPolicy": { | |
| 57 | + | "Name": "" | |
| 58 | + | }, | |
| 59 | + | "Memory": 268435456, | |
| 60 | + | "NanoCpus": 500000000, | |
| 61 | + | "PidsLimit": 128, | |
| 62 | + | "Ulimits": [ | |
| 63 | + | { | |
| 64 | + | "Name": "nofile", | |
| 65 | + | "Soft": 65536, | |
| 66 | + | "Hard": 65536 | |
| 67 | + | } | |
| 68 | + | ] | |
| 69 | + | } | |
| 70 | + | }`)) | |
| 71 | + | case r.Method == http.MethodPost && r.URL.Path == "/v1.41/containers/abc123/update": | |
| 72 | + | require.NoError(t, json.NewDecoder(r.Body).Decode(&updateBody)) | |
| 73 | + | w.Header().Set("Content-Type", "application/json") | |
| 74 | + | _, _ = w.Write([]byte(`{"Warnings":null}`)) | |
| 75 | + | default: | |
| 76 | + | t.Fatalf("unexpected request: %s %s", r.Method, r.URL.Path) | |
| 77 | + | } | |
| 78 | + | })) | |
| 79 | + | defer server.Close() | |
| 80 | + | ||
| 81 | + | runtime := newRuntimeForRestartPolicyHTTPServer(t, server) | |
| 82 | + | err := runtime.EnsureContainerRestartPolicy(context.Background(), "abc123", domain.RestartPolicyAlways) | |
| 83 | + | require.NoError(t, err) | |
| 84 | + | require.NotNil(t, updateBody) | |
| 85 | + | assert.Equal(t, domain.RestartPolicyAlways, updateBody["RestartPolicy"].(map[string]any)["Name"]) | |
| 86 | + | assert.Equal(t, float64(268435456), updateBody["Memory"]) | |
| 87 | + | assert.Equal(t, float64(500000000), updateBody["NanoCpus"]) | |
| 88 | + | assert.Equal(t, float64(128), updateBody["PidsLimit"]) | |
| 89 | + | ulimits, ok := updateBody["Ulimits"].([]any) | |
| 90 | + | require.True(t, ok, "Ulimits should be an array") | |
| 91 | + | require.Greater(t, len(ulimits), 0) | |
| 92 | + | firstUlimit, ok := ulimits[0].(map[string]any) | |
| 93 | + | require.True(t, ok, "first Ulimit should be a map") | |
| 94 | + | assert.Equal(t, "nofile", firstUlimit["Name"]) | |
| 95 | + | assert.Equal(t, float64(65536), firstUlimit["Soft"]) | |
| 96 | + | assert.Equal(t, float64(65536), firstUlimit["Hard"]) | |
| 97 | + | } | |
| 98 | + | ||
| 99 | + | func TestRuntime_EnsureContainerRestartPolicy_ReturnsErrorWhenHostConfigMissing(t *testing.T) { | |
| 100 | + | var updateCalled bool | |
| 101 | + | server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
| 102 | + | switch { | |
| 103 | + | case r.Method == http.MethodGet && r.URL.Path == "/v1.41/containers/abc123/json": | |
| 104 | + | w.Header().Set("Content-Type", "application/json") | |
| 105 | + | _, _ = w.Write([]byte(`{ | |
| 106 | + | "Id": "abc123" | |
| 107 | + | }`)) | |
| 108 | + | case r.Method == http.MethodPost && r.URL.Path == "/v1.41/containers/abc123/update": | |
| 109 | + | updateCalled = true | |
| 110 | + | w.WriteHeader(http.StatusInternalServerError) | |
| 111 | + | default: | |
| 112 | + | t.Fatalf("unexpected request: %s %s", r.Method, r.URL.Path) | |
| 113 | + | } | |
| 114 | + | })) | |
| 115 | + | defer server.Close() | |
| 116 | + | ||
| 117 | + | runtime := newRuntimeForRestartPolicyHTTPServer(t, server) | |
| 118 | + | err := runtime.EnsureContainerRestartPolicy(context.Background(), "abc123", domain.RestartPolicyAlways) | |
| 119 | + | require.Error(t, err) | |
| 120 | + | assert.Contains(t, err.Error(), "missing host config") | |
| 121 | + | assert.False(t, updateCalled, "update should not be called when host config is missing") | |
| 122 | + | } | |
| 123 | + | ||
| 124 | + | func newRuntimeForRestartPolicyHTTPServer(t *testing.T, server *httptest.Server) *Runtime { | |
| 125 | + | host := strings.TrimPrefix(server.URL, "http://") | |
| 126 | + | cli, err := client.NewClientWithOpts(client.WithHost("tcp://"+host), client.WithVersion("1.41"), client.WithHTTPClient(server.Client())) | |
| 127 | + | require.NoError(t, err) | |
| 128 | + | return NewRuntimeWithClient(cli) | |
| 129 | + | } | |
| @@ -0,0 +1,129 @@ | |||||
| 1 | + | package docker | |||
| 2 | + | ||||
| 3 | + | import ( | |||
| 4 | + | "context" | |||
| 5 | + | "encoding/json" | |||
| 6 | + | "net/http" | |||
| 7 | + | "net/http/httptest" | |||
| 8 | + | "strings" | |||
| 9 | + | "testing" | |||
| 10 | + | ||||
| 11 | + | "github.com/docker/docker/client" | |||
| 12 | + | "github.com/stretchr/testify/assert" | |||
| 13 | + | "github.com/stretchr/testify/require" | |||
| 14 | + | ||||
| 15 | + | "github.com/bnema/gordon/internal/domain" | |||
| 16 | + | ) | |||
| 17 | + | ||||
| 18 | + | func TestRuntime_EnsureContainerRestartPolicy_SkipsWhenAlreadySet(t *testing.T) { | |||
| 19 | + | var updateCalled bool | |||
| 20 | + | server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |||
| 21 | + | switch { | |||
| 22 | + | case r.Method == http.MethodGet && r.URL.Path == "/v1.41/containers/abc123/json": | |||
| 23 | + | w.Header().Set("Content-Type", "application/json") | |||
| 24 | + | _, _ = w.Write([]byte(`{ | |||
| 25 | + | "Id": "abc123", | |||
| 26 | + | "HostConfig": { | |||
| 27 | + | "RestartPolicy": { | |||
| 28 | + | "Name": "always" | |||
| 29 | + | } | |||
| 30 | + | } | |||
| 31 | + | }`)) | |||
| 32 | + | case r.Method == http.MethodPost && r.URL.Path == "/v1.41/containers/abc123/update": | |||
| 33 | + | updateCalled = true | |||
| 34 | + | w.WriteHeader(http.StatusInternalServerError) | |||
| 35 | + | default: | |||
| 36 | + | t.Fatalf("unexpected request: %s %s", r.Method, r.URL.Path) | |||
| 37 | + | } | |||
| 38 | + | })) | |||
| 39 | + | defer server.Close() | |||
| 40 | + | ||||
| 41 | + | runtime := newRuntimeForRestartPolicyHTTPServer(t, server) | |||
| 42 | + | err := runtime.EnsureContainerRestartPolicy(context.Background(), "abc123", domain.RestartPolicyAlways) | |||
| 43 | + | require.NoError(t, err) | |||
| 44 | + | assert.False(t, updateCalled, "update should not be called when restart policy is already set") | |||
| 45 | + | } | |||
| 46 | + | ||||
| 47 | + | func TestRuntime_EnsureContainerRestartPolicy_UpdatesAndPreservesResources(t *testing.T) { | |||
| 48 | + | var updateBody map[string]any | |||
| 49 | + | server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |||
| 50 | + | switch { | |||
| 51 | + | case r.Method == http.MethodGet && r.URL.Path == "/v1.41/containers/abc123/json": | |||
| 52 | + | w.Header().Set("Content-Type", "application/json") | |||
| 53 | + | _, _ = w.Write([]byte(`{ | |||
| 54 | + | "Id": "abc123", | |||
| 55 | + | "HostConfig": { | |||
| 56 | + | "RestartPolicy": { | |||
| 57 | + | "Name": "" | |||
| 58 | + | }, | |||
| 59 | + | "Memory": 268435456, | |||
| 60 | + | "NanoCpus": 500000000, | |||
| 61 | + | "PidsLimit": 128, | |||
| 62 | + | "Ulimits": [ | |||
| 63 | + | { | |||
| 64 | + | "Name": "nofile", | |||
| 65 | + | "Soft": 65536, | |||
| 66 | + | "Hard": 65536 | |||
| 67 | + | } | |||
| 68 | + | ] | |||
| 69 | + | } | |||
| 70 | + | }`)) | |||
| 71 | + | case r.Method == http.MethodPost && r.URL.Path == "/v1.41/containers/abc123/update": | |||
| 72 | + | require.NoError(t, json.NewDecoder(r.Body).Decode(&updateBody)) | |||
| 73 | + | w.Header().Set("Content-Type", "application/json") | |||
| 74 | + | _, _ = w.Write([]byte(`{"Warnings":null}`)) | |||
| 75 | + | default: | |||
| 76 | + | t.Fatalf("unexpected request: %s %s", r.Method, r.URL.Path) | |||
| 77 | + | } | |||
| 78 | + | })) | |||
| 79 | + | defer server.Close() | |||
| 80 | + | ||||
| 81 | + | runtime := newRuntimeForRestartPolicyHTTPServer(t, server) | |||
| 82 | + | err := runtime.EnsureContainerRestartPolicy(context.Background(), "abc123", domain.RestartPolicyAlways) | |||
| 83 | + | require.NoError(t, err) | |||
| 84 | + | require.NotNil(t, updateBody) | |||
| 85 | + | assert.Equal(t, domain.RestartPolicyAlways, updateBody["RestartPolicy"].(map[string]any)["Name"]) | |||
| 86 | + | assert.Equal(t, float64(268435456), updateBody["Memory"]) | |||
| 87 | + | assert.Equal(t, float64(500000000), updateBody["NanoCpus"]) | |||
| 88 | + | assert.Equal(t, float64(128), updateBody["PidsLimit"]) | |||
| 89 | + | ulimits, ok := updateBody["Ulimits"].([]any) | |||
| 90 | + | require.True(t, ok, "Ulimits should be an array") | |||
| 91 | + | require.Greater(t, len(ulimits), 0) | |||
| 92 | + | firstUlimit, ok := ulimits[0].(map[string]any) | |||
| 93 | + | require.True(t, ok, "first Ulimit should be a map") | |||
| 94 | + | assert.Equal(t, "nofile", firstUlimit["Name"]) | |||
| 95 | + | assert.Equal(t, float64(65536), firstUlimit["Soft"]) | |||
| 96 | + | assert.Equal(t, float64(65536), firstUlimit["Hard"]) | |||
| 97 | + | } | |||
| 98 | + | ||||
| 99 | + | func TestRuntime_EnsureContainerRestartPolicy_ReturnsErrorWhenHostConfigMissing(t *testing.T) { | |||
| 100 | + | var updateCalled bool | |||
| 101 | + | server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |||
| 102 | + | switch { | |||
| 103 | + | case r.Method == http.MethodGet && r.URL.Path == "/v1.41/containers/abc123/json": | |||
| 104 | + | w.Header().Set("Content-Type", "application/json") | |||
| 105 | + | _, _ = w.Write([]byte(`{ | |||
| 106 | + | "Id": "abc123" | |||
| 107 | + | }`)) | |||
| 108 | + | case r.Method == http.MethodPost && r.URL.Path == "/v1.41/containers/abc123/update": | |||
| 109 | + | updateCalled = true | |||
| 110 | + | w.WriteHeader(http.StatusInternalServerError) | |||
| 111 | + | default: | |||
| 112 | + | t.Fatalf("unexpected request: %s %s", r.Method, r.URL.Path) | |||
| 113 | + | } | |||
| 114 | + | })) | |||
| 115 | + | defer server.Close() | |||
| 116 | + | ||||
| 117 | + | runtime := newRuntimeForRestartPolicyHTTPServer(t, server) | |||
| 118 | + | err := runtime.EnsureContainerRestartPolicy(context.Background(), "abc123", domain.RestartPolicyAlways) | |||
| 119 | + | require.Error(t, err) | |||
| 120 | + | assert.Contains(t, err.Error(), "missing host config") | |||
| 121 | + | assert.False(t, updateCalled, "update should not be called when host config is missing") | |||
| 122 | + | } | |||
| 123 | + | ||||
| 124 | + | func newRuntimeForRestartPolicyHTTPServer(t *testing.T, server *httptest.Server) *Runtime { | |||
| 125 | + | host := strings.TrimPrefix(server.URL, "http://") | |||
| 126 | + | cli, err := client.NewClientWithOpts(client.WithHost("tcp://"+host), client.WithVersion("1.41"), client.WithHTTPClient(server.Client())) | |||
| 127 | + | require.NoError(t, err) | |||
| 128 | + | return NewRuntimeWithClient(cli) | |||
| 129 | + | } | |||
M internal/boundaries/out/mocks/mock_container_runtime.go +63 -0
| @@ -428,6 +428,69 @@ func (_c *MockContainerRuntime_DisconnectContainerFromNetwork_Call) RunAndReturn | |||
| 428 | 428 | return _c | |
| 429 | 429 | } | |
| 430 | 430 | ||
| 431 | + | // EnsureContainerRestartPolicy provides a mock function for the type MockContainerRuntime | |
| 432 | + | func (_mock *MockContainerRuntime) EnsureContainerRestartPolicy(ctx context.Context, containerID string, policy string) error { | |
| 433 | + | ret := _mock.Called(ctx, containerID, policy) | |
| 434 | + | ||
| 435 | + | if len(ret) == 0 { | |
| 436 | + | panic("no return value specified for EnsureContainerRestartPolicy") | |
| 437 | + | } | |
| 438 | + | ||
| 439 | + | var r0 error | |
| 440 | + | if returnFunc, ok := ret.Get(0).(func(context.Context, string, string) error); ok { | |
| 441 | + | r0 = returnFunc(ctx, containerID, policy) | |
| 442 | + | } else { | |
| 443 | + | r0 = ret.Error(0) | |
| 444 | + | } | |
| 445 | + | return r0 | |
| 446 | + | } | |
| 447 | + | ||
| 448 | + | // MockContainerRuntime_EnsureContainerRestartPolicy_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EnsureContainerRestartPolicy' | |
| 449 | + | type MockContainerRuntime_EnsureContainerRestartPolicy_Call struct { | |
| 450 | + | *mock.Call | |
| 451 | + | } | |
| 452 | + | ||
| 453 | + | // EnsureContainerRestartPolicy is a helper method to define mock.On call | |
| 454 | + | // - ctx context.Context | |
| 455 | + | // - containerID string | |
| 456 | + | // - policy string | |
| 457 | + | func (_e *MockContainerRuntime_Expecter) EnsureContainerRestartPolicy(ctx interface{}, containerID interface{}, policy interface{}) *MockContainerRuntime_EnsureContainerRestartPolicy_Call { | |
| 458 | + | return &MockContainerRuntime_EnsureContainerRestartPolicy_Call{Call: _e.mock.On("EnsureContainerRestartPolicy", ctx, containerID, policy)} | |
| 459 | + | } | |
| 460 | + | ||
| 461 | + | func (_c *MockContainerRuntime_EnsureContainerRestartPolicy_Call) Run(run func(ctx context.Context, containerID string, policy string)) *MockContainerRuntime_EnsureContainerRestartPolicy_Call { | |
| 462 | + | _c.Call.Run(func(args mock.Arguments) { | |
| 463 | + | var arg0 context.Context | |
| 464 | + | if args[0] != nil { | |
| 465 | + | arg0 = args[0].(context.Context) | |
| 466 | + | } | |
| 467 | + | var arg1 string | |
| 468 | + | if args[1] != nil { | |
| 469 | + | arg1 = args[1].(string) | |
| 470 | + | } | |
| 471 | + | var arg2 string | |
| 472 | + | if args[2] != nil { | |
| 473 | + | arg2 = args[2].(string) | |
| 474 | + | } | |
| 475 | + | run( | |
| 476 | + | arg0, | |
| 477 | + | arg1, | |
| 478 | + | arg2, | |
| 479 | + | ) | |
| 480 | + | }) | |
| 481 | + | return _c | |
| 482 | + | } | |
| 483 | + | ||
| 484 | + | func (_c *MockContainerRuntime_EnsureContainerRestartPolicy_Call) Return(err error) *MockContainerRuntime_EnsureContainerRestartPolicy_Call { | |
| 485 | + | _c.Call.Return(err) | |
| 486 | + | return _c | |
| 487 | + | } | |
| 488 | + | ||
| 489 | + | func (_c *MockContainerRuntime_EnsureContainerRestartPolicy_Call) RunAndReturn(run func(ctx context.Context, containerID string, policy string) error) *MockContainerRuntime_EnsureContainerRestartPolicy_Call { | |
| 490 | + | _c.Call.Return(run) | |
| 491 | + | return _c | |
| 492 | + | } | |
| 493 | + | ||
| 431 | 494 | // ExecInContainer provides a mock function for the type MockContainerRuntime | |
| 432 | 495 | func (_mock *MockContainerRuntime) ExecInContainer(ctx context.Context, containerID string, cmd []string) (*out.ExecResult, error) { | |
| 433 | 496 | ret := _mock.Called(ctx, containerID, cmd) | |
| @@ -428,6 +428,69 @@ func (_c *MockContainerRuntime_DisconnectContainerFromNetwork_Call) RunAndReturn | |||||
| 428 | return _c | 428 | return _c | ||
| 429 | } | 429 | } | ||
| 430 | 430 | ||||
| 431 | + | // EnsureContainerRestartPolicy provides a mock function for the type MockContainerRuntime | |||
| 432 | + | func (_mock *MockContainerRuntime) EnsureContainerRestartPolicy(ctx context.Context, containerID string, policy string) error { | |||
| 433 | + | ret := _mock.Called(ctx, containerID, policy) | |||
| 434 | + | ||||
| 435 | + | if len(ret) == 0 { | |||
| 436 | + | panic("no return value specified for EnsureContainerRestartPolicy") | |||
| 437 | + | } | |||
| 438 | + | ||||
| 439 | + | var r0 error | |||
| 440 | + | if returnFunc, ok := ret.Get(0).(func(context.Context, string, string) error); ok { | |||
| 441 | + | r0 = returnFunc(ctx, containerID, policy) | |||
| 442 | + | } else { | |||
| 443 | + | r0 = ret.Error(0) | |||
| 444 | + | } | |||
| 445 | + | return r0 | |||
| 446 | + | } | |||
| 447 | + | ||||
| 448 | + | // MockContainerRuntime_EnsureContainerRestartPolicy_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EnsureContainerRestartPolicy' | |||
| 449 | + | type MockContainerRuntime_EnsureContainerRestartPolicy_Call struct { | |||
| 450 | + | *mock.Call | |||
| 451 | + | } | |||
| 452 | + | ||||
| 453 | + | // EnsureContainerRestartPolicy is a helper method to define mock.On call | |||
| 454 | + | // - ctx context.Context | |||
| 455 | + | // - containerID string | |||
| 456 | + | // - policy string | |||
| 457 | + | func (_e *MockContainerRuntime_Expecter) EnsureContainerRestartPolicy(ctx interface{}, containerID interface{}, policy interface{}) *MockContainerRuntime_EnsureContainerRestartPolicy_Call { | |||
| 458 | + | return &MockContainerRuntime_EnsureContainerRestartPolicy_Call{Call: _e.mock.On("EnsureContainerRestartPolicy", ctx, containerID, policy)} | |||
| 459 | + | } | |||
| 460 | + | ||||
| 461 | + | func (_c *MockContainerRuntime_EnsureContainerRestartPolicy_Call) Run(run func(ctx context.Context, containerID string, policy string)) *MockContainerRuntime_EnsureContainerRestartPolicy_Call { | |||
| 462 | + | _c.Call.Run(func(args mock.Arguments) { | |||
| 463 | + | var arg0 context.Context | |||
| 464 | + | if args[0] != nil { | |||
| 465 | + | arg0 = args[0].(context.Context) | |||
| 466 | + | } | |||
| 467 | + | var arg1 string | |||
| 468 | + | if args[1] != nil { | |||
| 469 | + | arg1 = args[1].(string) | |||
| 470 | + | } | |||
| 471 | + | var arg2 string | |||
| 472 | + | if args[2] != nil { | |||
| 473 | + | arg2 = args[2].(string) | |||
| 474 | + | } | |||
| 475 | + | run( | |||
| 476 | + | arg0, | |||
| 477 | + | arg1, | |||
| 478 | + | arg2, | |||
| 479 | + | ) | |||
| 480 | + | }) | |||
| 481 | + | return _c | |||
| 482 | + | } | |||
| 483 | + | ||||
| 484 | + | func (_c *MockContainerRuntime_EnsureContainerRestartPolicy_Call) Return(err error) *MockContainerRuntime_EnsureContainerRestartPolicy_Call { | |||
| 485 | + | _c.Call.Return(err) | |||
| 486 | + | return _c | |||
| 487 | + | } | |||
| 488 | + | ||||
| 489 | + | func (_c *MockContainerRuntime_EnsureContainerRestartPolicy_Call) RunAndReturn(run func(ctx context.Context, containerID string, policy string) error) *MockContainerRuntime_EnsureContainerRestartPolicy_Call { | |||
| 490 | + | _c.Call.Return(run) | |||
| 491 | + | return _c | |||
| 492 | + | } | |||
| 493 | + | ||||
| 431 | // ExecInContainer provides a mock function for the type MockContainerRuntime | 494 | // ExecInContainer provides a mock function for the type MockContainerRuntime | ||
| 432 | func (_mock *MockContainerRuntime) ExecInContainer(ctx context.Context, containerID string, cmd []string) (*out.ExecResult, error) { | 495 | func (_mock *MockContainerRuntime) ExecInContainer(ctx context.Context, containerID string, cmd []string) (*out.ExecResult, error) { | ||
| 433 | ret := _mock.Called(ctx, containerID, cmd) | 496 | ret := _mock.Called(ctx, containerID, cmd) | ||
M internal/boundaries/out/runtime.go +1 -0
| @@ -20,6 +20,7 @@ type ContainerRuntime interface { | |||
| 20 | 20 | RestartContainer(ctx context.Context, containerID string) error | |
| 21 | 21 | RemoveContainer(ctx context.Context, containerID string, force bool) error | |
| 22 | 22 | RenameContainer(ctx context.Context, containerID, newName string) error | |
| 23 | + | EnsureContainerRestartPolicy(ctx context.Context, containerID, policy string) error | |
| 23 | 24 | ||
| 24 | 25 | // Container inspection | |
| 25 | 26 | ListContainers(ctx context.Context, all bool) ([]*domain.Container, error) | |
| @@ -20,6 +20,7 @@ type ContainerRuntime interface { | |||||
| 20 | RestartContainer(ctx context.Context, containerID string) error | 20 | RestartContainer(ctx context.Context, containerID string) error | ||
| 21 | RemoveContainer(ctx context.Context, containerID string, force bool) error | 21 | RemoveContainer(ctx context.Context, containerID string, force bool) error | ||
| 22 | RenameContainer(ctx context.Context, containerID, newName string) error | 22 | RenameContainer(ctx context.Context, containerID, newName string) error | ||
| 23 | + | EnsureContainerRestartPolicy(ctx context.Context, containerID, policy string) error | |||
| 23 | 24 | ||||
| 24 | // Container inspection | 25 | // Container inspection | ||
| 25 | ListContainers(ctx context.Context, all bool) ([]*domain.Container, error) | 26 | ListContainers(ctx context.Context, all bool) ([]*domain.Container, error) | ||