mirror of
https://github.com/SAP/jenkins-library.git
synced 2024-12-14 11:03:09 +02:00
cd243ee542
* Upload reports to Google Cloud Storage bucket * Added tests. Made fixes * Update step generation. GCS client was moved to GeneralConfig * Code was refactored * Fixed issues * Fixed issues * Code correction due to PR comments * Improved gcs client and integration tests * Integrated gcp config. Updated step metadata * Fixed issues. Added tests * Added cpe, vault, aliases resolving for reporting parameters * Added tests * Uncommented DeferExitHandler. Removed useless comments * fixed cloning of config * Added comments for exported functions. Removed unused mock * minor fix * Implemented setting of report name via paramRef * some refactoring. Writing tests * Update pkg/config/reporting.go * Update cmd/sonarExecuteScan_generated.go * Apply suggestions from code review * Update pkg/config/reporting.go * Update pkg/config/reporting.go * fixed removing valut secret files * Update pkg/config/reporting.go * restore order * restore order * Apply suggestions from code review * go generate * fixed tests * Update resources/metadata/sonarExecuteScan.yaml * Update resources.go * Fixed tests. Code was regenerated * changed somewhere gcp to gcs. Fixed one test * move gcsSubFolder to input parameters * fixed removing valut secret files * minor fix in integration tests * fix integration tests Co-authored-by: Oliver Nocon <33484802+OliverNocon@users.noreply.github.com> Co-authored-by: Christopher Fenner <26137398+CCFenner@users.noreply.github.com> Co-authored-by: Sven Merk <33895725+nevskrem@users.noreply.github.com>
221 lines
5.7 KiB
Go
221 lines
5.7 KiB
Go
package gcs
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"cloud.google.com/go/storage"
|
|
"github.com/SAP/jenkins-library/pkg/log"
|
|
"github.com/pkg/errors"
|
|
"google.golang.org/api/iterator"
|
|
"google.golang.org/api/option"
|
|
)
|
|
|
|
// Client is an interface to mock gcsClient
|
|
type Client interface {
|
|
UploadFile(bucketID string, sourcePath string, targetPath string) error
|
|
DownloadFile(bucketID string, sourcePath string, targetPath string) error
|
|
ListFiles(bucketID string) ([]string, error)
|
|
Close() error
|
|
}
|
|
|
|
// gcsClient provides functions to interact with google cloud storage API
|
|
type gcsClient struct {
|
|
context context.Context
|
|
envVars []EnvVar
|
|
client storage.Client
|
|
clientOptions []option.ClientOption
|
|
openFile func(name string) (io.ReadCloser, error)
|
|
createFile func(name string) (io.WriteCloser, error)
|
|
}
|
|
|
|
// EnvVar defines an environment variable incl. information about a potential modification to the variable
|
|
type EnvVar struct {
|
|
Name string
|
|
Value string
|
|
Modified bool
|
|
}
|
|
|
|
type gcsOption func(*gcsClient)
|
|
|
|
// WithEnvVars initializes env variables in gcsClient
|
|
func WithEnvVars(envVars []EnvVar) gcsOption {
|
|
return func(g *gcsClient) {
|
|
g.envVars = envVars
|
|
}
|
|
}
|
|
|
|
// WithEnvVars initializes the openFile function in gcsClient
|
|
func WithOpenFileFunction(openFile func(name string) (io.ReadCloser, error)) gcsOption {
|
|
return func(g *gcsClient) {
|
|
g.openFile = openFile
|
|
}
|
|
}
|
|
|
|
// WithEnvVars initializes the createFile function in gcsClient
|
|
func WithCreateFileFunction(createFile func(name string) (io.WriteCloser, error)) gcsOption {
|
|
return func(g *gcsClient) {
|
|
g.createFile = createFile
|
|
}
|
|
}
|
|
|
|
// WithEnvVars initializes the Google Cloud Storage client options
|
|
func WithClientOptions(opts ...option.ClientOption) gcsOption {
|
|
return func(g *gcsClient) {
|
|
g.clientOptions = append(g.clientOptions, opts...)
|
|
}
|
|
}
|
|
|
|
// Init intitializes the google cloud storage client
|
|
func NewClient(opts ...gcsOption) (*gcsClient, error) {
|
|
var (
|
|
defaultOpenFile = openFileFromFS
|
|
defaultCreateFile = createFileOnFS
|
|
)
|
|
|
|
ctx := context.Background()
|
|
gcsClient := &gcsClient{
|
|
context: ctx,
|
|
openFile: defaultOpenFile,
|
|
createFile: defaultCreateFile,
|
|
}
|
|
|
|
// options handling
|
|
for _, opt := range opts {
|
|
opt(gcsClient)
|
|
}
|
|
|
|
gcsClient.prepareEnv()
|
|
client, err := storage.NewClient(ctx, gcsClient.clientOptions...)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "bucket connection failed: %v", err)
|
|
}
|
|
gcsClient.client = *client
|
|
return gcsClient, nil
|
|
}
|
|
|
|
// UploadFile uploads a file into a google cloud storage bucket
|
|
func (g *gcsClient) UploadFile(bucketID string, sourcePath string, targetPath string) error {
|
|
target := g.client.Bucket(bucketID).Object(targetPath).NewWriter(g.context)
|
|
log.Entry().Debugf("uploading %v to %v\n", sourcePath, targetPath)
|
|
sourceFile, err := g.openFile(sourcePath)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "could not open source file: %v", err)
|
|
}
|
|
defer sourceFile.Close()
|
|
|
|
if err := g.copy(sourceFile, target); err != nil {
|
|
return errors.Wrapf(err, "upload failed: %v", err)
|
|
}
|
|
|
|
if err := target.Close(); err != nil {
|
|
return errors.Wrapf(err, "closing bucket failed: %v", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// DownloadFile downloads a file from a google cloud storage bucket
|
|
func (g *gcsClient) DownloadFile(bucketID string, sourcePath string, targetPath string) error {
|
|
log.Entry().Debugf("downloading %v to %v\n", sourcePath, targetPath)
|
|
gcsReader, err := g.client.Bucket(bucketID).Object(sourcePath).NewReader(g.context)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "could not open source file from a google cloud storage bucket: %v", err)
|
|
}
|
|
|
|
targetWriter, err := g.createFile(targetPath)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "could not create target file: %v", err)
|
|
}
|
|
defer targetWriter.Close()
|
|
|
|
if err := g.copy(gcsReader, targetWriter); err != nil {
|
|
return errors.Wrapf(err, "download failed: %v", err)
|
|
}
|
|
if err := gcsReader.Close(); err != nil {
|
|
return errors.Wrapf(err, "closing bucket failed: %v", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ListFiles lists all files in certain GCS bucket
|
|
func (g *gcsClient) ListFiles(bucketID string) ([]string, error) {
|
|
fileNames := []string{}
|
|
it := g.client.Bucket(bucketID).Objects(g.context, nil)
|
|
for {
|
|
attrs, err := it.Next()
|
|
if err == iterator.Done {
|
|
break
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
fileNames = append(fileNames, attrs.Name)
|
|
}
|
|
return fileNames, nil
|
|
}
|
|
|
|
// Close closes the client and removes previously set environment variables
|
|
func (g *gcsClient) Close() error {
|
|
if err := g.client.Close(); err != nil {
|
|
return err
|
|
}
|
|
if err := g.cleanupEnv(); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (g *gcsClient) copy(source io.Reader, target io.Writer) error {
|
|
if _, err := io.Copy(target, source); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// prepareEnv sets required environment variables in case they are not set yet
|
|
func (g *gcsClient) prepareEnv() {
|
|
for key, env := range g.envVars {
|
|
g.envVars[key].Modified = setenvIfEmpty(env.Name, env.Value)
|
|
}
|
|
}
|
|
|
|
// cleanupEnv removes environment variables set by prepareEnv
|
|
func (g *gcsClient) cleanupEnv() error {
|
|
for _, env := range g.envVars {
|
|
if err := removeEnvIfPreviouslySet(env.Name, env.Modified); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func setenvIfEmpty(env, val string) bool {
|
|
if len(os.Getenv(env)) == 0 {
|
|
os.Setenv(env, val)
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func removeEnvIfPreviouslySet(env string, previouslySet bool) error {
|
|
if previouslySet {
|
|
if err := os.Setenv(env, ""); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func openFileFromFS(name string) (io.ReadCloser, error) {
|
|
return os.Open(name)
|
|
}
|
|
|
|
func createFileOnFS(name string) (io.WriteCloser, error) {
|
|
if err := os.MkdirAll(filepath.Dir(name), os.ModePerm); err != nil {
|
|
return nil, err
|
|
}
|
|
return os.Create(name)
|
|
}
|