@@ -32,46 +32,44 @@ import (
3232 "k8s.io/klog/v2"
3333)
3434
35- // We need to pick some region to query the AWS APIs through, even if we are not running on AWS.
35+ // defaultRegion is the region to query the AWS APIs through, this can be any AWS region is required even if we are not
36+ // running on AWS.
3637const defaultRegion = "us-east-2"
3738
38- // It contains S3Client, an Amazon S3 service client that is used to perform bucket
39- // and object actions.
40- type awsClient struct {
41- S3Client * s3 .Client
39+ // Client contains S3 and STS clients that are used to perform bucket and object actions.
40+ type Client struct {
41+ s3Client * s3. Client
42+ stsClient * sts .Client
4243}
4344
44- func NewAWSClient (ctx context.Context ) (* awsClient , error ) {
45+ // NewAWSClient returns a new instance of awsClient configured to work in the default region (us-east-2).
46+ func NewClient (ctx context.Context ) (* Client , error ) {
4547 cfg , err := awsconfig .LoadDefaultConfig (ctx ,
4648 awsconfig .WithRegion (defaultRegion ))
4749 if err != nil {
48- return nil , fmt .Errorf ("failed to load AWS config: %w" , err )
50+ return nil , fmt .Errorf ("loading AWS config: %w" , err )
4951 }
50- return & awsClient {
51- S3Client : s3 .NewFromConfig (cfg ),
52+
53+ return & Client {
54+ s3Client : s3 .NewFromConfig (cfg ),
55+ stsClient : sts .NewFromConfig (cfg ),
5256 }, nil
5357}
5458
55- // AWSBucketName constructs an unique bucket name using the AWS account ID on region us-east-2
56- func AWSBucketName (ctx context.Context ) (string , error ) {
57- config , err := awsconfig .LoadDefaultConfig (ctx , awsconfig .WithRegion (string (types .BucketLocationConstraintUsEast2 )))
58- if err != nil {
59- return "" , fmt .Errorf ("failed to load AWS config: %w" , err )
60- }
61-
62- stsSvc := sts .NewFromConfig (config )
63- callerIdentity , err := stsSvc .GetCallerIdentity (ctx , & sts.GetCallerIdentityInput {})
59+ // BucketName constructs an unique bucket name using the AWS account ID in the default region (us-east-2).
60+ func (c Client ) BucketName (ctx context.Context ) (string , error ) {
61+ callerIdentity , err := c .stsClient .GetCallerIdentity (ctx , & sts.GetCallerIdentityInput {})
6462 if err != nil {
6563 return "" , fmt .Errorf ("building AWS STS presigned request: %w" , err )
6664 }
6765
68- // Add timestamp suffix
69- timestamp := time .Now ().Format ("01022006" )
70- bucket := fmt .Sprintf ("k8s-infra-kops-%s" , * callerIdentity .Account )
71- bucket = fmt .Sprintf ("%s-%s" , bucket , timestamp )
66+ // Construct the bucket name based on the AWS account ID and the current timestamp
67+ timestamp := time .Now ().Format ("20060102150405" )
68+ bucket := fmt .Sprintf ("k8s-infra-kops-%s-%s" , * callerIdentity .Account , timestamp )
7269
7370 bucket = strings .ToLower (bucket )
74- bucket = regexp .MustCompile ("[^a-z0-9-]" ).ReplaceAllString (bucket , "" ) // Only allow lowercase letters, numbers, and hyphens
71+ // Only allow lowercase letters, numbers, and hyphens
72+ bucket = regexp .MustCompile ("[^a-z0-9-]" ).ReplaceAllString (bucket , "" )
7573
7674 if len (bucket ) > 63 {
7775 bucket = bucket [:63 ] // Max length is 63
@@ -80,73 +78,88 @@ func AWSBucketName(ctx context.Context) (string, error) {
8078 return bucket , nil
8179}
8280
83- func (client awsClient ) EnsureS3Bucket (ctx context.Context , bucketName string , publicRead bool ) error {
84- _ , err := client .S3Client .CreateBucket (ctx , & s3.CreateBucketInput {
81+ // EnsureS3Bucket creates a new S3 bucket with the given name and public read permissions.
82+ func (c Client ) EnsureS3Bucket (ctx context.Context , bucketName string , publicRead bool ) error {
83+ _ , err := c .s3Client .CreateBucket (ctx , & s3.CreateBucketInput {
8584 Bucket : aws .String (bucketName ),
8685 CreateBucketConfiguration : & types.CreateBucketConfiguration {
87- LocationConstraint : types . BucketLocationConstraintUsEast2 ,
86+ LocationConstraint : defaultRegion ,
8887 },
8988 })
90-
91- var exists * types.BucketAlreadyExists
9289 if err != nil {
90+ var exists * types.BucketAlreadyExists
9391 if errors .As (err , & exists ) {
94- klog .Infof ("Bucket %s already exists.\n " , bucketName )
95- err = exists
96- }
97- } else {
98- err := s3 .NewBucketExistsWaiter (client .S3Client ).Wait (
99- ctx , & s3.HeadBucketInput {
100- Bucket : aws .String (bucketName ),
101- },
102- time .Minute )
103- if err != nil {
104- klog .Infof ("Failed attempt to wait for bucket %s to exist." , bucketName )
92+ klog .Infof ("Bucket %s already exists\n " , bucketName )
93+ } else {
94+ klog .Infof ("Error creating bucket %s, err: %v\n " , bucketName , err )
10595 }
96+
97+ return fmt .Errorf ("creating bucket %s: %w" , bucketName , err )
98+ }
99+
100+ // Wait for the bucket to be created
101+ err = s3 .NewBucketExistsWaiter (c .s3Client ).Wait (
102+ ctx , & s3.HeadBucketInput {
103+ Bucket : aws .String (bucketName ),
104+ },
105+ time .Minute )
106+ if err != nil {
107+ klog .Infof ("Failed attempt to wait for bucket %s to exist, err: %v" , bucketName , err )
108+
109+ return fmt .Errorf ("waiting for bucket %s to exist: %w" , bucketName , err )
106110 }
107111
108112 klog .Infof ("Bucket %s created successfully" , bucketName )
109113
110- if err == nil && publicRead {
111- err = client .setPublicReadPolicy (ctx , bucketName )
114+ if publicRead {
115+ err = c .setPublicReadPolicy (ctx , bucketName )
112116 if err != nil {
113- klog .Errorf ("Failed to set public read policy on bucket %s: %v" , bucketName , err )
114- return err
117+ klog .Errorf ("Failed to set public read policy on bucket %s, err: %v" , bucketName , err )
118+
119+ return fmt .Errorf ("setting public read policy for bucket %s: %w" , bucketName , err )
115120 }
121+
116122 klog .Infof ("Public read policy set on bucket %s" , bucketName )
117123 }
118124
119- return err
125+ return nil
120126}
121127
122- func (client awsClient ) DeleteS3Bucket (ctx context.Context , bucketName string ) error {
123- _ , err := client .S3Client .DeleteBucket (ctx , & s3.DeleteBucketInput {
128+ // DeleteS3Bucket deletes a S3 bucket with the given name.
129+ func (c Client ) DeleteS3Bucket (ctx context.Context , bucketName string ) error {
130+ _ , err := c .s3Client .DeleteBucket (ctx , & s3.DeleteBucketInput {
124131 Bucket : aws .String (bucketName ),
125132 })
126133 if err != nil {
127134 var noBucket * types.NoSuchBucket
128135 if errors .As (err , & noBucket ) {
129- klog .Infof ("Bucket %s does not exits" , bucketName )
130- err = noBucket
131- } else {
132- klog .Infof ("Couldn't delete bucket %s. Reason: %v" , bucketName , err )
133- }
134- } else {
135- err = s3 .NewBucketNotExistsWaiter (client .S3Client ).Wait (
136- ctx , & s3.HeadBucketInput {
137- Bucket : aws .String (bucketName ),
138- },
139- time .Minute )
140- if err != nil {
141- klog .Infof ("Failed attempt to wait for bucket %s to be deleted" , bucketName )
136+ klog .Infof ("Bucket %s does not exits." , bucketName )
137+
138+ return nil
142139 } else {
143- klog .Infof ("Bucket %s deleted" , bucketName )
140+ klog .Infof ("Couldn't delete bucket %s, err: %v" , bucketName , err )
141+
142+ return fmt .Errorf ("deleting bucket %s: %w" , bucketName , err )
144143 }
145144 }
146- return err
145+
146+ err = s3 .NewBucketNotExistsWaiter (c .s3Client ).Wait (
147+ ctx , & s3.HeadBucketInput {
148+ Bucket : aws .String (bucketName ),
149+ },
150+ time .Minute )
151+ if err != nil {
152+ klog .Infof ("Failed attempt to wait for bucket %s to be deleted, err: %v" , bucketName , err )
153+
154+ return fmt .Errorf ("waiting for bucket %s to be deleted, err: %w" , bucketName , err )
155+ }
156+
157+ klog .Infof ("Bucket %s deleted" , bucketName )
158+
159+ return nil
147160}
148161
149- func (client awsClient ) setPublicReadPolicy (ctx context.Context , bucketName string ) error {
162+ func (c Client ) setPublicReadPolicy (ctx context.Context , bucketName string ) error {
150163 policy := fmt .Sprintf (`{
151164 "Version": "2012-10-17",
152165 "Statement": [
@@ -160,13 +173,13 @@ func (client awsClient) setPublicReadPolicy(ctx context.Context, bucketName stri
160173 ]
161174 }` , bucketName )
162175
163- _ , err := client . S3Client .PutBucketPolicy (ctx , & s3.PutBucketPolicyInput {
176+ _ , err := c . s3Client .PutBucketPolicy (ctx , & s3.PutBucketPolicyInput {
164177 Bucket : aws .String (bucketName ),
165178 Policy : aws .String (policy ),
166179 })
167180 if err != nil {
168- return fmt .Errorf ("failed to put bucket policy for %s: %w" , bucketName , err )
181+ return fmt .Errorf ("putting bucket policy for %s: %w" , bucketName , err )
169182 }
170183
171- return err
184+ return nil
172185}
0 commit comments