Skip to content

Commit a93f09e

Browse files
authored
Merge pull request docker#10210 from glours/dry-run-kill-support
Dry run kill support
2 parents bbf3ec1 + 982a8cc commit a93f09e

File tree

10 files changed

+77
-38
lines changed

10 files changed

+77
-38
lines changed

cmd/compose/compose.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,12 @@ func RootCommand(streams command.Cli, backend api.Service) *cobra.Command { //no
338338
if parallel > 0 {
339339
backend.MaxConcurrency(parallel)
340340
}
341-
return backend.DryRunMode(dryRun)
341+
ctx, err := backend.DryRunMode(cmd.Context(), dryRun)
342+
if err != nil {
343+
return err
344+
}
345+
cmd.SetContext(ctx)
346+
return nil
342347
},
343348
}
344349

pkg/api/api.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ type Service interface {
7878
// MaxConcurrency defines upper limit for concurrent operations against engine API
7979
MaxConcurrency(parallel int)
8080
// DryRunMode defines if dry run applies to the command
81-
DryRunMode(dryRun bool) error
81+
DryRunMode(ctx context.Context, dryRun bool) (context.Context, error)
8282
// Watch services' development context and sync/notify/rebuild/restart on changes
8383
Watch(ctx context.Context, project *types.Project, services []string, options WatchOptions) error
8484
}

pkg/api/dryrunclient.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ import (
3737

3838
var _ client.APIClient = &DryRunClient{}
3939

40+
type DryRunKey struct{}
41+
4042
// DryRunClient implements APIClient by delegating to implementation functions. This allows lazy init and per-method overrides
4143
type DryRunClient struct {
4244
apiClient client.APIClient
@@ -61,7 +63,7 @@ func (d *DryRunClient) ContainerCreate(ctx context.Context, config *containerTyp
6163
}
6264

6365
func (d *DryRunClient) ContainerKill(ctx context.Context, container, signal string) error {
64-
return ErrNotImplemented
66+
return nil
6567
}
6668

6769
func (d *DryRunClient) ContainerPause(ctx context.Context, container string) error {

pkg/api/proxy.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ type ServiceProxy struct {
5252
ImagesFn func(ctx context.Context, projectName string, options ImagesOptions) ([]ImageSummary, error)
5353
WatchFn func(ctx context.Context, project *types.Project, services []string, options WatchOptions) error
5454
MaxConcurrencyFn func(parallel int)
55-
DryRunModeFn func(dryRun bool) error
55+
DryRunModeFn func(ctx context.Context, dryRun bool) (context.Context, error)
5656
interceptors []Interceptor
5757
}
5858

@@ -327,6 +327,6 @@ func (s *ServiceProxy) MaxConcurrency(i int) {
327327
s.MaxConcurrencyFn(i)
328328
}
329329

330-
func (s *ServiceProxy) DryRunMode(dryRun bool) error {
331-
return s.DryRunModeFn(dryRun)
330+
func (s *ServiceProxy) DryRunMode(ctx context.Context, dryRun bool) (context.Context, error) {
331+
return s.DryRunModeFn(ctx, dryRun)
332332
}

pkg/compose/compose.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,22 +66,22 @@ func (s *composeService) MaxConcurrency(i int) {
6666
s.maxConcurrency = i
6767
}
6868

69-
func (s *composeService) DryRunMode(dryRun bool) error {
69+
func (s *composeService) DryRunMode(ctx context.Context, dryRun bool) (context.Context, error) {
7070
if dryRun {
7171
cli, err := command.NewDockerCli()
7272
if err != nil {
73-
return err
73+
return ctx, err
7474
}
7575
err = cli.Initialize(flags.NewClientOptions(), command.WithInitializeClient(func(cli *command.DockerCli) (client.APIClient, error) {
7676
dryRunClient := api.NewDryRunClient(s.apiClient())
7777
return dryRunClient, nil
7878
}))
7979
if err != nil {
80-
return err
80+
return ctx, err
8181
}
8282
s.dockerCli = cli
8383
}
84-
return nil
84+
return context.WithValue(ctx, api.DryRunKey{}, dryRun), nil
8585
}
8686

8787
func (s *composeService) stdout() *streams.Out {

pkg/mocks/mock_docker_compose_api.go

Lines changed: 7 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/progress/plain.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ import (
2323
)
2424

2525
type plainWriter struct {
26-
out io.Writer
27-
done chan bool
26+
out io.Writer
27+
done chan bool
28+
dryRun bool
2829
}
2930

3031
func (p *plainWriter) Start(ctx context.Context) error {
@@ -37,7 +38,11 @@ func (p *plainWriter) Start(ctx context.Context) error {
3738
}
3839

3940
func (p *plainWriter) Event(e Event) {
40-
fmt.Fprintln(p.out, e.ID, e.Text, e.StatusText)
41+
prefix := ""
42+
if p.dryRun {
43+
prefix = "DRY RUN MODE - "
44+
}
45+
fmt.Fprintln(p.out, prefix, e.ID, e.Text, e.StatusText)
4146
}
4247

4348
func (p *plainWriter) Events(events []Event) {
@@ -47,7 +52,11 @@ func (p *plainWriter) Events(events []Event) {
4752
}
4853

4954
func (p *plainWriter) TailMsgf(m string, args ...interface{}) {
50-
fmt.Fprintln(p.out, append([]interface{}{m}, args...)...)
55+
prefix := ""
56+
if p.dryRun {
57+
prefix = DRYRUN_PREFIX
58+
}
59+
fmt.Fprintln(p.out, append([]interface{}{prefix, m}, args...)...)
5160
}
5261

5362
func (p *plainWriter) Stop() {

pkg/progress/tty.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ type ttyWriter struct {
4040
done chan bool
4141
mtx *sync.Mutex
4242
tailEvents []string
43+
dryRun bool
4344
}
4445

4546
func (w *ttyWriter) Start(ctx context.Context) error {
@@ -107,7 +108,11 @@ func (w *ttyWriter) Events(events []Event) {
107108
func (w *ttyWriter) TailMsgf(msg string, args ...interface{}) {
108109
w.mtx.Lock()
109110
defer w.mtx.Unlock()
110-
w.tailEvents = append(w.tailEvents, fmt.Sprintf(msg, args...))
111+
msgWithPrefix := msg
112+
if w.dryRun {
113+
msgWithPrefix = strings.TrimSpace(DRYRUN_PREFIX + msg)
114+
}
115+
w.tailEvents = append(w.tailEvents, fmt.Sprintf(msgWithPrefix, args...))
111116
}
112117

113118
func (w *ttyWriter) printTailEvents() {
@@ -167,7 +172,7 @@ func (w *ttyWriter) print() { //nolint:gocyclo
167172
if event.ParentID != "" {
168173
continue
169174
}
170-
line := lineText(event, "", terminalWidth, statusPadding, runtime.GOOS != "windows")
175+
line := lineText(event, "", terminalWidth, statusPadding, runtime.GOOS != "windows", w.dryRun)
171176
fmt.Fprint(w.out, line)
172177
numLines++
173178
for _, v := range w.eventIDs {
@@ -176,7 +181,7 @@ func (w *ttyWriter) print() { //nolint:gocyclo
176181
if skipChildEvents {
177182
continue
178183
}
179-
line := lineText(ev, " ", terminalWidth, statusPadding, runtime.GOOS != "windows")
184+
line := lineText(ev, " ", terminalWidth, statusPadding, runtime.GOOS != "windows", w.dryRun)
180185
fmt.Fprint(w.out, line)
181186
numLines++
182187
}
@@ -191,14 +196,18 @@ func (w *ttyWriter) print() { //nolint:gocyclo
191196
w.numLines = numLines
192197
}
193198

194-
func lineText(event Event, pad string, terminalWidth, statusPadding int, color bool) string {
199+
func lineText(event Event, pad string, terminalWidth, statusPadding int, color bool, dryRun bool) string {
195200
endTime := time.Now()
196201
if event.Status != Working {
197202
endTime = event.startTime
198203
if (event.endTime != time.Time{}) {
199204
endTime = event.endTime
200205
}
201206
}
207+
prefix := ""
208+
if dryRun {
209+
prefix = DRYRUN_PREFIX
210+
}
202211

203212
elapsed := endTime.Sub(event.startTime).Seconds()
204213

@@ -215,9 +224,10 @@ func lineText(event Event, pad string, terminalWidth, statusPadding int, color b
215224
if maxStatusLen > 0 && len(status) > maxStatusLen {
216225
status = status[:maxStatusLen] + "..."
217226
}
218-
text := fmt.Sprintf("%s %s %s %s%s %s",
227+
text := fmt.Sprintf("%s %s%s %s %s%s %s",
219228
pad,
220229
event.spinner.String(),
230+
prefix,
221231
event.ID,
222232
event.Text,
223233
strings.Repeat(" ", padding),

pkg/progress/tty_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,22 @@ func TestLineText(t *testing.T) {
4141

4242
lineWidth := len(fmt.Sprintf("%s %s", ev.ID, ev.Text))
4343

44-
out := lineText(ev, "", 50, lineWidth, true)
44+
out := lineText(ev, "", 50, lineWidth, true, false)
4545
assert.Equal(t, out, "\x1b[37m . id Text Status 0.0s\n\x1b[0m")
4646

47-
out = lineText(ev, "", 50, lineWidth, false)
47+
out = lineText(ev, "", 50, lineWidth, false, false)
4848
assert.Equal(t, out, " . id Text Status 0.0s\n")
4949

5050
ev.Status = Done
51-
out = lineText(ev, "", 50, lineWidth, true)
51+
out = lineText(ev, "", 50, lineWidth, true, false)
5252
assert.Equal(t, out, "\x1b[34m . id Text Status 0.0s\n\x1b[0m")
5353

5454
ev.Status = Error
55-
out = lineText(ev, "", 50, lineWidth, true)
55+
out = lineText(ev, "", 50, lineWidth, true, false)
5656
assert.Equal(t, out, "\x1b[31m . id Text Status 0.0s\n\x1b[0m")
5757

5858
ev.Status = Warning
59-
out = lineText(ev, "", 50, lineWidth, true)
59+
out = lineText(ev, "", 50, lineWidth, true, false)
6060
assert.Equal(t, out, "\x1b[33m . id Text Status 0.0s\n\x1b[0m")
6161
}
6262

@@ -75,7 +75,7 @@ func TestLineTextSingleEvent(t *testing.T) {
7575

7676
lineWidth := len(fmt.Sprintf("%s %s", ev.ID, ev.Text))
7777

78-
out := lineText(ev, "", 50, lineWidth, true)
78+
out := lineText(ev, "", 50, lineWidth, true, false)
7979
assert.Equal(t, out, "\x1b[34m . id Text Status 0.0s\n\x1b[0m")
8080
}
8181

pkg/progress/writer.go

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,17 @@ import (
2121
"os"
2222
"sync"
2323

24+
"github.com/docker/compose/v2/pkg/api"
25+
2426
"github.com/containerd/console"
2527
"github.com/moby/term"
2628
"golang.org/x/sync/errgroup"
2729
)
2830

31+
const (
32+
DRYRUN_PREFIX = " DRY-RUN MODE - "
33+
)
34+
2935
// Writer can write multiple progress events
3036
type Writer interface {
3137
Start(context.Context) error
@@ -66,7 +72,7 @@ func Run(ctx context.Context, pf progressFunc) error {
6672
// RunWithStatus will run a writer and the progress function in parallel and return a status
6773
func RunWithStatus(ctx context.Context, pf progressFuncWithStatus) (string, error) {
6874
eg, _ := errgroup.WithContext(ctx)
69-
w, err := NewWriter(os.Stderr)
75+
w, err := NewWriter(ctx, os.Stderr)
7076
var result string
7177
if err != nil {
7278
return "", err
@@ -103,21 +109,26 @@ const (
103109
var Mode = ModeAuto
104110

105111
// NewWriter returns a new multi-progress writer
106-
func NewWriter(out console.File) (Writer, error) {
112+
func NewWriter(ctx context.Context, out console.File) (Writer, error) {
107113
_, isTerminal := term.GetFdInfo(out)
114+
dryRun, ok := ctx.Value(api.DryRunKey{}).(bool)
115+
if !ok {
116+
dryRun = false
117+
}
108118
if Mode == ModeAuto && isTerminal {
109-
return newTTYWriter(out)
119+
return newTTYWriter(out, dryRun)
110120
}
111121
if Mode == ModeTTY {
112-
return newTTYWriter(out)
122+
return newTTYWriter(out, dryRun)
113123
}
114124
return &plainWriter{
115-
out: out,
116-
done: make(chan bool),
125+
out: out,
126+
done: make(chan bool),
127+
dryRun: dryRun,
117128
}, nil
118129
}
119130

120-
func newTTYWriter(out console.File) (Writer, error) {
131+
func newTTYWriter(out console.File, dryRun bool) (Writer, error) {
121132
con, err := console.ConsoleFromFile(out)
122133
if err != nil {
123134
return nil, err
@@ -130,5 +141,6 @@ func newTTYWriter(out console.File) (Writer, error) {
130141
repeated: false,
131142
done: make(chan bool),
132143
mtx: &sync.Mutex{},
144+
dryRun: dryRun,
133145
}, nil
134146
}

0 commit comments

Comments
 (0)