@@ -27,6 +27,7 @@ import (
2727 "github.com/CloudNativeAI/modctl/pkg/config"
2828 "github.com/CloudNativeAI/modctl/pkg/storage"
2929
30+ retry "github.com/avast/retry-go/v4"
3031 ocispec "github.com/opencontainers/image-spec/specs-go/v1"
3132 "golang.org/x/sync/errgroup"
3233)
@@ -85,7 +86,7 @@ func (b *backend) Pull(ctx context.Context, target string, cfg *config.Pull) err
8586 }
8687
8788 for _ , layer := range manifest .Layers {
88- g .Go (func () error { return fn (layer ) })
89+ g .Go (func () error { return retry . Do ( func () error { return fn (layer ) }, retryOpts ... ) })
8990 }
9091
9192 if err := g .Wait (); err != nil {
@@ -99,12 +100,16 @@ func (b *backend) Pull(ctx context.Context, target string, cfg *config.Pull) err
99100 }
100101
101102 // copy the config.
102- if err := pullIfNotExist (ctx , pb , internalpb .NormalizePrompt ("Pulling config" ), src , dst , manifest .Config , repo , tag ); err != nil {
103+ if err := retry .Do (func () error {
104+ return pullIfNotExist (ctx , pb , internalpb .NormalizePrompt ("Pulling config" ), src , dst , manifest .Config , repo , tag )
105+ }, retryOpts ... ); err != nil {
103106 return fmt .Errorf ("failed to pull config to local: %w" , err )
104107 }
105108
106109 // copy the manifest.
107- if err := pullIfNotExist (ctx , pb , internalpb .NormalizePrompt ("Pulling manifest" ), src , dst , manifestDesc , repo , tag ); err != nil {
110+ if err := retry .Do (func () error {
111+ return pullIfNotExist (ctx , pb , internalpb .NormalizePrompt ("Pulling manifest" ), src , dst , manifestDesc , repo , tag )
112+ }, retryOpts ... ); err != nil {
108113 return fmt .Errorf ("failed to pull manifest to local: %w" , err )
109114 }
110115
@@ -138,7 +143,8 @@ func pullIfNotExist(ctx context.Context, pb *internalpb.ProgressBar, prompt stri
138143 // check whether the content exists in the destination storage.
139144 exist , err := dst .StatManifest (ctx , repo , desc .Digest .String ())
140145 if err != nil {
141- pb .Complete (desc .Digest .String (), fmt .Sprintf ("Failed to check manifest %s, err: %v" , desc .Digest .String (), err ))
146+ err = fmt .Errorf ("failed to check manifest %s, err: %w" , desc .Digest .String (), err )
147+ pb .Abort (desc .Digest .String (), err )
142148 return err
143149 }
144150
@@ -149,18 +155,21 @@ func pullIfNotExist(ctx context.Context, pb *internalpb.ProgressBar, prompt stri
149155
150156 body , err := io .ReadAll (reader )
151157 if err != nil {
152- pb .Complete (desc .Digest .String (), fmt .Sprintf ("Failed to read manifest %s, err: %v" , desc .Digest .String (), err ))
158+ err = fmt .Errorf ("failed to read manifest %s, err: %w" , desc .Digest .String (), err )
159+ pb .Abort (desc .Digest .String (), err )
153160 return err
154161 }
155162
156163 if _ , err := dst .PushManifest (ctx , repo , tag , body ); err != nil {
157- pb .Complete (desc .Digest .String (), fmt .Sprintf ("Failed to store manifest %s, err: %v" , desc .Digest .String (), err ))
164+ err = fmt .Errorf ("failed to store manifest %s, err: %w" , desc .Digest .String (), err )
165+ pb .Abort (desc .Digest .String (), err )
158166 return err
159167 }
160168 } else {
161169 exist , err := dst .StatBlob (ctx , repo , desc .Digest .String ())
162170 if err != nil {
163- pb .Complete (desc .Digest .String (), fmt .Sprintf ("Failed to check blob %s, err: %v" , desc .Digest .String (), err ))
171+ err = fmt .Errorf ("failed to check blob %s, err: %w" , desc .Digest .String (), err )
172+ pb .Abort (desc .Digest .String (), err )
164173 return err
165174 }
166175
@@ -170,7 +179,8 @@ func pullIfNotExist(ctx context.Context, pb *internalpb.ProgressBar, prompt stri
170179 }
171180
172181 if _ , _ , err := dst .PushBlob (ctx , repo , reader , desc ); err != nil {
173- pb .Complete (desc .Digest .String (), fmt .Sprintf ("Failed to store blob %s, err: %v" , desc .Digest .String (), err ))
182+ err = fmt .Errorf ("failed to store blob %s, err: %w" , desc .Digest .String (), err )
183+ pb .Abort (desc .Digest .String (), err )
174184 return err
175185 }
176186 }
@@ -190,8 +200,9 @@ func pullAndExtractFromRemote(ctx context.Context, pb *internalpb.ProgressBar, p
190200
191201 reader := pb .Add (prompt , desc .Digest .String (), desc .Size , content )
192202 if err := extractLayer (desc , outputDir , reader ); err != nil {
193- pb .Complete (desc .Digest .String (), fmt .Sprintf ("Failed to pull and extract blob %s from remote, err: %v" , desc .Digest .String (), err ))
194- return fmt .Errorf ("failed to extract the blob %s to output directory: %w" , desc .Digest .String (), err )
203+ err = fmt .Errorf ("failed to extract the blob %s to output directory: %w" , desc .Digest .String (), err )
204+ pb .Abort (desc .Digest .String (), err )
205+ return err
195206 }
196207
197208 return nil
0 commit comments