@@ -3,6 +3,7 @@ package imagesource
33import (
44 "bytes"
55 "context"
6+ "errors"
67 "fmt"
78 "io"
89 "net/http"
@@ -14,17 +15,16 @@ import (
1415
1516 "k8s.io/klog/v2"
1617
17- "github.com/aws/aws-sdk-go/aws"
18- "github.com/aws/aws-sdk-go/aws/awserr "
19- "github.com/aws/aws-sdk-go/aws/credentials "
20- "github.com/aws/aws-sdk-go/aws/session "
21- "github.com/aws/aws-sdk-go/service/s3"
22- "github.com/aws/aws-sdk-go/service/s3/s3manager "
18+ "github.com/aws/aws-sdk-go-v2 /aws"
19+ awsmiddleware "github.com/aws/aws-sdk-go-v2 /aws/middleware "
20+ "github.com/aws/aws-sdk-go-v2/config "
21+ "github.com/aws/aws-sdk-go-v2/feature/s3/manager "
22+ "github.com/aws/aws-sdk-go-v2 /service/s3"
23+ "github.com/aws/smithy-go "
2324
2425 "github.com/distribution/distribution/v3"
2526 "github.com/distribution/distribution/v3/reference"
2627 "github.com/distribution/distribution/v3/registry/client/auth"
27- "github.com/distribution/distribution/v3/registry/client/transport"
2828 godigest "github.com/opencontainers/go-digest"
2929)
3030
@@ -34,76 +34,73 @@ type s3Driver struct {
3434 Creds auth.CredentialStore
3535 CopyFrom []string
3636
37- repositories map [string ]* s3.S3
37+ repositories map [string ]* s3.Client
3838}
3939
4040type s3CredentialStore struct {
41- store auth.CredentialStore
42- url * url.URL
43- retrieved bool
41+ store auth.CredentialStore
42+ url * url.URL
4443}
4544
46- func (s * s3CredentialStore ) IsExpired () bool { return ! s .retrieved }
47-
48- func (s * s3CredentialStore ) Retrieve () (credentials.Value , error ) {
49- s .retrieved = false
45+ func (s * s3CredentialStore ) Retrieve (ctx context.Context ) (aws.Credentials , error ) {
5046 accessKeyID , secretAccessKey := s .store .Basic (s .url )
5147 if len (accessKeyID ) == 0 || len (secretAccessKey ) == 0 {
52- return credentials. Value {}, fmt .Errorf ("no AWS credentials located for %s" , s .url )
48+ return aws. Credentials {}, fmt .Errorf ("no AWS credentials located for %s" , s .url )
5349 }
54- s .retrieved = true
5550 klog .V (4 ).Infof ("found credentials for %s" , s .url )
56- return credentials. Value {
51+ return aws. Credentials {
5752 AccessKeyID : accessKeyID ,
5853 SecretAccessKey : secretAccessKey ,
59- ProviderName : "DockerCfg" ,
54+ Source : "DockerCfg" ,
6055 }, nil
6156}
6257
63- func (d * s3Driver ) newObject (server * url.URL , region string , insecure bool , securityDomain * url.URL ) (* s3.S3 , error ) {
58+ func (d * s3Driver ) newObject (server * url.URL , region string , insecure bool , securityDomain * url.URL ) (* s3.Client , error ) {
6459 key := fmt .Sprintf ("%s:%s:%t:%s" , server , region , insecure , securityDomain )
6560 s3obj , ok := d .repositories [key ]
6661 if ok {
6762 return s3obj , nil
6863 }
6964
70- awsConfig := aws . NewConfig ()
65+ ctx := context . Background ()
7166
72- var creds * credentials.Credentials
73- creds = credentials .NewChainCredentials ([]credentials.Provider {
74- & s3CredentialStore {store : d .Creds , url : securityDomain },
75- & credentials.EnvProvider {},
76- & credentials.SharedCredentialsProvider {},
77- })
67+ configOpts := []func (* config.LoadOptions ) error {
68+ config .WithRegion (region ),
69+ }
7870
79- awsConfig .WithCredentials (creds )
80- awsConfig .WithRegion (region )
81- awsConfig .WithDisableSSL (insecure )
71+ credStore := & s3CredentialStore {store : d .Creds , url : securityDomain }
72+ if _ , err := credStore .Retrieve (ctx ); err == nil {
73+ configOpts = append (configOpts , config .WithCredentialsProvider (credStore ))
74+ }
8275
8376 switch {
8477 case klog .V (10 ).Enabled ():
85- awsConfig . WithLogLevel (aws .LogDebugWithHTTPBody | aws .LogDebugWithRequestErrors | aws .LogDebugWithSigning )
78+ configOpts = append ( configOpts , config . WithClientLogMode (aws .LogSigning | aws .LogRetries | aws .LogRequest | aws . LogResponse | aws . LogResponseWithBody | aws . LogDeprecatedUsage ) )
8679 case klog .V (8 ).Enabled ():
87- awsConfig . WithLogLevel (aws .LogDebugWithRequestErrors )
80+ configOpts = append ( configOpts , config . WithClientLogMode (aws .LogRetries | aws . LogRequest | aws . LogResponse | aws . LogDeprecatedUsage ) )
8881 case klog .V (6 ).Enabled ():
89- awsConfig . WithLogLevel (aws .LogDebug )
82+ configOpts = append ( configOpts , config . WithClientLogMode (aws .LogRetries | aws . LogRequest | aws . LogDeprecatedUsage ) )
9083 }
9184
92- if d .UserAgent != "" {
93- awsConfig .WithHTTPClient (& http.Client {
94- Transport : transport .NewTransport (http .DefaultTransport , transport .NewHeaderRequestModifier (http.Header {http .CanonicalHeaderKey ("User-Agent" ): []string {d .UserAgent }})),
95- })
96- }
97- s , err := session .NewSession (awsConfig )
85+ cfg , err := config .LoadDefaultConfig (ctx , configOpts ... )
9886 if err != nil {
9987 return nil , err
10088 }
101- s3obj = s3 .New (s )
89+
90+ s3Client := s3 .NewFromConfig (cfg , func (o * s3.Options ) {
91+ if insecure {
92+ o .EndpointOptions .DisableHTTPS = true
93+ }
94+ if d .UserAgent != "" {
95+ o .APIOptions = append (o .APIOptions , awsmiddleware .AddUserAgentKey (d .UserAgent ))
96+ }
97+ })
98+
10299 if d .repositories == nil {
103- d .repositories = make (map [string ]* s3.S3 )
100+ d .repositories = make (map [string ]* s3.Client )
104101 }
105- d .repositories [key ] = s3obj
106- return s3obj , nil
102+ d .repositories [key ] = s3Client
103+ return s3Client , nil
107104}
108105
109106func (d * s3Driver ) Repository (ctx context.Context , server * url.URL , repoName string , insecure bool ) (distribution.Repository , error ) {
@@ -137,7 +134,7 @@ func (d *s3Driver) Repository(ctx context.Context, server *url.URL, repoName str
137134
138135type s3Repository struct {
139136 ctx context.Context
140- s3 * s3.S3
137+ s3 * s3.Client
141138 bucket string
142139 once sync.Once
143140 initErr error
@@ -168,7 +165,7 @@ func (r *s3Repository) Tags(ctx context.Context) distribution.TagService {
168165}
169166
170167func (r * s3Repository ) attemptCopy (id string , bucket , key string ) bool {
171- if _ , err := r .s3 .HeadObject (& s3.HeadObjectInput {
168+ if _ , err := r .s3 .HeadObject (r . ctx , & s3.HeadObjectInput {
172169 Bucket : aws .String (bucket ),
173170 Key : aws .String (key ),
174171 }); err == nil {
@@ -190,16 +187,17 @@ func (r *s3Repository) attemptCopy(id string, bucket, key string) bool {
190187 } else {
191188 sourceKey = path .Join (copyFrom , id )
192189 }
193- _ , err := r .s3 .CopyObject (& s3.CopyObjectInput {
194- CopySource : aws .String (sourceKey ),
190+ _ , err := r .s3 .CopyObject (r . ctx , & s3.CopyObjectInput {
191+ CopySource : aws .String (url . QueryEscape ( sourceKey ) ),
195192 Bucket : aws .String (bucket ),
196193 Key : aws .String (key ),
197194 })
198195 if err == nil {
199196 klog .V (4 ).Infof ("Copied existing object from %s to %s" , sourceKey , key )
200197 return true
201198 }
202- if a , ok := err .(awserr.Error ); ok && a .Code () == "NoSuchKey" {
199+ var apiErr smithy.APIError
200+ if errors .As (err , & apiErr ) && apiErr .ErrorCode () == "NoSuchKey" {
203201 klog .V (4 ).Infof ("No existing object matches source %s" , sourceKey )
204202 continue
205203 }
@@ -208,19 +206,20 @@ func (r *s3Repository) attemptCopy(id string, bucket, key string) bool {
208206 return false
209207}
210208
211- func (r * s3Repository ) conditionalUpload (input * s3manager. UploadInput , id string ) error {
209+ func (r * s3Repository ) conditionalUpload (input * s3. PutObjectInput , id string ) error {
212210 if r .attemptCopy (id , * input .Bucket , * input .Key ) {
213211 return nil
214212 }
215- _ , err := s3manager .NewUploaderWithClient (r .s3 ).Upload (input )
213+ uploader := manager .NewUploader (r .s3 )
214+ _ , err := uploader .Upload (r .ctx , input )
216215 return err
217216}
218217
219218func (r * s3Repository ) init () error {
220219 r .once .Do (func () {
221- r .initErr = r .conditionalUpload (& s3manager. UploadInput {
220+ r .initErr = r .conditionalUpload (& s3. PutObjectInput {
222221 Bucket : aws .String (r .bucket ),
223- Metadata : map [string ]* string {"X-Docker-Distribution-API-Version" : aws . String ( "registry/2.0" ) },
222+ Metadata : map [string ]string {"X-Docker-Distribution-API-Version" : "registry/2.0" },
224223 Body : bytes .NewBufferString ("" ),
225224 Key : aws .String ("/v2/" ),
226225 }, "" )
@@ -264,7 +263,7 @@ func (s *s3ManifestService) Put(ctx context.Context, manifest distribution.Manif
264263 dgst := godigest .FromBytes (payload )
265264 blob := fmt .Sprintf ("/v2/%s/blobs/%s" , s .r .repoName , dgst )
266265
267- if err := s .r .conditionalUpload (& s3manager. UploadInput {
266+ if err := s .r .conditionalUpload (& s3. PutObjectInput {
268267 Bucket : aws .String (s .r .bucket ),
269268 ContentType : aws .String (mediaType ),
270269 Body : bytes .NewBuffer (payload ),
@@ -281,10 +280,10 @@ func (s *s3ManifestService) Put(ctx context.Context, manifest distribution.Manif
281280 }
282281 }
283282 for _ , tag := range tags {
284- if _ , err := s .r .s3 .CopyObject (& s3.CopyObjectInput {
283+ if _ , err := s .r .s3 .CopyObject (s . r . ctx , & s3.CopyObjectInput {
285284 Bucket : aws .String (s .r .bucket ),
286285 ContentType : aws .String (mediaType ),
287- CopySource : aws .String (path .Join (s .r .bucket , blob )),
286+ CopySource : aws .String (path .Join (s .r .bucket , url . QueryEscape ( blob ) )),
288287 Key : aws .String (fmt .Sprintf ("/v2/%s/manifests/%s" , s .r .repoName , tag )),
289288 }); err != nil {
290289 return "" , err
@@ -328,7 +327,7 @@ func (s *s3BlobStore) Put(ctx context.Context, mediaType string, p []byte) (dist
328327 return distribution.Descriptor {}, err
329328 }
330329 d := godigest .FromBytes (p )
331- if err := s .r .conditionalUpload (& s3manager. UploadInput {
330+ if err := s .r .conditionalUpload (& s3. PutObjectInput {
332331 Bucket : aws .String (s .r .bucket ),
333332 ContentType : aws .String (mediaType ),
334333 Body : bytes .NewBuffer (p ),
@@ -409,7 +408,8 @@ func (w *writer) ReadFrom(r io.Reader) (int64, error) {
409408 if w .startedAt .IsZero () {
410409 w .startedAt = time .Now ()
411410 }
412- _ , err := s3manager .NewUploaderWithClient (w .driver .s3 ).Upload (& s3manager.UploadInput {
411+ uploader := manager .NewUploader (w .driver .s3 )
412+ _ , err := uploader .Upload (w .driver .ctx , & s3.PutObjectInput {
413413 Bucket : aws .String (w .driver .bucket ),
414414 ContentType : aws .String ("application/octet-stream" ),
415415 Key : aws .String (w .key ),
0 commit comments