mirror of https://github.com/docker/compose.git
commit
6b435cf802
|
@ -45,7 +45,7 @@ COPY --from=make-cli /api/bin/* .
|
||||||
FROM scratch AS cross
|
FROM scratch AS cross
|
||||||
COPY --from=make-cross /api/bin/* .
|
COPY --from=make-cross /api/bin/* .
|
||||||
|
|
||||||
FROM make-protos as test
|
FROM fs as test
|
||||||
RUN make -f builder.Makefile test
|
RUN make -f builder.Makefile test
|
||||||
|
|
||||||
FROM fs AS lint
|
FROM fs AS lint
|
||||||
|
|
|
@ -33,12 +33,12 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
"github.com/hashicorp/go-multierror"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
cliconfig "github.com/docker/api/cli/config"
|
cliconfig "github.com/docker/api/cli/config"
|
||||||
cliopts "github.com/docker/api/cli/options"
|
cliopts "github.com/docker/api/cli/options"
|
||||||
"github.com/docker/api/context/store"
|
"github.com/docker/api/context/store"
|
||||||
|
"github.com/docker/api/multierror"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ContextCommand manages contexts
|
// ContextCommand manages contexts
|
||||||
|
|
|
@ -2,12 +2,12 @@ package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/docker/api/client"
|
"github.com/docker/api/client"
|
||||||
|
"github.com/docker/api/multierror"
|
||||||
)
|
)
|
||||||
|
|
||||||
type rmOpts struct {
|
type rmOpts struct {
|
||||||
|
@ -23,26 +23,22 @@ func RmCommand() *cobra.Command {
|
||||||
Short: "Remove containers",
|
Short: "Remove containers",
|
||||||
Args: cobra.MinimumNArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
var errs []string
|
|
||||||
c, err := client.New(cmd.Context())
|
c, err := client.New(cmd.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "cannot connect to backend")
|
return errors.Wrap(err, "cannot connect to backend")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var errs *multierror.Error
|
||||||
for _, id := range args {
|
for _, id := range args {
|
||||||
err := c.ContainerService().Delete(cmd.Context(), id, opts.force)
|
err := c.ContainerService().Delete(cmd.Context(), id, opts.force)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = append(errs, err.Error()+" "+id)
|
errs = multierror.Append(errs, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fmt.Println(id)
|
fmt.Println(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(errs) > 0 {
|
return errs.ErrorOrNil()
|
||||||
return errors.New(strings.Join(errs, "\n"))
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,10 +7,12 @@ import (
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/docker/api/backend"
|
"github.com/docker/api/backend"
|
||||||
"github.com/docker/api/compose"
|
"github.com/docker/api/compose"
|
||||||
"github.com/docker/api/containers"
|
"github.com/docker/api/containers"
|
||||||
|
"github.com/docker/api/errdefs"
|
||||||
)
|
)
|
||||||
|
|
||||||
type mobyService struct {
|
type mobyService struct {
|
||||||
|
@ -127,7 +129,11 @@ func (ms *mobyService) Logs(ctx context.Context, containerName string, request c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ms *mobyService) Delete(ctx context.Context, containerID string, force bool) error {
|
func (ms *mobyService) Delete(ctx context.Context, containerID string, force bool) error {
|
||||||
return ms.apiClient.ContainerRemove(ctx, containerID, types.ContainerRemoveOptions{
|
err := ms.apiClient.ContainerRemove(ctx, containerID, types.ContainerRemoveOptions{
|
||||||
Force: force,
|
Force: force,
|
||||||
})
|
})
|
||||||
|
if client.IsErrNotFound(err) {
|
||||||
|
return errors.Wrapf(errdefs.ErrNotFound, "container %q", containerID)
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
package multierror
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-multierror"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Error wraps a multierror.Error and defines a default
|
||||||
|
// formatting function that fits cli needs
|
||||||
|
type Error struct {
|
||||||
|
err *multierror.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Error) Error() string {
|
||||||
|
if e == nil || e.err == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
e.err.ErrorFormat = listErrorFunc
|
||||||
|
return e.err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrappedErrors returns the list of errors that this Error is wrapping.
|
||||||
|
// It is an implementation of the errwrap.Wrapper interface so that
|
||||||
|
// multierror.Error can be used with that library.
|
||||||
|
//
|
||||||
|
// This method is not safe to be called concurrently and is no different
|
||||||
|
// than accessing the Errors field directly. It is implemented only to
|
||||||
|
// satisfy the errwrap.Wrapper interface.
|
||||||
|
func (e *Error) WrappedErrors() []error {
|
||||||
|
return e.err.WrappedErrors()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unwrap returns an error from Error (or nil if there are no errors)
|
||||||
|
func (e *Error) Unwrap() error {
|
||||||
|
if e == nil || e.err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return e.err.Unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorOrNil returns an error interface if this Error represents
|
||||||
|
// a list of errors, or returns nil if the list of errors is empty. This
|
||||||
|
// function is useful at the end of accumulation to make sure that the value
|
||||||
|
// returned represents the existence of errors.
|
||||||
|
func (e *Error) ErrorOrNil() error {
|
||||||
|
if e == nil || e.err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if len(e.err.Errors) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append adds an error to a multierror, if err is
|
||||||
|
// not a multierror it will be converted to one
|
||||||
|
func Append(err error, errs ...error) *Error {
|
||||||
|
switch err := err.(type) {
|
||||||
|
case *Error:
|
||||||
|
if err == nil {
|
||||||
|
err = new(Error)
|
||||||
|
}
|
||||||
|
for _, e := range errs {
|
||||||
|
err.err = multierror.Append(err.err, e)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
default:
|
||||||
|
newErrs := make([]error, 0, len(errs)+1)
|
||||||
|
if err != nil {
|
||||||
|
newErrs = append(newErrs, err)
|
||||||
|
}
|
||||||
|
newErrs = append(newErrs, errs...)
|
||||||
|
|
||||||
|
return Append(&Error{}, newErrs...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func listErrorFunc(errs []error) string {
|
||||||
|
if len(errs) == 1 {
|
||||||
|
return errs[0].Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
messages := make([]string, len(errs))
|
||||||
|
|
||||||
|
for i, err := range errs {
|
||||||
|
messages[i] = "Error: " + err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(messages, "\n")
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package multierror
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSingleError(t *testing.T) {
|
||||||
|
var err *Error
|
||||||
|
err = Append(err, errors.New("error"))
|
||||||
|
assert.Equal(t, 1, len(err.WrappedErrors()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGoError(t *testing.T) {
|
||||||
|
var err error
|
||||||
|
result := Append(err, errors.New("error"))
|
||||||
|
assert.Equal(t, 1, len(result.WrappedErrors()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMultiError(t *testing.T) {
|
||||||
|
var err *Error
|
||||||
|
err = Append(err,
|
||||||
|
errors.New("first"),
|
||||||
|
errors.New("second"),
|
||||||
|
)
|
||||||
|
assert.Equal(t, 2, len(err.WrappedErrors()))
|
||||||
|
assert.Equal(t, "Error: first\nError: second", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnwrap(t *testing.T) {
|
||||||
|
var err *Error
|
||||||
|
assert.Equal(t, nil, errors.Unwrap(err))
|
||||||
|
|
||||||
|
err = Append(err, errors.New("first"))
|
||||||
|
e := errors.Unwrap(err)
|
||||||
|
assert.Equal(t, "first", e.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestErrorOrNil(t *testing.T) {
|
||||||
|
var err *Error
|
||||||
|
assert.Equal(t, nil, err.ErrorOrNil())
|
||||||
|
|
||||||
|
err = Append(err, errors.New("error"))
|
||||||
|
e := err.ErrorOrNil()
|
||||||
|
assert.Equal(t, "error", e.Error())
|
||||||
|
}
|
Loading…
Reference in New Issue