mirror of https://github.com/docker/compose.git
Add --ignore-pull-failures to command pull
Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
This commit is contained in:
parent
9f81314124
commit
02744ac4f9
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
quiet bool
|
||||||
parallel bool
|
parallel bool
|
||||||
noParallel bool
|
noParallel bool
|
||||||
includeDeps 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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
func (e ecsLocalSimulation) Pull(ctx context.Context, project *types.Project, options compose.PullOptions) error {
|
||||||
return e.compose.Pull(ctx, project)
|
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 {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,68 +67,19 @@ 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{
|
err := s.pullServiceImage(ctx, service, info, configFile, w)
|
||||||
ID: service.Name,
|
|
||||||
Status: progress.Working,
|
|
||||||
Text: "Pulling",
|
|
||||||
})
|
|
||||||
ref, err := reference.ParseNormalizedNamed(service.Image)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
if !opts.IgnoreFailures {
|
||||||
}
|
|
||||||
|
|
||||||
repoInfo, err := registry.ParseRepositoryInfo(ref)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
key := repoInfo.Index.Name
|
|
||||||
if repoInfo.Index.Official {
|
|
||||||
key = info.IndexServerAddress
|
|
||||||
}
|
|
||||||
|
|
||||||
authConfig, err := configFile.GetAuthConfig(key)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
dec := json.NewDecoder(stream)
|
|
||||||
for {
|
|
||||||
var jm jsonmessage.JSONMessage
|
|
||||||
if err := dec.Decode(&jm); err != nil {
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if jm.Error != nil {
|
// If IgnoreFailures we still want to show the error message
|
||||||
return errors.New(jm.Error.Message)
|
w.Event(progress.Event{
|
||||||
}
|
ID: fmt.Sprintf("Pulling %s:", service.Name),
|
||||||
toPullProgressEvent(service.Name, jm, w)
|
Text: fmt.Sprintf("%v", err),
|
||||||
|
Status: progress.Error,
|
||||||
|
StatusText: fmt.Sprintf("%s", err),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
w.Event(progress.Event{
|
|
||||||
ID: service.Name,
|
|
||||||
Status: progress.Done,
|
|
||||||
Text: "Pulled",
|
|
||||||
})
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -133,6 +87,72 @@ func (s *composeService) Pull(ctx context.Context, project *types.Project) error
|
||||||
return eg.Wait()
|
return eg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
repoInfo, err := registry.ParseRepositoryInfo(ref)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
key := repoInfo.Index.Name
|
||||||
|
if repoInfo.Index.Official {
|
||||||
|
key = info.IndexServerAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
authConfig, err := configFile.GetAuthConfig(key)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
if jm.ID == "" || jm.Progress == nil {
|
if jm.ID == "" || jm.Progress == nil {
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue