From e4541a7fd1c4aa7abc0d4abbee27c8dcb045b48c Mon Sep 17 00:00:00 2001 From: Ricard Clau Date: Wed, 4 Oct 2017 21:04:20 +0200 Subject: [PATCH] support for s3 path (#9151) --- conf/defaults.ini | 1 + conf/sample.ini | 1 + docs/sources/installation/configuration.md | 5 +++++ pkg/components/imguploader/imguploader.go | 8 +++++++- pkg/components/imguploader/s3uploader.go | 6 ++++-- 5 files changed, 18 insertions(+), 3 deletions(-) diff --git a/conf/defaults.ini b/conf/defaults.ini index dfa6bf99017..14e77449241 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -479,6 +479,7 @@ provider = bucket_url = bucket = region = +path = access_key = secret_key = diff --git a/conf/sample.ini b/conf/sample.ini index 89170000df6..1aedfbf6532 100644 --- a/conf/sample.ini +++ b/conf/sample.ini @@ -424,6 +424,7 @@ [external_image_storage.s3] ;bucket = ;region = +;path = ;access_key = ;secret_key = diff --git a/docs/sources/installation/configuration.md b/docs/sources/installation/configuration.md index 85ff1026c10..6630825e803 100644 --- a/docs/sources/installation/configuration.md +++ b/docs/sources/installation/configuration.md @@ -651,11 +651,16 @@ These options control how images should be made public so they can be shared on You can choose between (s3, webdav, gcs). If left empty Grafana will ignore the upload action. ## [external_image_storage.s3] + ### bucket Bucket name for S3. e.g. grafana.snapshot + ### region Region name for S3. e.g. 'us-east-1', 'cn-north-1', etc +### path +Optional extra path inside bucket, useful to apply expiration policies + ### bucket_url (for backward compatibility, only works when no bucket or region are configured) Bucket URL for S3. AWS region can be specified within URL or defaults to 'us-east-1', e.g. diff --git a/pkg/components/imguploader/imguploader.go b/pkg/components/imguploader/imguploader.go index 1feeb6f07c3..728614735d0 100644 --- a/pkg/components/imguploader/imguploader.go +++ b/pkg/components/imguploader/imguploader.go @@ -30,9 +30,15 @@ func NewImageUploader() (ImageUploader, error) { bucket := s3sec.Key("bucket").MustString("") region := s3sec.Key("region").MustString("") + path := s3sec.Key("path").MustString("") bucketUrl := s3sec.Key("bucket_url").MustString("") accessKey := s3sec.Key("access_key").MustString("") secretKey := s3sec.Key("secret_key").MustString("") + + if path != "" && path[len(path)-1:] != "/" { + path += "/" + } + if bucket == "" || region == "" { info, err := getRegionAndBucketFromUrl(bucketUrl) if err != nil { @@ -42,7 +48,7 @@ func NewImageUploader() (ImageUploader, error) { region = info.region } - return NewS3Uploader(region, bucket, "public-read", accessKey, secretKey), nil + return NewS3Uploader(region, bucket, path, "public-read", accessKey, secretKey), nil case "webdav": webdavSec, err := setting.Cfg.GetSection("external_image_storage.webdav") if err != nil { diff --git a/pkg/components/imguploader/s3uploader.go b/pkg/components/imguploader/s3uploader.go index 860bb1a1abd..62196357c61 100644 --- a/pkg/components/imguploader/s3uploader.go +++ b/pkg/components/imguploader/s3uploader.go @@ -19,16 +19,18 @@ import ( type S3Uploader struct { region string bucket string + path string acl string secretKey string accessKey string log log.Logger } -func NewS3Uploader(region, bucket, acl, accessKey, secretKey string) *S3Uploader { +func NewS3Uploader(region, bucket, path, acl, accessKey, secretKey string) *S3Uploader { return &S3Uploader{ region: region, bucket: bucket, + path: path, acl: acl, accessKey: accessKey, secretKey: secretKey, @@ -56,7 +58,7 @@ func (u *S3Uploader) Upload(ctx context.Context, imageDiskPath string) (string, } s3_endpoint, _ := endpoints.DefaultResolver().EndpointFor("s3", u.region) - key := util.GetRandomString(20) + ".png" + key := u.path + util.GetRandomString(20) + ".png" image_url := s3_endpoint.URL + "/" + u.bucket + "/" + key log.Debug("Uploading image to s3", "url = ", image_url)