1
0
Эх сурвалжийг харах

Add --ignore-pull-failures to command pull

Signed-off-by: Ulysses Souza <[email protected]>
Ulysses Souza 4 жил өмнө
parent
commit
02744ac4f9

+ 1 - 1
aci/compose.go

@@ -52,7 +52,7 @@ func (cs *aciComposeService) Push(ctx context.Context, project *types.Project, o
 	return errdefs.ErrNotImplemented
 	return errdefs.ErrNotImplemented
 }
 }
 
 
-func (cs *aciComposeService) Pull(ctx context.Context, project *types.Project) error {
+func (cs *aciComposeService) Pull(ctx context.Context, project *types.Project, options compose.PullOptions) error {
 	return errdefs.ErrNotImplemented
 	return errdefs.ErrNotImplemented
 }
 }
 
 

+ 1 - 1
api/client/compose.go

@@ -36,7 +36,7 @@ func (c *composeService) Push(ctx context.Context, project *types.Project, optio
 	return errdefs.ErrNotImplemented
 	return errdefs.ErrNotImplemented
 }
 }
 
 
-func (c *composeService) Pull(ctx context.Context, project *types.Project) error {
+func (c *composeService) Pull(ctx context.Context, project *types.Project, options compose.PullOptions) error {
 	return errdefs.ErrNotImplemented
 	return errdefs.ErrNotImplemented
 }
 }
 
 

+ 6 - 1
api/compose/api.go

@@ -33,7 +33,7 @@ type Service interface {
 	// Push executes the equivalent ot a `compose push`
 	// Push executes the equivalent ot a `compose push`
 	Push(ctx context.Context, project *types.Project, options PushOptions) error
 	Push(ctx context.Context, project *types.Project, options PushOptions) error
 	// Pull executes the equivalent of a `compose pull`
 	// Pull executes the equivalent of a `compose pull`
-	Pull(ctx context.Context, project *types.Project) error
+	Pull(ctx context.Context, project *types.Project, opts PullOptions) error
 	// Create executes the equivalent to a `compose create`
 	// Create executes the equivalent to a `compose create`
 	Create(ctx context.Context, project *types.Project, opts CreateOptions) error
 	Create(ctx context.Context, project *types.Project, opts CreateOptions) error
 	// Start executes the equivalent to a `compose start`
 	// Start executes the equivalent to a `compose start`
@@ -157,6 +157,11 @@ type PushOptions struct {
 	IgnoreFailures bool
 	IgnoreFailures bool
 }
 }
 
 
+// PullOptions group options of the Push API
+type PullOptions struct {
+	IgnoreFailures bool
+}
+
 // KillOptions group options of the Kill API
 // KillOptions group options of the Kill API
 type KillOptions struct {
 type KillOptions struct {
 	// Signal to send to containers
 	// Signal to send to containers

+ 13 - 6
cli/cmd/compose/pull.go

@@ -25,6 +25,7 @@ import (
 	"github.com/spf13/cobra"
 	"github.com/spf13/cobra"
 
 
 	"github.com/docker/compose-cli/api/client"
 	"github.com/docker/compose-cli/api/client"
+	"github.com/docker/compose-cli/api/compose"
 	"github.com/docker/compose-cli/api/progress"
 	"github.com/docker/compose-cli/api/progress"
 	"github.com/docker/compose-cli/utils"
 	"github.com/docker/compose-cli/utils"
 )
 )
@@ -32,10 +33,11 @@ import (
 type pullOptions struct {
 type pullOptions struct {
 	*projectOptions
 	*projectOptions
 	composeOptions
 	composeOptions
-	quiet       bool
-	parallel    bool
-	noParallel  bool
-	includeDeps bool
+	quiet              bool
+	parallel           bool
+	noParallel         bool
+	includeDeps        bool
+	ignorePullFailures bool
 }
 }
 
 
 func pullCommand(p *projectOptions) *cobra.Command {
 func pullCommand(p *projectOptions) *cobra.Command {
@@ -59,6 +61,7 @@ func pullCommand(p *projectOptions) *cobra.Command {
 	flags.MarkHidden("parallel") //nolint:errcheck
 	flags.MarkHidden("parallel") //nolint:errcheck
 	cmd.Flags().BoolVar(&opts.parallel, "no-parallel", true, "DEPRECATED disable parallel pulling.")
 	cmd.Flags().BoolVar(&opts.parallel, "no-parallel", true, "DEPRECATED disable parallel pulling.")
 	flags.MarkHidden("no-parallel") //nolint:errcheck
 	flags.MarkHidden("no-parallel") //nolint:errcheck
+	cmd.Flags().BoolVar(&opts.ignorePullFailures, "ignore-pull-failures", false, "Pull what it can and ignores images with pull failures")
 	return cmd
 	return cmd
 }
 }
 
 
@@ -86,12 +89,16 @@ func runPull(ctx context.Context, opts pullOptions, services []string) error {
 		project.Services = enabled
 		project.Services = enabled
 	}
 	}
 
 
+	apiOpts := compose.PullOptions{
+		IgnoreFailures: opts.ignorePullFailures,
+	}
+
 	if opts.quiet {
 	if opts.quiet {
-		return c.ComposeService().Pull(ctx, project)
+		return c.ComposeService().Pull(ctx, project, apiOpts)
 	}
 	}
 
 
 	_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
 	_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
-		return "", c.ComposeService().Pull(ctx, project)
+		return "", c.ComposeService().Pull(ctx, project, apiOpts)
 	})
 	})
 	return err
 	return err
 }
 }

+ 2 - 2
ecs/local/compose.go

@@ -40,8 +40,8 @@ func (e ecsLocalSimulation) Push(ctx context.Context, project *types.Project, op
 	return e.compose.Push(ctx, project, options)
 	return e.compose.Push(ctx, project, options)
 }
 }
 
 
-func (e ecsLocalSimulation) Pull(ctx context.Context, project *types.Project) error {
-	return e.compose.Pull(ctx, project)
+func (e ecsLocalSimulation) Pull(ctx context.Context, project *types.Project, options compose.PullOptions) error {
+	return e.compose.Pull(ctx, project, options)
 }
 }
 
 
 func (e ecsLocalSimulation) Create(ctx context.Context, project *types.Project, opts compose.CreateOptions) error {
 func (e ecsLocalSimulation) Create(ctx context.Context, project *types.Project, opts compose.CreateOptions) error {

+ 1 - 1
ecs/up.go

@@ -39,7 +39,7 @@ func (b *ecsAPIService) Push(ctx context.Context, project *types.Project, option
 	return errdefs.ErrNotImplemented
 	return errdefs.ErrNotImplemented
 }
 }
 
 
-func (b *ecsAPIService) Pull(ctx context.Context, project *types.Project) error {
+func (b *ecsAPIService) Pull(ctx context.Context, project *types.Project, options compose.PullOptions) error {
 	return errdefs.ErrNotImplemented
 	return errdefs.ErrNotImplemented
 }
 }
 
 

+ 1 - 1
kube/compose.go

@@ -174,7 +174,7 @@ func (s *composeService) Push(ctx context.Context, project *types.Project, optio
 }
 }
 
 
 // Pull executes the equivalent of a `compose pull`
 // Pull executes the equivalent of a `compose pull`
-func (s *composeService) Pull(ctx context.Context, project *types.Project) error {
+func (s *composeService) Pull(ctx context.Context, project *types.Project, options compose.PullOptions) error {
 	return errdefs.ErrNotImplemented
 	return errdefs.ErrNotImplemented
 }
 }
 
 

+ 77 - 57
local/compose/pull.go

@@ -21,22 +21,25 @@ import (
 	"encoding/base64"
 	"encoding/base64"
 	"encoding/json"
 	"encoding/json"
 	"errors"
 	"errors"
+	"fmt"
 	"io"
 	"io"
 	"strings"
 	"strings"
 
 
 	"github.com/compose-spec/compose-go/types"
 	"github.com/compose-spec/compose-go/types"
 	"github.com/distribution/distribution/v3/reference"
 	"github.com/distribution/distribution/v3/reference"
+	"github.com/docker/buildx/driver"
 	cliconfig "github.com/docker/cli/cli/config"
 	cliconfig "github.com/docker/cli/cli/config"
 	moby "github.com/docker/docker/api/types"
 	moby "github.com/docker/docker/api/types"
 	"github.com/docker/docker/pkg/jsonmessage"
 	"github.com/docker/docker/pkg/jsonmessage"
 	"github.com/docker/docker/registry"
 	"github.com/docker/docker/registry"
 	"golang.org/x/sync/errgroup"
 	"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/config"
 	"github.com/docker/compose-cli/api/progress"
 	"github.com/docker/compose-cli/api/progress"
 )
 )
 
 
-func (s *composeService) Pull(ctx context.Context, project *types.Project) error {
+func (s *composeService) Pull(ctx context.Context, project *types.Project, opts compose.PullOptions) error {
 	configFile, err := cliconfig.Load(config.Dir())
 	configFile, err := cliconfig.Load(config.Dir())
 	if err != nil {
 	if err != nil {
 		return err
 		return err
@@ -64,73 +67,90 @@ func (s *composeService) Pull(ctx context.Context, project *types.Project) error
 			continue
 			continue
 		}
 		}
 		eg.Go(func() error {
 		eg.Go(func() error {
-			w.Event(progress.Event{
-				ID:     service.Name,
-				Status: progress.Working,
-				Text:   "Pulling",
-			})
-			ref, err := reference.ParseNormalizedNamed(service.Image)
+			err := s.pullServiceImage(ctx, service, info, configFile, w)
 			if err != nil {
 			if err != nil {
-				return err
+				if !opts.IgnoreFailures {
+					return err
+				}
+				// If IgnoreFailures we still want to show the error message
+				w.Event(progress.Event{
+					ID:         fmt.Sprintf("Pulling %s:", service.Name),
+					Text:       fmt.Sprintf("%v", err),
+					Status:     progress.Error,
+					StatusText: fmt.Sprintf("%s", err),
+				})
 			}
 			}
+			return nil
+		})
+	}
 
 
-			repoInfo, err := registry.ParseRepositoryInfo(ref)
-			if err != nil {
-				return err
-			}
+	return eg.Wait()
+}
 
 
-			key := repoInfo.Index.Name
-			if repoInfo.Index.Official {
-				key = info.IndexServerAddress
-			}
+func (s *composeService) pullServiceImage(ctx context.Context, service types.ServiceConfig, info moby.Info, configFile driver.Auth, w progress.Writer) error {
+	w.Event(progress.Event{
+		ID:     service.Name,
+		Status: progress.Working,
+		Text:   "Pulling",
+	})
+	ref, err := reference.ParseNormalizedNamed(service.Image)
+	if err != nil {
+		return err
+	}
 
 
-			authConfig, err := configFile.GetAuthConfig(key)
-			if err != nil {
-				return err
-			}
+	repoInfo, err := registry.ParseRepositoryInfo(ref)
+	if err != nil {
+		return err
+	}
 
 
-			buf, err := json.Marshal(authConfig)
-			if err != nil {
-				return err
-			}
+	key := repoInfo.Index.Name
+	if repoInfo.Index.Official {
+		key = info.IndexServerAddress
+	}
 
 
-			stream, err := s.apiClient.ImagePull(ctx, service.Image, moby.ImagePullOptions{
-				RegistryAuth: base64.URLEncoding.EncodeToString(buf),
-				Platform:     service.Platform,
-			})
-			if err != nil {
-				w.Event(progress.Event{
-					ID:     service.Name,
-					Status: progress.Error,
-					Text:   "Error",
-				})
-				return err
-			}
+	authConfig, err := configFile.GetAuthConfig(key)
+	if err != nil {
+		return err
+	}
 
 
-			dec := json.NewDecoder(stream)
-			for {
-				var jm jsonmessage.JSONMessage
-				if err := dec.Decode(&jm); err != nil {
-					if err == io.EOF {
-						break
-					}
-					return err
-				}
-				if jm.Error != nil {
-					return errors.New(jm.Error.Message)
-				}
-				toPullProgressEvent(service.Name, jm, w)
-			}
-			w.Event(progress.Event{
-				ID:     service.Name,
-				Status: progress.Done,
-				Text:   "Pulled",
-			})
-			return nil
+	buf, err := json.Marshal(authConfig)
+	if err != nil {
+		return err
+	}
+
+	stream, err := s.apiClient.ImagePull(ctx, service.Image, moby.ImagePullOptions{
+		RegistryAuth: base64.URLEncoding.EncodeToString(buf),
+		Platform:     service.Platform,
+	})
+	if err != nil {
+		w.Event(progress.Event{
+			ID:     service.Name,
+			Status: progress.Error,
+			Text:   "Error",
 		})
 		})
+		return err
 	}
 	}
 
 
-	return eg.Wait()
+	dec := json.NewDecoder(stream)
+	for {
+		var jm jsonmessage.JSONMessage
+		if err := dec.Decode(&jm); err != nil {
+			if err == io.EOF {
+				break
+			}
+			return err
+		}
+		if jm.Error != nil {
+			return errors.New(jm.Error.Message)
+		}
+		toPullProgressEvent(service.Name, jm, w)
+	}
+	w.Event(progress.Event{
+		ID:     service.Name,
+		Status: progress.Done,
+		Text:   "Pulled",
+	})
+	return nil
 }
 }
 
 
 func toPullProgressEvent(parent string, jm jsonmessage.JSONMessage, w progress.Writer) {
 func toPullProgressEvent(parent string, jm jsonmessage.JSONMessage, w progress.Writer) {