mirror of
https://github.com/SAP/jenkins-library.git
synced 2024-12-16 11:09:33 +02:00
143 lines
4.4 KiB
Go
143 lines
4.4 KiB
Go
|
package cmd
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"encoding/json"
|
||
|
"os"
|
||
|
"path/filepath"
|
||
|
|
||
|
"github.com/SAP/jenkins-library/pkg/log"
|
||
|
"github.com/SAP/jenkins-library/pkg/telemetry"
|
||
|
|
||
|
"github.com/aws/aws-sdk-go-v2/config"
|
||
|
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||
|
)
|
||
|
|
||
|
// S3PutObjectAPI defines the interface for the PutObject function.
|
||
|
// We use this interface to test the function using a mocked service.
|
||
|
type S3PutObjectAPI interface {
|
||
|
PutObject(ctx context.Context,
|
||
|
params *s3.PutObjectInput,
|
||
|
optFns ...func(*s3.Options)) (*s3.PutObjectOutput, error)
|
||
|
}
|
||
|
|
||
|
// PutFile uploads a file to an AWS S3 bucket
|
||
|
// The function needs a context (including the AWS Region) and a PutObjectInput for the service call
|
||
|
// The return value is a PutObjectOutput with the result of the upload
|
||
|
func PutFile(c context.Context, api S3PutObjectAPI, input *s3.PutObjectInput) (*s3.PutObjectOutput, error) {
|
||
|
return api.PutObject(c, input)
|
||
|
}
|
||
|
|
||
|
// Struct to store the AWS credentials from a specified JSON string
|
||
|
type awsCredentials struct {
|
||
|
AwsAccessKeyID string `json:"access_key_id"`
|
||
|
Bucket string `json:"bucket"`
|
||
|
AwsSecretAccessKey string `json:"secret_access_key"`
|
||
|
AwsRegion string `json:"region"`
|
||
|
}
|
||
|
|
||
|
func awsS3Upload(configOptions awsS3UploadOptions, telemetryData *telemetry.CustomData) {
|
||
|
// Prepare Credentials
|
||
|
log.Entry().Infoln("Start reading AWS Credentials")
|
||
|
var obj awsCredentials
|
||
|
|
||
|
err := json.Unmarshal([]byte(configOptions.JSONCredentialsAWS), &obj)
|
||
|
if err != nil {
|
||
|
log.Entry().
|
||
|
WithError(err).
|
||
|
Fatal("Could not read JSONCredentialsAWS")
|
||
|
}
|
||
|
|
||
|
// Set environment variables which are needed to initialize S3 Client
|
||
|
log.Entry().Infoln("Successfully read AWS Credentials. Setting up environment variables")
|
||
|
awsRegionSet := setenvIfEmpty("AWS_REGION", obj.AwsRegion)
|
||
|
awsAccessKeyIDSet := setenvIfEmpty("AWS_ACCESS_KEY_ID", obj.AwsAccessKeyID)
|
||
|
awsSecretAccessKeySet := setenvIfEmpty("AWS_SECRET_ACCESS_KEY", obj.AwsSecretAccessKey)
|
||
|
|
||
|
defer removeEnvIfPreviouslySet("AWS_REGION", awsRegionSet)
|
||
|
defer removeEnvIfPreviouslySet("AWS_ACCESS_KEY_ID", awsAccessKeyIDSet)
|
||
|
defer removeEnvIfPreviouslySet("AWS_SECRET_ACCESS_KEY", awsSecretAccessKeySet)
|
||
|
|
||
|
// Initialize S3 Client
|
||
|
log.Entry().Infoln("Loading Configuration for S3 Client")
|
||
|
cfg, err := config.LoadDefaultConfig(context.TODO())
|
||
|
if err != nil {
|
||
|
log.Entry().
|
||
|
WithError(err).
|
||
|
Fatal("AWS Client Configuration failed")
|
||
|
}
|
||
|
client := s3.NewFromConfig(cfg)
|
||
|
|
||
|
err = runAwsS3Upload(&configOptions, client, obj.Bucket)
|
||
|
if err != nil {
|
||
|
log.Entry().WithError(err).Fatal("Step execution failed")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func runAwsS3Upload(configOptions *awsS3UploadOptions, client S3PutObjectAPI, bucket string) error {
|
||
|
// Iterate through directories
|
||
|
err := filepath.Walk(configOptions.FilePath, func(currentFilePath string, f os.FileInfo, err error) error {
|
||
|
// Handle Failure to prevent panic (e.g. in case of an invalid filepath)
|
||
|
if err != nil {
|
||
|
log.Entry().WithError(err).Warnf("Failed to access path: '%v'", currentFilePath)
|
||
|
return err
|
||
|
}
|
||
|
// Skip directories, only upload files
|
||
|
if !f.IsDir() {
|
||
|
log.Entry().Infof("Current target path is: '%v'", currentFilePath)
|
||
|
|
||
|
// Open File
|
||
|
currentFile, e := os.Open(currentFilePath)
|
||
|
if e != nil {
|
||
|
log.Entry().WithError(e).Warnf("Could not open the file '%s'", currentFilePath)
|
||
|
return e
|
||
|
}
|
||
|
defer currentFile.Close()
|
||
|
|
||
|
// AWS SDK needs UNIX file paths to automatically create directories
|
||
|
key := filepath.ToSlash(currentFilePath)
|
||
|
|
||
|
// Intitialize S3 PutObjectInput
|
||
|
inputObject := &s3.PutObjectInput{
|
||
|
Bucket: &bucket,
|
||
|
Key: &key,
|
||
|
Body: currentFile,
|
||
|
}
|
||
|
|
||
|
// Upload File
|
||
|
log.Entry().Infof("Start upload of file '%v'", currentFilePath)
|
||
|
_, e = PutFile(context.TODO(), client, inputObject)
|
||
|
if e != nil {
|
||
|
log.Entry().WithError(e).Warnf("There was an error during the upload of file '%v'", currentFilePath)
|
||
|
return e
|
||
|
}
|
||
|
|
||
|
log.Entry().Infof("Upload of file '%v' was successful!", currentFilePath)
|
||
|
return e
|
||
|
}
|
||
|
return nil
|
||
|
})
|
||
|
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
log.Entry().Infoln("Upload has successfully finished!")
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// Function to set environment variables if they are not already set
|
||
|
func setenvIfEmpty(env, val string) bool {
|
||
|
if len(os.Getenv(env)) == 0 {
|
||
|
os.Setenv(env, val)
|
||
|
return true
|
||
|
}
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
// Function to remove environment variables if they are set
|
||
|
func removeEnvIfPreviouslySet(env string, previouslySet bool) {
|
||
|
if previouslySet {
|
||
|
os.Setenv(env, "")
|
||
|
}
|
||
|
}
|