@@ -23,7 +23,9 @@ import (
23
23
"net"
24
24
"net/http"
25
25
"strings"
26
+ "sync"
26
27
28
+ "github.com/distribution/distribution/v3/uuid"
27
29
moby "github.com/docker/docker/api/types"
28
30
containerType "github.com/docker/docker/api/types/container"
29
31
"github.com/docker/docker/api/types/events"
@@ -35,6 +37,7 @@ import (
35
37
"github.com/docker/docker/api/types/volume"
36
38
"github.com/docker/docker/client"
37
39
specs "github.com/opencontainers/image-spec/specs-go/v1"
40
+ "github.com/pkg/errors"
38
41
)
39
42
40
43
const (
@@ -48,12 +51,19 @@ type DryRunKey struct{}
48
51
// DryRunClient implements APIClient by delegating to implementation functions. This allows lazy init and per-method overrides
49
52
type DryRunClient struct {
50
53
apiClient client.APIClient
54
+ execs sync.Map
55
+ }
56
+
57
+ type execDetails struct {
58
+ container string
59
+ command []string
51
60
}
52
61
53
62
// NewDryRunClient produces a DryRunClient
54
63
func NewDryRunClient (apiClient client.APIClient ) * DryRunClient {
55
64
return & DryRunClient {
56
65
apiClient : apiClient ,
66
+ execs : sync.Map {},
57
67
}
58
68
}
59
69
@@ -155,6 +165,27 @@ func (d *DryRunClient) VolumeRemove(ctx context.Context, volumeID string, force
155
165
return ErrNotImplemented
156
166
}
157
167
168
+ func (d * DryRunClient ) ContainerExecCreate (ctx context.Context , container string , config moby.ExecConfig ) (moby.IDResponse , error ) {
169
+ id := uuid .Generate ().String ()
170
+ d .execs .Store (id , execDetails {
171
+ container : container ,
172
+ command : config .Cmd ,
173
+ })
174
+ return moby.IDResponse {
175
+ ID : id ,
176
+ }, nil
177
+ }
178
+
179
+ func (d * DryRunClient ) ContainerExecStart (ctx context.Context , execID string , config moby.ExecStartCheck ) error {
180
+ v , ok := d .execs .LoadAndDelete (execID )
181
+ if ! ok {
182
+ return fmt .Errorf ("invalid exec ID %q" , execID )
183
+ }
184
+ details := v .(execDetails )
185
+ fmt .Printf ("%sExecuting command %q in %s (detached mode)\n " , DRYRUN_PREFIX , details .command , details .container )
186
+ return nil
187
+ }
188
+
158
189
// Functions delegated to original APIClient (not used by Compose or not modifying the Compose stack
159
190
160
191
func (d * DryRunClient ) ConfigList (ctx context.Context , options moby.ConfigListOptions ) ([]swarm.Config , error ) {
@@ -186,11 +217,7 @@ func (d *DryRunClient) ContainerDiff(ctx context.Context, container string) ([]c
186
217
}
187
218
188
219
func (d * DryRunClient ) ContainerExecAttach (ctx context.Context , execID string , config moby.ExecStartCheck ) (moby.HijackedResponse , error ) {
189
- return d .apiClient .ContainerExecAttach (ctx , execID , config )
190
- }
191
-
192
- func (d * DryRunClient ) ContainerExecCreate (ctx context.Context , container string , config moby.ExecConfig ) (moby.IDResponse , error ) {
193
- return d .apiClient .ContainerExecCreate (ctx , container , config )
220
+ return moby.HijackedResponse {}, errors .New ("interactive exec is not supported in dry-run mode" )
194
221
}
195
222
196
223
func (d * DryRunClient ) ContainerExecInspect (ctx context.Context , execID string ) (moby.ContainerExecInspect , error ) {
@@ -201,10 +228,6 @@ func (d *DryRunClient) ContainerExecResize(ctx context.Context, execID string, o
201
228
return d .apiClient .ContainerExecResize (ctx , execID , options )
202
229
}
203
230
204
- func (d * DryRunClient ) ContainerExecStart (ctx context.Context , execID string , config moby.ExecStartCheck ) error {
205
- return d .apiClient .ContainerExecStart (ctx , execID , config )
206
- }
207
-
208
231
func (d * DryRunClient ) ContainerExport (ctx context.Context , container string ) (io.ReadCloser , error ) {
209
232
return d .apiClient .ContainerExport (ctx , container )
210
233
}
0 commit comments