Skip to content

Commit 8db0221

Browse files
committed
rm: clean up all nodes before returning errors
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
1 parent 4f6f49d commit 8db0221

2 files changed

Lines changed: 93 additions & 17 deletions

File tree

commands/rm.go

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package commands
22

33
import (
44
"context"
5+
stderrors "errors"
56
"fmt"
67
"time"
78

@@ -90,7 +91,7 @@ func runRm(ctx context.Context, dockerCli command.Cli, in rmOptions) error {
9091
return err
9192
}
9293

93-
err1 := rm(ctx, nodes, in)
94+
err1 := rm(timeoutCtx, nodes, in)
9495
if err := txn.Remove(b.Name); err != nil {
9596
return err
9697
}
@@ -140,24 +141,36 @@ func rmCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
140141
}
141142

142143
func rm(ctx context.Context, nodes []builder.Node, in rmOptions) (err error) {
144+
errCh := make(chan error, len(nodes)*3)
145+
var eg errgroup.Group
143146
for _, node := range nodes {
144-
if node.Driver == nil {
145-
continue
146-
}
147-
// Do not stop the buildkitd daemon when --keep-daemon is provided
148-
if !in.keepDaemon {
149-
if err := node.Driver.Stop(ctx, true); err != nil {
150-
return err
147+
eg.Go(func() error {
148+
if node.Err != nil {
149+
errCh <- errors.Wrapf(node.Err, "failed to load node %s", node.Name)
151150
}
152-
}
153-
if err := node.Driver.Rm(ctx, true, !in.keepState, !in.keepDaemon); err != nil {
154-
return err
155-
}
156-
if node.Err != nil {
157-
err = node.Err
158-
}
151+
if node.Driver == nil {
152+
return nil
153+
}
154+
// Do not stop the buildkitd daemon when --keep-daemon is provided
155+
if !in.keepDaemon {
156+
if err := node.Driver.Stop(ctx, true); err != nil {
157+
errCh <- errors.Wrapf(err, "failed to stop node %s", node.Name)
158+
}
159+
}
160+
if err := node.Driver.Rm(ctx, true, !in.keepState, !in.keepDaemon); err != nil {
161+
errCh <- errors.Wrapf(err, "failed to remove node %s", node.Name)
162+
}
163+
return nil
164+
})
165+
}
166+
_ = eg.Wait()
167+
close(errCh)
168+
169+
var errs []error
170+
for err := range errCh {
171+
errs = append(errs, err)
159172
}
160-
return err
173+
return stderrors.Join(errs...)
161174
}
162175

163176
func rmAllInactive(ctx context.Context, txn *store.Txn, dockerCli command.Cli, in rmOptions) error {
@@ -187,7 +200,7 @@ func rmAllInactive(ctx context.Context, txn *store.Txn, dockerCli command.Cli, i
187200
return nil
188201
}
189202
if b.Inactive() {
190-
rmerr := rm(ctx, nodes, in)
203+
rmerr := rm(timeoutCtx, nodes, in)
191204
if err := txn.Remove(b.Name); err != nil {
192205
return err
193206
}

tests/rm.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/docker/buildx/driver"
99
"github.com/docker/buildx/store"
1010
"github.com/docker/buildx/util/confutil"
11+
"github.com/moby/buildkit/identity"
1112
"github.com/moby/buildkit/util/testutil/integration"
1213
"github.com/pkg/errors"
1314
"github.com/stretchr/testify/require"
@@ -25,6 +26,8 @@ var rmTests = []func(t *testing.T, sb integration.Sandbox){
2526
testRmMulti,
2627
testRmInvalidBuildkitdConfig,
2728
testRmAllInactiveInvalidBuildkitdConfig,
29+
testRmUnreachableEndpoint,
30+
testRmUnreachableRemoteEndpoint,
2831
}
2932

3033
func testRm(t *testing.T, sb integration.Sandbox) {
@@ -34,6 +37,7 @@ func testRm(t *testing.T, sb integration.Sandbox) {
3437

3538
out, err := rmCmd(sb, withArgs("default"))
3639
require.Error(t, err, out) // can't remove a docker builder
40+
require.Contains(t, out, "context builder cannot be removed")
3741

3842
out, err = createCmd(sb, withArgs("--driver", "docker-container"))
3943
require.NoError(t, err, out)
@@ -155,6 +159,65 @@ func testRmAllInactiveInvalidBuildkitdConfig(t *testing.T, sb integration.Sandbo
155159
builderName = ""
156160
}
157161

162+
func testRmUnreachableEndpoint(t *testing.T, sb integration.Sandbox) {
163+
if !isDockerContainerWorker(sb) {
164+
t.Skip("only testing with docker-container worker")
165+
}
166+
167+
out, err := createCmd(sb, withArgs("--driver", "docker-container"))
168+
require.NoError(t, err, out)
169+
builderName := strings.TrimSpace(out)
170+
171+
out, err = inspectCmd(sb, withArgs(builderName, "--bootstrap"))
172+
require.NoError(t, err, out)
173+
174+
t.Cleanup(func() {
175+
if builderName == "" {
176+
return
177+
}
178+
_, _ = rmCmd(sb, withArgs("--keep-daemon", builderName))
179+
})
180+
181+
var goodContainer string
182+
updateStoredBuilder(t, sb, builderName, func(ng *store.NodeGroup) {
183+
require.NotEmpty(t, ng.Nodes)
184+
goodContainer = driver.BuilderName(ng.Nodes[0].Name)
185+
badNode := ng.Nodes[0]
186+
badNode.Name += "-unreachable"
187+
badNode.Endpoint = "tcp://127.0.0.1:1"
188+
ng.Nodes = append([]store.Node{badNode}, ng.Nodes...)
189+
})
190+
191+
out, err = rmCmd(sb, withArgs("--timeout=2s", builderName))
192+
require.Error(t, err, out)
193+
require.Contains(t, out, "failed to remove "+builderName)
194+
requireNoStoredBuilder(t, sb, builderName)
195+
requireNoContainer(t, sb, goodContainer)
196+
builderName = ""
197+
}
198+
199+
func testRmUnreachableRemoteEndpoint(t *testing.T, sb integration.Sandbox) {
200+
if !isRemoteWorker(sb) || isRemoteMultiNodeWorker(sb) {
201+
t.Skip("only testing with remote worker")
202+
}
203+
204+
builderName := "remote-" + identity.NewID()
205+
out, err := createCmd(sb, withArgs("--driver", "remote", "--name", builderName, "--timeout=2s", "tcp://127.0.0.1:1"))
206+
require.NoError(t, err, out)
207+
208+
t.Cleanup(func() {
209+
if builderName != "" {
210+
_, _ = rmCmd(sb, withArgs("--timeout=2s", builderName))
211+
}
212+
})
213+
214+
out, err = rmCmd(sb, withArgs("--timeout=2s", builderName))
215+
require.NoError(t, err, out)
216+
require.Contains(t, out, builderName+" removed")
217+
requireNoStoredBuilder(t, sb, builderName)
218+
builderName = ""
219+
}
220+
158221
func updateStoredBuilder(t *testing.T, sb integration.Sandbox, name string, fn func(*store.NodeGroup)) {
159222
t.Helper()
160223

0 commit comments

Comments
 (0)