mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-03 17:43:42 +08:00 
			
		
		
		
	Merge pull request #885 from crazy-max/rm-inactive
cli: add --all-inactive for rm command
This commit is contained in:
		@@ -2,36 +2,53 @@ package commands
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/buildx/store"
 | 
			
		||||
	"github.com/docker/buildx/store/storeutil"
 | 
			
		||||
	"github.com/docker/cli/cli"
 | 
			
		||||
	"github.com/docker/cli/cli/command"
 | 
			
		||||
	"github.com/moby/buildkit/util/appcontext"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"golang.org/x/sync/errgroup"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type rmOptions struct {
 | 
			
		||||
	builder    string
 | 
			
		||||
	keepState  bool
 | 
			
		||||
	keepDaemon bool
 | 
			
		||||
	builder     string
 | 
			
		||||
	keepState   bool
 | 
			
		||||
	keepDaemon  bool
 | 
			
		||||
	allInactive bool
 | 
			
		||||
	force       bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	rmInactiveWarning = `WARNING! This will remove all builders that are not in running state. Are you sure you want to continue?`
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func runRm(dockerCli command.Cli, in rmOptions) error {
 | 
			
		||||
	ctx := appcontext.Context()
 | 
			
		||||
 | 
			
		||||
	if in.allInactive && !in.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), rmInactiveWarning) {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	txn, release, err := storeutil.GetStore(dockerCli)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer release()
 | 
			
		||||
 | 
			
		||||
	if in.allInactive {
 | 
			
		||||
		return rmAllInactive(ctx, txn, dockerCli, in)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if in.builder != "" {
 | 
			
		||||
		ng, err := storeutil.GetNodeGroup(txn, dockerCli, in.builder)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		err1 := rm(ctx, dockerCli, ng, in.keepState, in.keepDaemon)
 | 
			
		||||
		err1 := rm(ctx, dockerCli, in, ng)
 | 
			
		||||
		if err := txn.Remove(ng.Name); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
@@ -43,7 +60,7 @@ func runRm(dockerCli command.Cli, in rmOptions) error {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if ng != nil {
 | 
			
		||||
		err1 := rm(ctx, dockerCli, ng, in.keepState, in.keepDaemon)
 | 
			
		||||
		err1 := rm(ctx, dockerCli, in, ng)
 | 
			
		||||
		if err := txn.Remove(ng.Name); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
@@ -63,6 +80,9 @@ func rmCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
 | 
			
		||||
		RunE: func(cmd *cobra.Command, args []string) error {
 | 
			
		||||
			options.builder = rootOpts.builder
 | 
			
		||||
			if len(args) > 0 {
 | 
			
		||||
				if options.allInactive {
 | 
			
		||||
					return errors.New("cannot specify builder name when --all-inactive is set")
 | 
			
		||||
				}
 | 
			
		||||
				options.builder = args[0]
 | 
			
		||||
			}
 | 
			
		||||
			return runRm(dockerCli, options)
 | 
			
		||||
@@ -72,11 +92,13 @@ func rmCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
 | 
			
		||||
	flags := cmd.Flags()
 | 
			
		||||
	flags.BoolVar(&options.keepState, "keep-state", false, "Keep BuildKit state")
 | 
			
		||||
	flags.BoolVar(&options.keepDaemon, "keep-daemon", false, "Keep the buildkitd daemon running")
 | 
			
		||||
	flags.BoolVar(&options.allInactive, "all-inactive", false, "Remove all inactive builders")
 | 
			
		||||
	flags.BoolVarP(&options.force, "force", "f", false, "Do not prompt for confirmation")
 | 
			
		||||
 | 
			
		||||
	return cmd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func rm(ctx context.Context, dockerCli command.Cli, ng *store.NodeGroup, keepState, keepDaemon bool) error {
 | 
			
		||||
func rm(ctx context.Context, dockerCli command.Cli, in rmOptions, ng *store.NodeGroup) error {
 | 
			
		||||
	dis, err := driversForNodeGroup(ctx, dockerCli, ng, "")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
@@ -86,12 +108,12 @@ func rm(ctx context.Context, dockerCli command.Cli, ng *store.NodeGroup, keepSta
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		// Do not stop the buildkitd daemon when --keep-daemon is provided
 | 
			
		||||
		if !keepDaemon {
 | 
			
		||||
		if !in.keepDaemon {
 | 
			
		||||
			if err := di.Driver.Stop(ctx, true); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if err := di.Driver.Rm(ctx, true, !keepState, !keepDaemon); err != nil {
 | 
			
		||||
		if err := di.Driver.Rm(ctx, true, !in.keepState, !in.keepDaemon); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if di.Err != nil {
 | 
			
		||||
@@ -100,3 +122,42 @@ func rm(ctx context.Context, dockerCli command.Cli, ng *store.NodeGroup, keepSta
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func rmAllInactive(ctx context.Context, txn *store.Txn, dockerCli command.Cli, in rmOptions) error {
 | 
			
		||||
	ctx, cancel := context.WithTimeout(ctx, 20*time.Second)
 | 
			
		||||
	defer cancel()
 | 
			
		||||
 | 
			
		||||
	ll, err := txn.List()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	builders := make([]*nginfo, len(ll))
 | 
			
		||||
	for i, ng := range ll {
 | 
			
		||||
		builders[i] = &nginfo{ng: ng}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	eg, _ := errgroup.WithContext(ctx)
 | 
			
		||||
	for _, b := range builders {
 | 
			
		||||
		func(b *nginfo) {
 | 
			
		||||
			eg.Go(func() error {
 | 
			
		||||
				if err := loadNodeGroupData(ctx, dockerCli, b); err != nil {
 | 
			
		||||
					return errors.Wrapf(err, "cannot load %s", b.ng.Name)
 | 
			
		||||
				}
 | 
			
		||||
				if b.ng.Dynamic {
 | 
			
		||||
					return nil
 | 
			
		||||
				}
 | 
			
		||||
				if b.inactive() {
 | 
			
		||||
					rmerr := rm(ctx, dockerCli, in, b.ng)
 | 
			
		||||
					if err := txn.Remove(b.ng.Name); err != nil {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
					return rmerr
 | 
			
		||||
				}
 | 
			
		||||
				return nil
 | 
			
		||||
			})
 | 
			
		||||
		}(b)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return eg.Wait()
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -389,6 +389,17 @@ type nginfo struct {
 | 
			
		||||
	err     error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// inactive checks if all nodes are inactive for this builder
 | 
			
		||||
func (n *nginfo) inactive() bool {
 | 
			
		||||
	for idx := range n.ng.Nodes {
 | 
			
		||||
		d := n.drivers[idx]
 | 
			
		||||
		if d.info != nil && d.info.Status == driver.Running {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func boot(ctx context.Context, ngi *nginfo) (bool, error) {
 | 
			
		||||
	toBoot := make([]int, 0, len(ngi.drivers))
 | 
			
		||||
	for i, d := range ngi.drivers {
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,9 @@ Remove a builder instance
 | 
			
		||||
 | 
			
		||||
| Name | Description |
 | 
			
		||||
| --- | --- |
 | 
			
		||||
| [`--all-inactive`](#all-inactive) | Remove all inactive builders |
 | 
			
		||||
| [`--builder string`](#builder) | Override the configured builder instance |
 | 
			
		||||
| [`-f`](#force), [`--force`](#force) | Do not prompt for confirmation |
 | 
			
		||||
| [`--keep-daemon`](#keep-daemon) | Keep the buildkitd daemon running |
 | 
			
		||||
| [`--keep-state`](#keep-state) | Keep BuildKit state |
 | 
			
		||||
 | 
			
		||||
@@ -25,16 +27,33 @@ default builder.
 | 
			
		||||
 | 
			
		||||
## Examples
 | 
			
		||||
 | 
			
		||||
### <a name="all-inactive"></a> Remove all inactive builders (--all-inactive)
 | 
			
		||||
 | 
			
		||||
Remove builders that are not in running state.
 | 
			
		||||
 | 
			
		||||
```console
 | 
			
		||||
$ docker buildx rm --all-inactive
 | 
			
		||||
WARNING! This will remove all builders that are not in running state. Are you sure you want to continue? [y/N] y
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### <a name="builder"></a> Override the configured builder instance (--builder)
 | 
			
		||||
 | 
			
		||||
Same as [`buildx --builder`](buildx.md#builder).
 | 
			
		||||
 | 
			
		||||
### <a name="keep-state"></a> Keep BuildKit state (--keep-state)
 | 
			
		||||
### <a name="force"></a> Do not prompt for confirmation (--force)
 | 
			
		||||
 | 
			
		||||
Keep BuildKit state, so it can be reused by a new builder with the same name.
 | 
			
		||||
Currently, only supported by the [`docker-container` driver](buildx_create.md#driver).
 | 
			
		||||
Do not prompt for confirmation before removing inactive builders.
 | 
			
		||||
 | 
			
		||||
```console
 | 
			
		||||
$ docker buildx rm --all-inactive --force
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### <a name="keep-daemon"></a> Keep the buildkitd daemon running (--keep-daemon)
 | 
			
		||||
 | 
			
		||||
Keep the buildkitd daemon running after the buildx context is removed. This is useful when you manage buildkitd daemons and buildx contexts independently.
 | 
			
		||||
Currently, only supported by the [`docker-container` and `kubernetes` drivers](buildx_create.md#driver).
 | 
			
		||||
 | 
			
		||||
### <a name="keep-state"></a> Keep BuildKit state (--keep-state)
 | 
			
		||||
 | 
			
		||||
Keep BuildKit state, so it can be reused by a new builder with the same name.
 | 
			
		||||
Currently, only supported by the [`docker-container` driver](buildx_create.md#driver).
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user