Skip to content
This repository was archived by the owner on Nov 27, 2023. It is now read-only.

Commit badf822

Browse files
authored
Merge pull request #1454 from ulyssessouza/add-ignore-pull-failures
Add --ignore-pull-failures to command pull
2 parents 9f81314 + 02744ac commit badf822

File tree

8 files changed

+102
-70
lines changed

8 files changed

+102
-70
lines changed

aci/compose.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func (cs *aciComposeService) Push(ctx context.Context, project *types.Project, o
5252
return errdefs.ErrNotImplemented
5353
}
5454

55-
func (cs *aciComposeService) Pull(ctx context.Context, project *types.Project) error {
55+
func (cs *aciComposeService) Pull(ctx context.Context, project *types.Project, options compose.PullOptions) error {
5656
return errdefs.ErrNotImplemented
5757
}
5858

api/client/compose.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func (c *composeService) Push(ctx context.Context, project *types.Project, optio
3636
return errdefs.ErrNotImplemented
3737
}
3838

39-
func (c *composeService) Pull(ctx context.Context, project *types.Project) error {
39+
func (c *composeService) Pull(ctx context.Context, project *types.Project, options compose.PullOptions) error {
4040
return errdefs.ErrNotImplemented
4141
}
4242

api/compose/api.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ type Service interface {
3333
// Push executes the equivalent ot a `compose push`
3434
Push(ctx context.Context, project *types.Project, options PushOptions) error
3535
// Pull executes the equivalent of a `compose pull`
36-
Pull(ctx context.Context, project *types.Project) error
36+
Pull(ctx context.Context, project *types.Project, opts PullOptions) error
3737
// Create executes the equivalent to a `compose create`
3838
Create(ctx context.Context, project *types.Project, opts CreateOptions) error
3939
// Start executes the equivalent to a `compose start`
@@ -157,6 +157,11 @@ type PushOptions struct {
157157
IgnoreFailures bool
158158
}
159159

160+
// PullOptions group options of the Push API
161+
type PullOptions struct {
162+
IgnoreFailures bool
163+
}
164+
160165
// KillOptions group options of the Kill API
161166
type KillOptions struct {
162167
// Signal to send to containers

cli/cmd/compose/pull.go

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,19 @@ import (
2525
"github.com/spf13/cobra"
2626

2727
"github.com/docker/compose-cli/api/client"
28+
"github.com/docker/compose-cli/api/compose"
2829
"github.com/docker/compose-cli/api/progress"
2930
"github.com/docker/compose-cli/utils"
3031
)
3132

3233
type pullOptions struct {
3334
*projectOptions
3435
composeOptions
35-
quiet bool
36-
parallel bool
37-
noParallel bool
38-
includeDeps bool
36+
quiet bool
37+
parallel bool
38+
noParallel bool
39+
includeDeps bool
40+
ignorePullFailures bool
3941
}
4042

4143
func pullCommand(p *projectOptions) *cobra.Command {
@@ -59,6 +61,7 @@ func pullCommand(p *projectOptions) *cobra.Command {
5961
flags.MarkHidden("parallel") //nolint:errcheck
6062
cmd.Flags().BoolVar(&opts.parallel, "no-parallel", true, "DEPRECATED disable parallel pulling.")
6163
flags.MarkHidden("no-parallel") //nolint:errcheck
64+
cmd.Flags().BoolVar(&opts.ignorePullFailures, "ignore-pull-failures", false, "Pull what it can and ignores images with pull failures")
6265
return cmd
6366
}
6467

@@ -86,12 +89,16 @@ func runPull(ctx context.Context, opts pullOptions, services []string) error {
8689
project.Services = enabled
8790
}
8891

92+
apiOpts := compose.PullOptions{
93+
IgnoreFailures: opts.ignorePullFailures,
94+
}
95+
8996
if opts.quiet {
90-
return c.ComposeService().Pull(ctx, project)
97+
return c.ComposeService().Pull(ctx, project, apiOpts)
9198
}
9299

93100
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
94-
return "", c.ComposeService().Pull(ctx, project)
101+
return "", c.ComposeService().Pull(ctx, project, apiOpts)
95102
})
96103
return err
97104
}

ecs/local/compose.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ func (e ecsLocalSimulation) Push(ctx context.Context, project *types.Project, op
4040
return e.compose.Push(ctx, project, options)
4141
}
4242

43-
func (e ecsLocalSimulation) Pull(ctx context.Context, project *types.Project) error {
44-
return e.compose.Pull(ctx, project)
43+
func (e ecsLocalSimulation) Pull(ctx context.Context, project *types.Project, options compose.PullOptions) error {
44+
return e.compose.Pull(ctx, project, options)
4545
}
4646

4747
func (e ecsLocalSimulation) Create(ctx context.Context, project *types.Project, opts compose.CreateOptions) error {

ecs/up.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func (b *ecsAPIService) Push(ctx context.Context, project *types.Project, option
3939
return errdefs.ErrNotImplemented
4040
}
4141

42-
func (b *ecsAPIService) Pull(ctx context.Context, project *types.Project) error {
42+
func (b *ecsAPIService) Pull(ctx context.Context, project *types.Project, options compose.PullOptions) error {
4343
return errdefs.ErrNotImplemented
4444
}
4545

kube/compose.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ func (s *composeService) Push(ctx context.Context, project *types.Project, optio
174174
}
175175

176176
// Pull executes the equivalent of a `compose pull`
177-
func (s *composeService) Pull(ctx context.Context, project *types.Project) error {
177+
func (s *composeService) Pull(ctx context.Context, project *types.Project, options compose.PullOptions) error {
178178
return errdefs.ErrNotImplemented
179179
}
180180

local/compose/pull.go

Lines changed: 77 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,25 @@ import (
2121
"encoding/base64"
2222
"encoding/json"
2323
"errors"
24+
"fmt"
2425
"io"
2526
"strings"
2627

2728
"github.com/compose-spec/compose-go/types"
2829
"github.com/distribution/distribution/v3/reference"
30+
"github.com/docker/buildx/driver"
2931
cliconfig "github.com/docker/cli/cli/config"
3032
moby "github.com/docker/docker/api/types"
3133
"github.com/docker/docker/pkg/jsonmessage"
3234
"github.com/docker/docker/registry"
3335
"golang.org/x/sync/errgroup"
3436

37+
"github.com/docker/compose-cli/api/compose"
3538
"github.com/docker/compose-cli/api/config"
3639
"github.com/docker/compose-cli/api/progress"
3740
)
3841

39-
func (s *composeService) Pull(ctx context.Context, project *types.Project) error {
42+
func (s *composeService) Pull(ctx context.Context, project *types.Project, opts compose.PullOptions) error {
4043
configFile, err := cliconfig.Load(config.Dir())
4144
if err != nil {
4245
return err
@@ -64,73 +67,90 @@ func (s *composeService) Pull(ctx context.Context, project *types.Project) error
6467
continue
6568
}
6669
eg.Go(func() error {
67-
w.Event(progress.Event{
68-
ID: service.Name,
69-
Status: progress.Working,
70-
Text: "Pulling",
71-
})
72-
ref, err := reference.ParseNormalizedNamed(service.Image)
70+
err := s.pullServiceImage(ctx, service, info, configFile, w)
7371
if err != nil {
74-
return err
72+
if !opts.IgnoreFailures {
73+
return err
74+
}
75+
// If IgnoreFailures we still want to show the error message
76+
w.Event(progress.Event{
77+
ID: fmt.Sprintf("Pulling %s:", service.Name),
78+
Text: fmt.Sprintf("%v", err),
79+
Status: progress.Error,
80+
StatusText: fmt.Sprintf("%s", err),
81+
})
7582
}
83+
return nil
84+
})
85+
}
7686

77-
repoInfo, err := registry.ParseRepositoryInfo(ref)
78-
if err != nil {
79-
return err
80-
}
87+
return eg.Wait()
88+
}
8189

82-
key := repoInfo.Index.Name
83-
if repoInfo.Index.Official {
84-
key = info.IndexServerAddress
85-
}
90+
func (s *composeService) pullServiceImage(ctx context.Context, service types.ServiceConfig, info moby.Info, configFile driver.Auth, w progress.Writer) error {
91+
w.Event(progress.Event{
92+
ID: service.Name,
93+
Status: progress.Working,
94+
Text: "Pulling",
95+
})
96+
ref, err := reference.ParseNormalizedNamed(service.Image)
97+
if err != nil {
98+
return err
99+
}
86100

87-
authConfig, err := configFile.GetAuthConfig(key)
88-
if err != nil {
89-
return err
90-
}
101+
repoInfo, err := registry.ParseRepositoryInfo(ref)
102+
if err != nil {
103+
return err
104+
}
91105

92-
buf, err := json.Marshal(authConfig)
93-
if err != nil {
94-
return err
95-
}
106+
key := repoInfo.Index.Name
107+
if repoInfo.Index.Official {
108+
key = info.IndexServerAddress
109+
}
96110

97-
stream, err := s.apiClient.ImagePull(ctx, service.Image, moby.ImagePullOptions{
98-
RegistryAuth: base64.URLEncoding.EncodeToString(buf),
99-
Platform: service.Platform,
100-
})
101-
if err != nil {
102-
w.Event(progress.Event{
103-
ID: service.Name,
104-
Status: progress.Error,
105-
Text: "Error",
106-
})
107-
return err
108-
}
111+
authConfig, err := configFile.GetAuthConfig(key)
112+
if err != nil {
113+
return err
114+
}
109115

110-
dec := json.NewDecoder(stream)
111-
for {
112-
var jm jsonmessage.JSONMessage
113-
if err := dec.Decode(&jm); err != nil {
114-
if err == io.EOF {
115-
break
116-
}
117-
return err
118-
}
119-
if jm.Error != nil {
120-
return errors.New(jm.Error.Message)
121-
}
122-
toPullProgressEvent(service.Name, jm, w)
123-
}
124-
w.Event(progress.Event{
125-
ID: service.Name,
126-
Status: progress.Done,
127-
Text: "Pulled",
128-
})
129-
return nil
116+
buf, err := json.Marshal(authConfig)
117+
if err != nil {
118+
return err
119+
}
120+
121+
stream, err := s.apiClient.ImagePull(ctx, service.Image, moby.ImagePullOptions{
122+
RegistryAuth: base64.URLEncoding.EncodeToString(buf),
123+
Platform: service.Platform,
124+
})
125+
if err != nil {
126+
w.Event(progress.Event{
127+
ID: service.Name,
128+
Status: progress.Error,
129+
Text: "Error",
130130
})
131+
return err
131132
}
132133

133-
return eg.Wait()
134+
dec := json.NewDecoder(stream)
135+
for {
136+
var jm jsonmessage.JSONMessage
137+
if err := dec.Decode(&jm); err != nil {
138+
if err == io.EOF {
139+
break
140+
}
141+
return err
142+
}
143+
if jm.Error != nil {
144+
return errors.New(jm.Error.Message)
145+
}
146+
toPullProgressEvent(service.Name, jm, w)
147+
}
148+
w.Event(progress.Event{
149+
ID: service.Name,
150+
Status: progress.Done,
151+
Text: "Pulled",
152+
})
153+
return nil
134154
}
135155

136156
func toPullProgressEvent(parent string, jm jsonmessage.JSONMessage, w progress.Writer) {

0 commit comments

Comments
 (0)