66 "fmt"
77 "io"
88 "net/http"
9+ "os"
910
1011 containerd "github.com/containerd/containerd/v2/client"
1112 "github.com/containerd/containerd/v2/core/remotes/docker"
@@ -45,27 +46,49 @@ func prepareImageStore(ctx context.Context, parsedReference *referenceutil.Image
4546 return transferimage .NewStore (parsedReference .String (), storeOpts ... ), nil
4647}
4748
48- func createOCIRegistry (ctx context.Context , parsedReference * referenceutil.ImageReference , gOptions types.GlobalCommandOptions , plainHTTP bool ) (* registry.OCIRegistry , error ) {
49+ func createOCIRegistry (ctx context.Context , parsedReference * referenceutil.ImageReference , gOptions types.GlobalCommandOptions , plainHTTP bool ) (* registry.OCIRegistry , func (), error ) {
4950 ch , err := dockerconfigresolver .NewCredentialHelper (parsedReference .Domain )
5051 if err != nil {
51- return nil , err
52+ return nil , nil , err
5253 }
5354
5455 opts := []registry.Opt {
5556 registry .WithCredentials (ch ),
5657 }
5758
58- if len (gOptions .HostsDir ) > 0 {
59+ var tmpHostsDir string
60+ cleanup := func () {
61+ if tmpHostsDir != "" {
62+ os .RemoveAll (tmpHostsDir )
63+ }
64+ }
65+
66+ // If insecure-registry is set, create a temporary hosts.toml with skip_verify
67+ if gOptions .InsecureRegistry {
68+ tmpHostsDir , err = dockerconfigresolver .CreateTmpHostsConfig (parsedReference .Domain , true )
69+ if err != nil {
70+ log .G (ctx ).WithError (err ).Warnf ("failed to create temporary hosts.toml for %q, continuing without it" , parsedReference .Domain )
71+ } else if tmpHostsDir != "" {
72+ opts = append (opts , registry .WithHostDir (tmpHostsDir ))
73+ }
74+ } else if len (gOptions .HostsDir ) > 0 {
5975 opts = append (opts , registry .WithHostDir (gOptions .HostsDir [0 ]))
6076 }
6177
6278 if isLocalHost , err := docker .MatchLocalhost (parsedReference .Domain ); err != nil {
63- return nil , err
79+ cleanup ()
80+ return nil , nil , err
6481 } else if isLocalHost || plainHTTP {
6582 opts = append (opts , registry .WithDefaultScheme ("http" ))
6683 }
6784
68- return registry .NewOCIRegistry (ctx , parsedReference .String (), opts ... )
85+ reg , err := registry .NewOCIRegistry (ctx , parsedReference .String (), opts ... )
86+ if err != nil {
87+ cleanup ()
88+ return nil , nil , err
89+ }
90+
91+ return reg , cleanup , nil
6992}
7093
7194func PullImageWithTransfer (ctx context.Context , client * containerd.Client , parsedReference * referenceutil.ImageReference , rawRef string , options types.ImagePullOptions ) (* EnsuredImage , error ) {
@@ -79,20 +102,22 @@ func PullImageWithTransfer(ctx context.Context, client *containerd.Client, parse
79102 progressWriter = options .Stdout
80103 }
81104
82- fetcher , err := createOCIRegistry (ctx , parsedReference , options .GOptions , false )
105+ fetcher , cleanup , err := createOCIRegistry (ctx , parsedReference , options .GOptions , false )
83106 if err != nil {
84107 return nil , err
85108 }
109+ defer cleanup ()
86110
87111 transferErr := doTransfer (ctx , client , fetcher , store , options .Quiet , progressWriter )
88112
89- if transferErr != nil && (errors .Is (transferErr , http .ErrSchemeMismatch ) || errutil .IsErrConnectionRefused (transferErr )) {
113+ if transferErr != nil && (errors .Is (transferErr , http .ErrSchemeMismatch ) || errutil .IsErrConnectionRefused (transferErr ) || errutil . IsErrHTTPResponseToHTTPSClient ( transferErr ) || errutil . IsErrTLSHandshakeFailure ( transferErr ) ) {
90114 if options .GOptions .InsecureRegistry {
91- log .G (ctx ).WithError (err ).Warnf ("server %q does not seem to support HTTPS, falling back to plain HTTP" , parsedReference .Domain )
92- fetcher , err = createOCIRegistry (ctx , parsedReference , options .GOptions , true )
115+ log .G (ctx ).WithError (transferErr ).Warnf ("server %q does not seem to support HTTPS, falling back to plain HTTP" , parsedReference .Domain )
116+ fetcher , cleanup2 , err : = createOCIRegistry (ctx , parsedReference , options .GOptions , true )
93117 if err != nil {
94118 return nil , err
95119 }
120+ defer cleanup2 ()
96121 transferErr = doTransfer (ctx , client , fetcher , store , options .Quiet , progressWriter )
97122 }
98123 }
@@ -151,20 +176,22 @@ func PushImageWithTransfer(ctx context.Context, client *containerd.Client, parse
151176 progressWriter = options .Stdout
152177 }
153178
154- pusher , err := createOCIRegistry (ctx , parsedReference , options .GOptions , false )
179+ pusher , cleanup , err := createOCIRegistry (ctx , parsedReference , options .GOptions , false )
155180 if err != nil {
156181 return err
157182 }
183+ defer cleanup ()
158184
159185 transferErr := doTransfer (ctx , client , source , pusher , options .Quiet , progressWriter )
160186
161- if transferErr != nil && (errors .Is (transferErr , http .ErrSchemeMismatch ) || errutil .IsErrConnectionRefused (transferErr )) {
187+ if transferErr != nil && (errors .Is (transferErr , http .ErrSchemeMismatch ) || errutil .IsErrConnectionRefused (transferErr ) || errutil . IsErrHTTPResponseToHTTPSClient ( transferErr ) || errutil . IsErrTLSHandshakeFailure ( transferErr ) ) {
162188 if options .GOptions .InsecureRegistry {
163- log .G (ctx ).WithError (err ).Warnf ("server %q does not seem to support HTTPS, falling back to plain HTTP" , parsedReference .Domain )
164- pusher , err = createOCIRegistry (ctx , parsedReference , options .GOptions , true )
189+ log .G (ctx ).WithError (transferErr ).Warnf ("server %q does not seem to support HTTPS, falling back to plain HTTP" , parsedReference .Domain )
190+ pusher , cleanup2 , err : = createOCIRegistry (ctx , parsedReference , options .GOptions , true )
165191 if err != nil {
166192 return err
167193 }
194+ defer cleanup2 ()
168195 transferErr = doTransfer (ctx , client , source , pusher , options .Quiet , progressWriter )
169196 }
170197 }
0 commit comments