diff --git a/aci/compose.go b/aci/compose.go index f004ddbd7..183b2080d 100644 --- a/aci/compose.go +++ b/aci/compose.go @@ -48,7 +48,7 @@ func (cs *aciComposeService) Build(ctx context.Context, project *types.Project, return errdefs.ErrNotImplemented } -func (cs *aciComposeService) Push(ctx context.Context, project *types.Project) error { +func (cs *aciComposeService) Push(ctx context.Context, project *types.Project, options compose.PushOptions) error { return errdefs.ErrNotImplemented } diff --git a/api/client/compose.go b/api/client/compose.go index f68378b8c..1e8b23987 100644 --- a/api/client/compose.go +++ b/api/client/compose.go @@ -32,7 +32,7 @@ func (c *composeService) Build(ctx context.Context, project *types.Project, opti return errdefs.ErrNotImplemented } -func (c *composeService) Push(ctx context.Context, project *types.Project) error { +func (c *composeService) Push(ctx context.Context, project *types.Project, options compose.PushOptions) error { return errdefs.ErrNotImplemented } diff --git a/api/compose/api.go b/api/compose/api.go index 02d2ef31d..9803d9daa 100644 --- a/api/compose/api.go +++ b/api/compose/api.go @@ -30,7 +30,7 @@ type Service interface { // Build executes the equivalent to a `compose build` Build(ctx context.Context, project *types.Project, options BuildOptions) error // Push executes the equivalent ot a `compose push` - Push(ctx context.Context, project *types.Project) error + Push(ctx context.Context, project *types.Project, options PushOptions) error // Pull executes the equivalent of a `compose pull` Pull(ctx context.Context, project *types.Project) error // Create executes the equivalent to a `compose create` @@ -133,6 +133,11 @@ type ConvertOptions struct { Output string } +// PushOptions group options of the Push API +type PushOptions struct { + IgnoreFailures bool +} + // KillOptions group options of the Kill API type KillOptions struct { // Signal to send to containers diff --git a/cli/cmd/compose/push.go b/cli/cmd/compose/push.go index 407f88364..21c6f1ee1 100644 --- a/cli/cmd/compose/push.go +++ b/cli/cmd/compose/push.go @@ -22,12 +22,15 @@ import ( "github.com/spf13/cobra" "github.com/docker/compose-cli/api/client" + "github.com/docker/compose-cli/api/compose" "github.com/docker/compose-cli/api/progress" ) type pushOptions struct { *projectOptions composeOptions + + Ignorefailures bool } func pushCommand(p *projectOptions) *cobra.Command { @@ -41,6 +44,8 @@ func pushCommand(p *projectOptions) *cobra.Command { return runPush(cmd.Context(), opts, args) }, } + pushCmd.Flags().BoolVar(&opts.Ignorefailures, "ignore-push-failures", false, "Push what it can and ignores images with push failures") + return pushCmd } @@ -56,7 +61,9 @@ func runPush(ctx context.Context, opts pushOptions, services []string) error { } _, err = progress.Run(ctx, func(ctx context.Context) (string, error) { - return "", c.ComposeService().Push(ctx, project) + return "", c.ComposeService().Push(ctx, project, compose.PushOptions{ + IgnoreFailures: opts.Ignorefailures, + }) }) return err } diff --git a/ecs/local/compose.go b/ecs/local/compose.go index f8a8da8e5..b28cb8a11 100644 --- a/ecs/local/compose.go +++ b/ecs/local/compose.go @@ -36,8 +36,8 @@ func (e ecsLocalSimulation) Build(ctx context.Context, project *types.Project, o return e.compose.Build(ctx, project, options) } -func (e ecsLocalSimulation) Push(ctx context.Context, project *types.Project) error { - return e.compose.Push(ctx, project) +func (e ecsLocalSimulation) Push(ctx context.Context, project *types.Project, options compose.PushOptions) error { + return e.compose.Push(ctx, project, options) } func (e ecsLocalSimulation) Pull(ctx context.Context, project *types.Project) error { diff --git a/ecs/up.go b/ecs/up.go index b899bd0df..eccbf5c01 100644 --- a/ecs/up.go +++ b/ecs/up.go @@ -35,7 +35,7 @@ func (b *ecsAPIService) Build(ctx context.Context, project *types.Project, optio return errdefs.ErrNotImplemented } -func (b *ecsAPIService) Push(ctx context.Context, project *types.Project) error { +func (b *ecsAPIService) Push(ctx context.Context, project *types.Project, options compose.PushOptions) error { return errdefs.ErrNotImplemented } diff --git a/kube/compose.go b/kube/compose.go index 08a30851d..4456069e2 100644 --- a/kube/compose.go +++ b/kube/compose.go @@ -169,7 +169,7 @@ func (s *composeService) Build(ctx context.Context, project *types.Project, opti } // Push executes the equivalent ot a `compose push` -func (s *composeService) Push(ctx context.Context, project *types.Project) error { +func (s *composeService) Push(ctx context.Context, project *types.Project, options compose.PushOptions) error { return errdefs.ErrNotImplemented } diff --git a/local/compose/push.go b/local/compose/push.go index b0de803f1..67056fd36 100644 --- a/local/compose/push.go +++ b/local/compose/push.go @@ -33,11 +33,12 @@ import ( "github.com/pkg/errors" "golang.org/x/sync/errgroup" + "github.com/docker/compose-cli/api/compose" "github.com/docker/compose-cli/api/config" "github.com/docker/compose-cli/api/progress" ) -func (s *composeService) Push(ctx context.Context, project *types.Project) error { +func (s *composeService) Push(ctx context.Context, project *types.Project, options compose.PushOptions) error { configFile, err := cliconfig.Load(config.Dir(ctx)) if err != nil { return err @@ -64,13 +65,25 @@ func (s *composeService) Push(ctx context.Context, project *types.Project) error } service := service eg.Go(func() error { - return s.pullServiceImage(ctx, service, info, configFile, w) + err := s.pushServiceImage(ctx, service, info, configFile, w) + if err != nil { + if !options.IgnoreFailures { + return err + } + w.Event(progress.Event{ + ID: fmt.Sprintf("Pushing %s:", service.Name), + Text: fmt.Sprintf("%v", err), + Status: progress.Error, + StatusText: fmt.Sprintf("%s", err), + }) + } + return nil }) } return eg.Wait() } -func (s *composeService) pullServiceImage(ctx context.Context, service types.ServiceConfig, info moby.Info, configFile driver.Auth, w progress.Writer) error { +func (s *composeService) pushServiceImage(ctx context.Context, service types.ServiceConfig, info moby.Info, configFile driver.Auth, w progress.Writer) error { ref, err := reference.ParseNormalizedNamed(service.Image) if err != nil { return err @@ -113,7 +126,7 @@ func (s *composeService) pullServiceImage(ctx context.Context, service types.Ser if jm.Error != nil { return errors.New(jm.Error.Message) } - toPushProgressEvent("Pushing "+service.Name, jm, w) + toPushProgressEvent(service.Name, jm, w) } return nil }