diff --git a/internal/pipe/blob/blob_minio_test.go b/internal/pipe/blob/blob_minio_test.go index 1a664ee43d3..b8d673a8183 100644 --- a/internal/pipe/blob/blob_minio_test.go +++ b/internal/pipe/blob/blob_minio_test.go @@ -36,6 +36,7 @@ func TestMinioUpload(t *testing.T) { { Provider: "s3", Bucket: "test", + Region: "us-east", Endpoint: "http://" + listen, IDs: []string{"foo", "bar"}, }, diff --git a/internal/pipe/blob/blob_test.go b/internal/pipe/blob/blob_test.go index 2ae59fab313..0bd22fe158f 100644 --- a/internal/pipe/blob/blob_test.go +++ b/internal/pipe/blob/blob_test.go @@ -241,6 +241,65 @@ func TestPipe_Publish(t *testing.T) { } } +func TestURL(t *testing.T) { + var buck = Bucket{} + + t.Run("s3 with opts", func(t *testing.T) { + url, err := buck.url(context.New(config.Project{}), config.Blob{ + Bucket: "foo", + Provider: "s3", + Region: "us-west-1", + Folder: "foo", + Endpoint: "s3.foobar.com", + DisableSSL: true, + }) + require.NoError(t, err) + require.Equal(t, "s3://foo?disableSSL=true&endpoint=s3.foobar.com®ion=us-west-1&s3ForcePathStyle=true", url) + }) + + t.Run("s3 with some opts", func(t *testing.T) { + url, err := buck.url(context.New(config.Project{}), config.Blob{ + Bucket: "foo", + Provider: "s3", + Region: "us-west-1", + DisableSSL: true, + }) + require.NoError(t, err) + require.Equal(t, "s3://foo?disableSSL=true®ion=us-west-1", url) + }) + + t.Run("gs with opts", func(t *testing.T) { + url, err := buck.url(context.New(config.Project{}), config.Blob{ + Bucket: "foo", + Provider: "gs", + Region: "us-west-1", + Folder: "foo", + Endpoint: "s3.foobar.com", + DisableSSL: true, + }) + require.NoError(t, err) + require.Equal(t, "gs://foo", url) + }) + + t.Run("s3 no opts", func(t *testing.T) { + url, err := buck.url(context.New(config.Project{}), config.Blob{ + Bucket: "foo", + Provider: "s3", + }) + require.NoError(t, err) + require.Equal(t, "s3://foo", url) + }) + + t.Run("gs no opts", func(t *testing.T) { + url, err := buck.url(context.New(config.Project{}), config.Blob{ + Bucket: "foo", + Provider: "gs", + }) + require.NoError(t, err) + require.Equal(t, "gs://foo", url) + }) +} + func setEnv(env map[string]string) { for k, v := range env { os.Setenv(k, v) diff --git a/internal/pipe/blob/openbucket.go b/internal/pipe/blob/openbucket.go index 0103f7bc63f..cee46c2e18a 100644 --- a/internal/pipe/blob/openbucket.go +++ b/internal/pipe/blob/openbucket.go @@ -3,6 +3,7 @@ package blob import ( "fmt" "io/ioutil" + "net/url" "path/filepath" "github.com/apex/log" @@ -51,22 +52,48 @@ func (b Bucket) Connect(ctx *context.Context, bucketURL string) (*blob.Bucket, e return conn, nil } -// Upload takes connection initilized from newOpenBucket to upload goreleaser artifacts -// Takes goreleaser context(which includes artificats) and bucketURL for upload destination (gs://gorelease-bucket) -func (b Bucket) Upload(ctx *context.Context, conf config.Blob) error { +func (b Bucket) url(ctx *context.Context, conf config.Blob) (string, error) { bucket, err := tmpl.New(ctx).Apply(conf.Bucket) if err != nil { - return err + return "", err + } + + bucketURL := fmt.Sprintf("%s://%s", conf.Provider, bucket) + + if conf.Provider != "s3" { + return bucketURL, nil + } + + var query = url.Values{} + if conf.Endpoint != "" { + query.Add("endpoint", conf.Endpoint) + query.Add("s3ForcePathStyle", "true") + } + if conf.Region != "" { + query.Add("region", conf.Region) } + if conf.DisableSSL { + query.Add("disableSSL", "true") + } + + if len(query) > 0 { + bucketURL = bucketURL + "?" + query.Encode() + } + + return bucketURL, nil +} +// Upload takes connection initilized from newOpenBucket to upload goreleaser artifacts +// Takes goreleaser context(which includes artificats) and bucketURL for upload destination (gs://gorelease-bucket) +func (b Bucket) Upload(ctx *context.Context, conf config.Blob) error { folder, err := tmpl.New(ctx).Apply(conf.Folder) if err != nil { return err } - var bucketURL = fmt.Sprintf("%s://%s", conf.Provider, bucket) - if conf.Endpoint != "" && conf.Provider == "s3" { - bucketURL = fmt.Sprintf("%s?endpoint=%s&s3ForcePathStyle=true", bucketURL, conf.Endpoint) + bucketURL, err := b.url(ctx, conf) + if err != nil { + return err } // Get the openbucket connection for specific provider @@ -97,6 +124,7 @@ func (b Bucket) Upload(ctx *context.Context, conf config.Blob) error { "artifact": artifact.Name, }).Info("uploading") + // TODO: replace this with ?prefix=folder on the bucket url w, err := conn.NewWriter(ctx, filepath.Join(folder, artifact.Name), nil) if err != nil { return errors.Wrap(err, "failed to obtain writer") diff --git a/pkg/config/config.go b/pkg/config/config.go index e9b3176db06..ad2a065acbd 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -325,12 +325,14 @@ type S3 struct { // Blob contains config for GO CDK blob type Blob struct { - Bucket string `yaml:",omitempty"` - Provider string `yaml:",omitempty"` - Folder string `yaml:",omitempty"` - KMSKey string `yaml:",omitempty"` - IDs []string `yaml:"ids,omitempty"` - Endpoint string `yaml:",omitempty"` // used for minio for example + Bucket string `yaml:",omitempty"` + Provider string `yaml:",omitempty"` + Region string `yaml:",omitempty"` + DisableSSL bool `yaml:"disableSSL,omitempty"` + Folder string `yaml:",omitempty"` + KMSKey string `yaml:",omitempty"` + IDs []string `yaml:"ids,omitempty"` + Endpoint string `yaml:",omitempty"` // used for minio for example } // Upload configuration diff --git a/www/content/blob.md b/www/content/blob.md index b6a63961145..baa205bf36b 100644 --- a/www/content/blob.md +++ b/www/content/blob.md @@ -23,6 +23,16 @@ blobs: # Implies s3ForcePathStyle and requires provider to be `s3` endpoint: https://minio.foo.bar + # Sets the bucket region. + # Requires provider to be `s3` + # Defaults to empty. + region: us-west-1 + + # Disables SSL + # Requires provider to be `s3` + # Defaults to false + disableSSL: true + # Template for the bucket name bucket: goreleaser-bucket