Skip to content

Commit

Permalink
add access point api
Browse files Browse the repository at this point in the history
  • Loading branch information
yangzong18 committed Jul 7, 2023
1 parent 77977ff commit 725e48e
Show file tree
Hide file tree
Showing 8 changed files with 690 additions and 2 deletions.
186 changes: 186 additions & 0 deletions oss/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2492,6 +2492,192 @@ func (client Client) DeleteBucketStyle(bucketName, styleName string, options ...
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})
}

// LimitUploadSpeed set upload bandwidth limit speed,default is 0,unlimited
// upSpeed KB/s, 0 is unlimited,default is 0
// error it's nil if success, otherwise failure
Expand Down
174 changes: 174 additions & 0 deletions oss/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5505,3 +5505,177 @@ func (s *OssClientSuite) TestBucketStyle(c *C) {
c.Assert(err, IsNil)

}

// 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
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
ticker := time.Tick(1 * time.Minute) // 每分钟执行一次
timeout := time.After(60 * time.Minute) // 60分钟后终止执行

for {
select {
case <-ticker:
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 {
return
}
case <-timeout:
return
}
}
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 @@ -49,7 +49,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",
"metaQuery", "resourceGroup", "rtc", "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 @@ -209,6 +209,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

0 comments on commit 725e48e

Please sign in to comment.