summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/minio/minio-go/api-put-bucket.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/minio/minio-go/api-put-bucket.go')
-rw-r--r--vendor/github.com/minio/minio-go/api-put-bucket.go134
1 files changed, 98 insertions, 36 deletions
diff --git a/vendor/github.com/minio/minio-go/api-put-bucket.go b/vendor/github.com/minio/minio-go/api-put-bucket.go
index 7c7e03f49..2d91e6d16 100644
--- a/vendor/github.com/minio/minio-go/api-put-bucket.go
+++ b/vendor/github.com/minio/minio-go/api-put-bucket.go
@@ -1,5 +1,6 @@
/*
- * Minio Go Library for Amazon S3 Compatible Cloud Storage (C) 2015, 2016 Minio, Inc.
+ * Minio Go Library for Amazon S3 Compatible Cloud Storage
+ * (C) 2015, 2016, 2017 Minio, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,6 +29,7 @@ import (
"net/url"
"path"
+ "github.com/minio/minio-go/pkg/credentials"
"github.com/minio/minio-go/pkg/policy"
"github.com/minio/minio-go/pkg/s3signer"
)
@@ -41,7 +43,14 @@ import (
//
// For Amazon S3 for more supported regions - http://docs.aws.amazon.com/general/latest/gr/rande.html
// For Google Cloud Storage for more supported regions - https://cloud.google.com/storage/docs/bucket-locations
-func (c Client) MakeBucket(bucketName string, location string) error {
+func (c Client) MakeBucket(bucketName string, location string) (err error) {
+ defer func() {
+ // Save the location into cache on a successful makeBucket response.
+ if err == nil {
+ c.bucketLocCache.Set(bucketName, location)
+ }
+ }()
+
// Validate the input arguments.
if err := isValidBucketName(bucketName); err != nil {
return err
@@ -52,45 +61,70 @@ func (c Client) MakeBucket(bucketName string, location string) error {
location = "us-east-1"
}
- // Instantiate the request.
- req, err := c.makeBucketRequest(bucketName, location)
- if err != nil {
- return err
- }
+ // Try creating bucket with the provided region, in case of
+ // invalid region error let's guess the appropriate region
+ // from S3 API headers
- // Execute the request.
- resp, err := c.do(req)
- defer closeResponse(resp)
- if err != nil {
- return err
- }
+ // Create a done channel to control 'newRetryTimer' go routine.
+ doneCh := make(chan struct{}, 1)
+
+ // Indicate to our routine to exit cleanly upon return.
+ defer close(doneCh)
+
+ // Blank indentifier is kept here on purpose since 'range' without
+ // blank identifiers is only supported since go1.4
+ // https://golang.org/doc/go1.4#forrange.
+ for _ = range c.newRetryTimer(MaxRetry, DefaultRetryUnit, DefaultRetryCap, MaxJitter, doneCh) {
+ // Initialize the makeBucket request.
+ req, err := c.makeBucketRequest(bucketName, location)
+ if err != nil {
+ return err
+ }
+
+ // Execute make bucket request.
+ resp, err := c.do(req)
+ defer closeResponse(resp)
+ if err != nil {
+ return err
+ }
- if resp != nil {
if resp.StatusCode != http.StatusOK {
- return httpRespToErrorResponse(resp, bucketName, "")
+ err := httpRespToErrorResponse(resp, bucketName, "")
+ errResp := ToErrorResponse(err)
+ if resp.StatusCode == http.StatusBadRequest && errResp.Region != "" {
+ // Fetch bucket region found in headers
+ // of S3 error response, attempt bucket
+ // create again.
+ location = errResp.Region
+ continue
+ }
+ // Nothing to retry, fail.
+ return err
}
- }
- // Save the location into cache on a successful makeBucket response.
- c.bucketLocCache.Set(bucketName, location)
+ // Control reaches here when bucket create was successful,
+ // break out.
+ break
+ }
- // Return.
+ // Success.
return nil
}
-// makeBucketRequest constructs request for makeBucket.
+// Low level wrapper API For makeBucketRequest.
func (c Client) makeBucketRequest(bucketName string, location string) (*http.Request, error) {
// Validate input arguments.
if err := isValidBucketName(bucketName); err != nil {
return nil, err
}
- // In case of Amazon S3. The make bucket issued on already
- // existing bucket would fail with 'AuthorizationMalformed' error
- // if virtual style is used. So we default to 'path style' as that
- // is the preferred method here. The final location of the
- // 'bucket' is provided through XML LocationConstraint data with
- // the request.
+ // In case of Amazon S3. The make bucket issued on
+ // already existing bucket would fail with
+ // 'AuthorizationMalformed' error if virtual style is
+ // used. So we default to 'path style' as that is the
+ // preferred method here. The final location of the
+ // 'bucket' is provided through XML LocationConstraint
+ // data with the request.
targetURL := c.endpointURL
targetURL.Path = path.Join(bucketName, "") + "/"
@@ -103,8 +137,32 @@ func (c Client) makeBucketRequest(bucketName string, location string) (*http.Req
// set UserAgent for the request.
c.setUserAgent(req)
+ // Get credentials from the configured credentials provider.
+ value, err := c.credsProvider.Get()
+ if err != nil {
+ return nil, err
+ }
+
+ var (
+ signerType = value.SignerType
+ accessKeyID = value.AccessKeyID
+ secretAccessKey = value.SecretAccessKey
+ sessionToken = value.SessionToken
+ )
+
+ // Custom signer set then override the behavior.
+ if c.overrideSignerType != credentials.SignatureDefault {
+ signerType = c.overrideSignerType
+ }
+
+ // If signerType returned by credentials helper is anonymous,
+ // then do not sign regardless of signerType override.
+ if value.SignerType == credentials.SignatureAnonymous {
+ signerType = credentials.SignatureAnonymous
+ }
+
// set sha256 sum for signature calculation only with signature version '4'.
- if c.signature.isV4() {
+ if signerType.IsV4() {
req.Header.Set("X-Amz-Content-Sha256", hex.EncodeToString(sum256([]byte{})))
}
@@ -122,19 +180,19 @@ func (c Client) makeBucketRequest(bucketName string, location string) (*http.Req
req.ContentLength = int64(len(createBucketConfigBytes))
// Set content-md5.
req.Header.Set("Content-Md5", base64.StdEncoding.EncodeToString(sumMD5(createBucketConfigBytes)))
- if c.signature.isV4() {
+ if signerType.IsV4() {
// Set sha256.
req.Header.Set("X-Amz-Content-Sha256", hex.EncodeToString(sum256(createBucketConfigBytes)))
}
}
// Sign the request.
- if c.signature.isV4() {
+ if signerType.IsV4() {
// Signature calculated for MakeBucket request should be for 'us-east-1',
// regardless of the bucket's location constraint.
- req = s3signer.SignV4(*req, c.accessKeyID, c.secretAccessKey, "us-east-1")
- } else if c.signature.isV2() {
- req = s3signer.SignV2(*req, c.accessKeyID, c.secretAccessKey)
+ req = s3signer.SignV4(*req, accessKeyID, secretAccessKey, sessionToken, "us-east-1")
+ } else if signerType.IsV2() {
+ req = s3signer.SignV2(*req, accessKeyID, secretAccessKey)
}
// Return signed request.
@@ -157,11 +215,14 @@ func (c Client) SetBucketPolicy(bucketName string, objectPrefix string, bucketPo
if err := isValidObjectPrefix(objectPrefix); err != nil {
return err
}
+
if !bucketPolicy.IsValidBucketPolicy() {
return ErrInvalidArgument(fmt.Sprintf("Invalid bucket policy provided. %s", bucketPolicy))
}
- policyInfo, err := c.getBucketPolicy(bucketName, objectPrefix)
- if err != nil {
+
+ policyInfo, err := c.getBucketPolicy(bucketName)
+ errResponse := ToErrorResponse(err)
+ if err != nil && errResponse.Code != "NoSuchBucketPolicy" {
return err
}
@@ -236,8 +297,9 @@ func (c Client) removeBucketPolicy(bucketName string) error {
// Execute DELETE on objectName.
resp, err := c.executeMethod("DELETE", requestMetadata{
- bucketName: bucketName,
- queryValues: urlValues,
+ bucketName: bucketName,
+ queryValues: urlValues,
+ contentSHA256Bytes: emptySHA256,
})
defer closeResponse(resp)
if err != nil {