Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add access point api #389

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 186 additions & 0 deletions oss/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2632,6 +2632,192 @@ func (client Client) DeleteBucketResponseHeader(bucketName string, options ...Op
return CheckRespCode(resp.StatusCode, []int{http.StatusNoContent})
}

// CreateBucketAccessPoint create access point for bucket
// bucketName the bucket name.
// create CreateBucketAccessPoint.
// CreateBucketAccessPointResult response in struct format.
// error it's nil if no error, otherwise it's an error object.
func (client Client) CreateBucketAccessPoint(bucketName string, create CreateBucketAccessPoint, options ...Option) (CreateBucketAccessPointResult, error) {
var out CreateBucketAccessPointResult
bs, err := xml.Marshal(create)
if err != nil {
return out, err
}
body, err := client.CreateBucketAccessPointXml(bucketName, string(bs), options...)
if err != nil {
return out, err
}
err = xmlUnmarshal(strings.NewReader(body), &out)
return out, err
}

// CreateBucketAccessPointXml map a custom domain name to a bucket
// bucketName the bucket name.
// xmlBody the cname configuration in xml format
// error it's nil if no error, otherwise it's an error object.
func (client Client) CreateBucketAccessPointXml(bucketName string, xmlBody string, options ...Option) (string, error) {
params := map[string]interface{}{}
params["accessPoint"] = nil

buffer := new(bytes.Buffer)
buffer.Write([]byte(xmlBody))
contentType := http.DetectContentType(buffer.Bytes())
headers := map[string]string{}
headers[HTTPHeaderContentType] = contentType

resp, err := client.do("PUT", bucketName, params, headers, buffer, options...)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
out := string(body)
return out, err
}

// GetBucketAccessPoint get access point for bucket
// bucketName the bucket name.
// GetBucketAccessPointResult result in struct format.
// error it's nil if no error, otherwise it's an error object.
func (client Client) GetBucketAccessPoint(bucketName, apName string, options ...Option) (GetBucketAccessPointResult, error) {
var out GetBucketAccessPointResult
body, err := client.GetBucketAccessPointXml(bucketName, apName, options...)
if err != nil {
return out, err
}
err = xmlUnmarshal(strings.NewReader(body), &out)
return out, err
}

// GetBucketAccessPointXml get bucket's access point
// bucketName the bucket name.
// string the access point of bucket in xml format.
// error it's nil if no error, otherwise it's an error object.
func (client Client) GetBucketAccessPointXml(bucketName, apName string, options ...Option) (string, error) {
params := map[string]interface{}{}
params["accessPoint"] = nil
headers := map[string]string{}
headers[HTTPHeaderOssAccessPointName] = apName
resp, err := client.do("GET", bucketName, params, headers, nil, options...)
defer resp.Body.Close()
if err != nil {
return "", err
}
body, err := ioutil.ReadAll(resp.Body)
out := string(body)
return out, err
}

// DeleteBucketAccessPoint delete bucket's access point
// bucketName the bucket name.
// apName the access point name.
// error it's nil if no error, otherwise it's an error object.
func (client Client) DeleteBucketAccessPoint(bucketName, apName string, options ...Option) error {
params := map[string]interface{}{}
params["accessPoint"] = nil
headers := map[string]string{}
headers[HTTPHeaderOssAccessPointName] = apName
resp, err := client.do("DELETE", bucketName, params, headers, nil, options...)
if err != nil {
return err
}
defer resp.Body.Close()
return CheckRespCode(resp.StatusCode, []int{http.StatusNoContent})
}

// ListBucketAccessPointXml get bucket's access point list
// bucketName the bucket name.
// string the access point of bucket in xml format.
// error it's nil if no error, otherwise it's an error object.
func (client Client) ListBucketAccessPoint(bucketName string, options ...Option) (ListBucketAccessPointsResult, error) {
var out ListBucketAccessPointsResult
body, err := client.ListBucketAccessPointXml(bucketName, options...)
if err != nil {
return out, err
}
err = xmlUnmarshal(strings.NewReader(body), &out)
return out, err
}

// ListBucketAccessPointXml get bucket's access point list
// bucketName the bucket name.
// string the access point of bucket in xml format.
// error it's nil if no error, otherwise it's an error object.
func (client Client) ListBucketAccessPointXml(bucketName string, options ...Option) (string, error) {
params, err := GetRawParams(options)
if err != nil {
return "", err
}
params["accessPoint"] = nil
resp, err := client.do("GET", bucketName, params, nil, nil, options...)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
out := string(body)
return out, err
}

// PutBucketAccessPointPolicy create access point policy for bucket
// name the bucket name or the access point alias name.
// apName the access point name.
// policy the access point policy.
// error it's nil if no error, otherwise it's an error object.
func (client Client) PutAccessPointPolicy(name, apName, policy string, options ...Option) error {
params := map[string]interface{}{}
params["accessPointPolicy"] = nil

buffer := new(bytes.Buffer)
buffer.Write([]byte(policy))
contentType := http.DetectContentType(buffer.Bytes())
headers := map[string]string{}
headers[HTTPHeaderContentType] = contentType
headers[HTTPHeaderOssAccessPointName] = apName
resp, err := client.do("PUT", name, params, headers, buffer, options...)
if err != nil {
return err
}
defer resp.Body.Close()
return CheckRespCode(resp.StatusCode, []int{http.StatusOK})
}

// GetAccessPointPolicy get bucket's access point policy
// name the bucket name or the access point alias name.
// apName the access point name.
// error it's nil if no error, otherwise it's an error object.
func (client Client) GetAccessPointPolicy(name, apName string, options ...Option) (string, error) {
params := map[string]interface{}{}
params["accessPointPolicy"] = nil
headers := map[string]string{}
headers[HTTPHeaderOssAccessPointName] = apName
resp, err := client.do("GET", name, params, headers, nil, options...)
defer resp.Body.Close()
if err != nil {
return "", err
}
body, err := ioutil.ReadAll(resp.Body)
out := string(body)
return out, err
}

// DeleteAccessPointPolicy delete bucket's access point policy
// name the bucket name or the access point alias name.
// apName the access point name.
// error it's nil if no error, otherwise it's an error object.
func (client Client) DeleteAccessPointPolicy(name, apName string, options ...Option) error {
params := map[string]interface{}{}
params["accessPointPolicy"] = nil
headers := map[string]string{}
headers[HTTPHeaderOssAccessPointName] = apName
resp, err := client.do("DELETE", name, params, headers, nil, options...)
if err != nil {
return err
}
defer resp.Body.Close()
return CheckRespCode(resp.StatusCode, []int{http.StatusNoContent})
}

// DescribeRegions get describe regions
// GetDescribeRegionsResult the result of bucket in xml format.
// error it's nil if no error, otherwise it's an error object.
Expand Down
175 changes: 175 additions & 0 deletions oss/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5881,3 +5881,178 @@ func (s *OssClientSuite) TestBucketResponseHeader(c *C) {
c.Assert(err, IsNil)
client.DeleteBucket(bucketName)
}

// TestBucketAccessPoint
func (s *OssClientSuite) TestBucketAccessPoint(c *C) {
if accountID == "" {
c.ExpectFailure("account ID is empty!")
}
var bucketNameTest = bucketNamePrefix + "-acc-" + RandLowStr(6)
client, err := New(endpoint, accessID, accessKey)
c.Assert(err, IsNil)

err = client.CreateBucket(bucketNameTest)
c.Assert(err, IsNil)
time.Sleep(3 * time.Second)

// Create Access Point
apName := "ap1-" + RandLowStr(10)
var create CreateBucketAccessPoint
create.AccessPointName = apName
create.NetworkOrigin = "internet"
resp, err := client.CreateBucketAccessPoint(bucketNameTest, create)
c.Assert(err, IsNil)

c.Assert(resp.AccessPointArn != "", Equals, true)
c.Assert(strings.Contains(resp.AccessPointArn, "acs:oss:"), Equals, true)
c.Assert(resp.Alias != "", Equals, true)
c.Assert(strings.Contains(resp.Alias, "ossalias"), Equals, true)
time.Sleep(1 * time.Second)

// get access point
_, err = client.GetBucketAccessPoint(bucketNameTest, "not-exist-ap")
c.Assert(err, NotNil)
c.Assert(err.(ServiceError).StatusCode, Equals, 404)
c.Assert(err.(ServiceError).Code, Equals, "NoSuchAccessPoint")

res, err := client.GetBucketAccessPoint(bucketNameTest, apName)
aliasName := res.Alias
c.Assert(err, IsNil)
c.Assert(res.AccessPointName, Equals, apName)
c.Assert(res.Bucket, Equals, bucketNameTest)
c.Assert(res.AccountId != "", Equals, true)
c.Assert(res.NetworkOrigin, Equals, "internet")
c.Assert(res.VpcId, Equals, "")
c.Assert(res.AccessPointArn != "", Equals, true)
accessPointArn := res.AccessPointArn
c.Assert(strings.Contains(res.AccessPointArn, "acs:oss:"), Equals, true)
c.Assert(res.CreationDate != "", Equals, true)
c.Assert(res.Alias != "", Equals, true)
c.Assert(res.Status != "", Equals, true)
c.Assert(strings.Contains(res.Endpoints.PublicEndpoint, "oss-accesspoint.aliyuncs.com"), Equals, true)
c.Assert(strings.Contains(res.Endpoints.PublicEndpoint, apName), Equals, true)

c.Assert(strings.Contains(res.Endpoints.InternalEndpoint, "-internal.oss-accesspoint.aliyuncs.com"), Equals, true)
c.Assert(strings.Contains(res.Endpoints.InternalEndpoint, apName), Equals, true)

apName1 := "ap2-" + RandLowStr(10)
var create1 CreateBucketAccessPoint
create1.AccessPointName = apName1
create1.NetworkOrigin = "vpc"
vpcId := "vpc-1234567890"
create1.VpcId = &vpcId
resp1, err := client.CreateBucketAccessPoint(bucketNameTest, create1)
c.Assert(err, IsNil)

c.Assert(resp1.AccessPointArn != "", Equals, true)
c.Assert(strings.Contains(resp1.AccessPointArn, "acs:oss:"), Equals, true)
c.Assert(resp1.Alias != "", Equals, true)
c.Assert(strings.Contains(resp1.Alias, "ossalias"), Equals, true)
time.Sleep(1 * time.Second)

// list access point
list, err := client.ListBucketAccessPoint(bucketNameTest)
c.Assert(err, IsNil)
c.Assert(len(list.AccessPoints), Equals, 2)

c.Assert(list.AccessPoints[1].AccessPointName, Equals, apName1)
c.Assert(list.AccessPoints[1].Bucket, Equals, bucketNameTest)
c.Assert(list.AccessPoints[1].Alias != "", Equals, true)
c.Assert(list.AccessPoints[1].NetworkOrigin, Equals, "vpc")
c.Assert(list.AccessPoints[1].VpcId, Equals, vpcId)
c.Assert(list.AccessPoints[1].Status != "", Equals, true)

// test access point policy
policy := `{
"Version":"1",
"Statement":[
{
"Action":[
"oss:*"
],
"Effect": "Allow",
"Principal":["` + accountID + `"],
"Resource":[
"` + accessPointArn + `",
"` + accessPointArn + `/object/*"
]
}
]
}`

err = client.PutAccessPointPolicy(bucketNameTest, apName, policy)
c.Assert(err, IsNil)

info, err := client.GetAccessPointPolicy(bucketNameTest, apName)
c.Assert(err, IsNil)
c.Assert(info, Equals, policy)

// test access point policy by alias
for {
res, err = client.GetBucketAccessPoint(bucketNameTest, apName)
c.Assert(err, IsNil)
if res.Status == "enable" {
break
}
time.Sleep(30 * time.Second)
}
policy1 := `{
"Version":"1",
"Statement":[
{
"Action":[
"oss:*"
],
"Effect": "Allow",
"Principal":["` + accountID + `"],
"Resource":[
"` + accessPointArn + `",
"` + accessPointArn + `/object/*"
]
},
{
"Action":[
"oss:PutObject",
"oss:GetObject"
],
"Effect":"Deny",
"Principal":["123456"],
"Resource":[
"` + accessPointArn + `",
"` + accessPointArn + `/object/*"
]
}
]
}`
err = client.PutAccessPointPolicy(aliasName, apName, policy1)
c.Assert(err, IsNil)

_, err = client.GetAccessPointPolicy(aliasName, apName)
c.Assert(err, IsNil)
err = client.DeleteAccessPointPolicy(aliasName, apName)
c.Assert(err, IsNil)

err = client.PutAccessPointPolicy(bucketNameTest, apName, policy1)
c.Assert(err, IsNil)
err = client.DeleteAccessPointPolicy(bucketNameTest, apName)
c.Assert(err, IsNil)

// delete bucket access point
for {
list2, err := client.ListBucketAccessPoint(bucketNameTest)
testLogger.Println(list2)
c.Assert(err, IsNil)
if len(list2.AccessPoints) > 0 {
for _, point := range list2.AccessPoints {
if point.Status == "enable" {
err = client.DeleteBucketAccessPoint(bucketNameTest, point.AccessPointName)
c.Assert(err, IsNil)
}
}
} else {
break
}
time.Sleep(30 * time.Second)
}
ForceDeleteBucket(client, bucketNameTest, c)
}
2 changes: 1 addition & 1 deletion oss/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ var signKeyList = []string{"acl", "uploads", "location", "cors",
"x-oss-enable-md5", "x-oss-enable-sha1", "x-oss-enable-sha256",
"x-oss-hash-ctx", "x-oss-md5-ctx", "transferAcceleration",
"regionList", "cloudboxes", "x-oss-ac-source-ip", "x-oss-ac-subnet-mask", "x-oss-ac-vpc-id", "x-oss-ac-forward-allow",
"metaQuery", "resourceGroup", "rtc", "x-oss-async-process", "responseHeader",
"metaQuery", "resourceGroup", "rtc", "x-oss-async-process", "responseHeader", "accessPoint", "accessPointPolicy",
}

// init initializes Conn
Expand Down
1 change: 1 addition & 0 deletions oss/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ const (
HttpHeaderOssNotification = "X-Oss-Notification"
HTTPHeaderOssEc = "X-Oss-Ec"
HTTPHeaderOssErr = "X-Oss-Err"
HTTPHeaderOssAccessPointName = "X-Oss-Access-Point-Name"
)

// HTTP Param
Expand Down
Loading