github.com/jaylevin/jenkins-library@v1.230.4/cmd/awsS3Upload.go (about) 1 package cmd 2 3 import ( 4 "context" 5 "encoding/json" 6 "os" 7 "path/filepath" 8 9 "github.com/SAP/jenkins-library/pkg/log" 10 "github.com/SAP/jenkins-library/pkg/telemetry" 11 12 "github.com/aws/aws-sdk-go-v2/config" 13 "github.com/aws/aws-sdk-go-v2/service/s3" 14 ) 15 16 // S3PutObjectAPI defines the interface for the PutObject function. 17 // We use this interface to test the function using a mocked service. 18 type S3PutObjectAPI interface { 19 PutObject(ctx context.Context, 20 params *s3.PutObjectInput, 21 optFns ...func(*s3.Options)) (*s3.PutObjectOutput, error) 22 } 23 24 // PutFile uploads a file to an AWS S3 bucket 25 // The function needs a context (including the AWS Region) and a PutObjectInput for the service call 26 // The return value is a PutObjectOutput with the result of the upload 27 func PutFile(c context.Context, api S3PutObjectAPI, input *s3.PutObjectInput) (*s3.PutObjectOutput, error) { 28 return api.PutObject(c, input) 29 } 30 31 // Struct to store the AWS credentials from a specified JSON string 32 type awsCredentials struct { 33 AwsAccessKeyID string `json:"access_key_id"` 34 Bucket string `json:"bucket"` 35 AwsSecretAccessKey string `json:"secret_access_key"` 36 AwsRegion string `json:"region"` 37 } 38 39 func awsS3Upload(configOptions awsS3UploadOptions, telemetryData *telemetry.CustomData) { 40 // Prepare Credentials 41 log.Entry().Infoln("Start reading AWS Credentials") 42 var obj awsCredentials 43 44 err := json.Unmarshal([]byte(configOptions.JSONCredentialsAWS), &obj) 45 if err != nil { 46 log.Entry(). 47 WithError(err). 48 Fatal("Could not read JSONCredentialsAWS") 49 } 50 51 // Set environment variables which are needed to initialize S3 Client 52 log.Entry().Infoln("Successfully read AWS Credentials. Setting up environment variables") 53 awsRegionSet := setenvIfEmpty("AWS_REGION", obj.AwsRegion) 54 awsAccessKeyIDSet := setenvIfEmpty("AWS_ACCESS_KEY_ID", obj.AwsAccessKeyID) 55 awsSecretAccessKeySet := setenvIfEmpty("AWS_SECRET_ACCESS_KEY", obj.AwsSecretAccessKey) 56 57 defer removeEnvIfPreviouslySet("AWS_REGION", awsRegionSet) 58 defer removeEnvIfPreviouslySet("AWS_ACCESS_KEY_ID", awsAccessKeyIDSet) 59 defer removeEnvIfPreviouslySet("AWS_SECRET_ACCESS_KEY", awsSecretAccessKeySet) 60 61 // Initialize S3 Client 62 log.Entry().Infoln("Loading Configuration for S3 Client") 63 cfg, err := config.LoadDefaultConfig(context.TODO()) 64 if err != nil { 65 log.Entry(). 66 WithError(err). 67 Fatal("AWS Client Configuration failed") 68 } 69 client := s3.NewFromConfig(cfg) 70 71 err = runAwsS3Upload(&configOptions, client, obj.Bucket) 72 if err != nil { 73 log.Entry().WithError(err).Fatal("Step execution failed") 74 } 75 } 76 77 func runAwsS3Upload(configOptions *awsS3UploadOptions, client S3PutObjectAPI, bucket string) error { 78 // Iterate through directories 79 err := filepath.Walk(configOptions.FilePath, func(currentFilePath string, f os.FileInfo, err error) error { 80 // Handle Failure to prevent panic (e.g. in case of an invalid filepath) 81 if err != nil { 82 log.Entry().WithError(err).Warnf("Failed to access path: '%v'", currentFilePath) 83 return err 84 } 85 // Skip directories, only upload files 86 if !f.IsDir() { 87 log.Entry().Infof("Current target path is: '%v'", currentFilePath) 88 89 // Open File 90 currentFile, e := os.Open(currentFilePath) 91 if e != nil { 92 log.Entry().WithError(e).Warnf("Could not open the file '%s'", currentFilePath) 93 return e 94 } 95 defer currentFile.Close() 96 97 // AWS SDK needs UNIX file paths to automatically create directories 98 key := filepath.ToSlash(currentFilePath) 99 100 // Intitialize S3 PutObjectInput 101 inputObject := &s3.PutObjectInput{ 102 Bucket: &bucket, 103 Key: &key, 104 Body: currentFile, 105 } 106 107 // Upload File 108 log.Entry().Infof("Start upload of file '%v'", currentFilePath) 109 _, e = PutFile(context.TODO(), client, inputObject) 110 if e != nil { 111 log.Entry().WithError(e).Warnf("There was an error during the upload of file '%v'", currentFilePath) 112 return e 113 } 114 115 log.Entry().Infof("Upload of file '%v' was successful!", currentFilePath) 116 return e 117 } 118 return nil 119 }) 120 121 if err != nil { 122 return err 123 } 124 log.Entry().Infoln("Upload has successfully finished!") 125 return err 126 } 127 128 // Function to set environment variables if they are not already set 129 func setenvIfEmpty(env, val string) bool { 130 if len(os.Getenv(env)) == 0 { 131 os.Setenv(env, val) 132 return true 133 } 134 return false 135 } 136 137 // Function to remove environment variables if they are set 138 func removeEnvIfPreviouslySet(env string, previouslySet bool) { 139 if previouslySet { 140 os.Setenv(env, "") 141 } 142 }