Import upstream version 0.0~git20220516.14de474
Debian Janitor
1 year, 11 months ago
1 | 1 | jobs: |
2 | 2 | build: |
3 | 3 | docker: |
4 | - image: circleci/golang:1.8 | |
4 | - image: circleci/golang:1.10 | |
5 | 5 | working_directory: /go/src/github.com/denverdino/aliyungo |
6 | 6 | steps: |
7 | 7 | - checkout |
0 | name: Go | |
1 | on: [push] | |
2 | jobs: | |
3 | ||
4 | build: | |
5 | name: Build | |
6 | runs-on: ubuntu-latest | |
7 | steps: | |
8 | ||
9 | - name: Set up Go 1.13 | |
10 | uses: actions/setup-go@v1 | |
11 | with: | |
12 | go-version: 1.13 | |
13 | id: go | |
14 | ||
15 | - name: Check out code into the Go module directory | |
16 | uses: actions/checkout@v1 | |
17 | ||
18 | - name: Get dependencies | |
19 | run: | | |
20 | go get -v -t -d ./... | |
21 | if [ -f Gopkg.toml ]; then | |
22 | curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh | |
23 | dep ensure | |
24 | fi | |
25 | - name: Run golangci-lint with reviewdog | |
26 | uses: reviewdog/action-golangci-lint@v1.1.3 | |
27 | with: | |
28 | github_token: ${{ secrets.github_token }} | |
29 | ||
30 |
0 | 0 | language: go |
1 | ||
1 | arch: | |
2 | - AMD64 | |
3 | - ppc64le | |
2 | 4 | go: |
3 | - 1.7.4 | |
5 | - 1.10.8 | |
4 | 6 | |
5 | 7 | # let us have speedy Docker-based Travis workers |
6 | 8 | sudo: false |
0 | 0 | package acm |
1 | 1 | |
2 | 2 | import ( |
3 | "crypto/hmac" | |
4 | "crypto/sha1" | |
5 | "encoding/base64" | |
6 | "errors" | |
7 | "fmt" | |
8 | "io/ioutil" | |
3 | 9 | "net/http" |
10 | "net/url" | |
11 | "strconv" | |
12 | "strings" | |
4 | 13 | "time" |
5 | "fmt" | |
6 | "errors" | |
7 | "io/ioutil" | |
8 | "strings" | |
9 | "encoding/base64" | |
10 | "crypto/sha1" | |
11 | "crypto/hmac" | |
12 | "strconv" | |
13 | "net/url" | |
14 | 14 | ) |
15 | 15 | |
16 | 16 | type Client struct { |
65 | 65 | servers := strings.Split(body, "\n") |
66 | 66 | |
67 | 67 | for k, v := range servers { |
68 | if strings.Index(v, ":") == -1 { | |
68 | if !strings.Contains(v, ":") { | |
69 | 69 | c.servers[k] = v + ":8080" |
70 | 70 | } else { |
71 | 71 | c.servers[k] = v |
100 | 100 | timeStamp = timeStamp[:13] |
101 | 101 | |
102 | 102 | spec := "?" |
103 | if strings.Index(api, "?") != -1 { | |
103 | if strings.Contains(api, "?") { | |
104 | 104 | spec = "&" |
105 | 105 | } |
106 | 106 | |
132 | 132 | request.Header.Add("Spas-Signature", c.getSign([]string{probe})) |
133 | 133 | c.HttpClient.Timeout = time.Duration(c.TimeOut+30) * time.Second |
134 | 134 | } else { |
135 | request.Header.Add("Spas-Signature", c.getSign([]string{c.NameSpace, params["group"], timeStamp})) | |
135 | if group, exists := params["group"]; exists { | |
136 | request.Header.Add("Spas-Signature", c.getSign([]string{c.NameSpace, group, timeStamp})) | |
137 | } else { | |
138 | request.Header.Add("Spas-Signature", c.getSign([]string{c.NameSpace, timeStamp})) | |
139 | } | |
140 | ||
136 | 141 | } |
137 | 142 | |
138 | 143 | resp, err := c.HttpClient.Do(request) |
143 | 148 | defer resp.Body.Close() |
144 | 149 | |
145 | 150 | byt, err := ioutil.ReadAll(resp.Body) |
146 | if err != nil { | |
147 | return "", err | |
148 | } | |
149 | ||
150 | byt, err = GbkToUtf8(byt) | |
151 | 151 | if err != nil { |
152 | 152 | return "", err |
153 | 153 | } |
176 | 176 | return c.callApi("diamond-server/basestone.do?method=getAllConfigByTenant", map[string]string{ |
177 | 177 | "pageNo": strconv.Itoa(pageNo), |
178 | 178 | "pageSize": strconv.Itoa(pageSize), |
179 | "tenant": c.NameSpace, | |
180 | "method": "getAllConfigByTenant", | |
179 | 181 | }, "GET") |
180 | 182 | } |
181 | 183 | |
182 | 184 | func (c *Client) Publish(dataId, group, content string) (string, error) { |
183 | bt, err := Utf8ToGbk([]byte(content)) | |
184 | if err != nil { | |
185 | return "", err | |
186 | } | |
187 | ||
188 | 185 | return c.callApi("diamond-server/basestone.do?method=syncUpdateAll", map[string]string{ |
189 | 186 | "tenant": c.NameSpace, |
190 | 187 | "dataId": dataId, |
191 | 188 | "group": group, |
192 | "content": string(bt), | |
189 | "content": content, | |
193 | 190 | }, "POST") |
194 | 191 | } |
195 | 192 |
0 | 0 | package acm |
1 | 1 | |
2 | 2 | import ( |
3 | "testing" | |
3 | "fmt" | |
4 | 4 | "log" |
5 | 5 | "os" |
6 | "fmt" | |
6 | "testing" | |
7 | 7 | ) |
8 | 8 | |
9 | 9 | func getClient() *Client { |
25 | 25 | client := getClient() |
26 | 26 | defer client.Delete("test", "test") |
27 | 27 | |
28 | _, err := client.Publish("test", "test", "test") | |
28 | _, err := client.Publish("test", "test", "test测试") | |
29 | 29 | |
30 | 30 | if err != nil { |
31 | 31 | t.Fatalf("pulish error:%s", err) |
49 | 49 | if err != nil { |
50 | 50 | t.Error(err) |
51 | 51 | } |
52 | if ret != "test测试" { | |
53 | t.Error("wrong respond content") | |
54 | } | |
52 | 55 | fmt.Println(ret) |
53 | 56 | }) |
54 | 57 | } |
55 | 58 | |
56 | 59 | func TestClient_Subscribe(t *testing.T) { |
57 | 60 | RunWithTest(t, func(client *Client, t *testing.T) { |
58 | _, err := client.Subscribe("test", "test","") | |
61 | _, err := client.Subscribe("test", "test", "") | |
59 | 62 | if err != nil { |
60 | 63 | t.Error(err) |
61 | 64 | } |
62 | 65 | }) |
63 | 66 | } |
67 | ||
68 | func TestClient_GetAllConfig(t *testing.T) { | |
69 | RunWithTest(t, func(client *Client, t *testing.T) { | |
70 | _, err := client.GetAllConfigs(1, 200) | |
71 | if err != nil { | |
72 | t.Error(err) | |
73 | } | |
74 | }) | |
75 | } |
0 | package auth | |
1 | ||
2 | import ( | |
3 | "crypto/rand" | |
4 | "fmt" | |
5 | "io" | |
6 | "os" | |
7 | "syscall" | |
8 | "time" | |
9 | ) | |
10 | ||
11 | const ( | |
12 | // Bits is the number of bits in a UUID | |
13 | Bits = 128 | |
14 | ||
15 | // Size is the number of bytes in a UUID | |
16 | Size = Bits / 8 | |
17 | ||
18 | format = "%08x%04x%04x%04x%012x" | |
19 | ) | |
20 | ||
21 | var ( | |
22 | // Loggerf can be used to override the default logging destination. Such | |
23 | // log messages in this library should be logged at warning or higher. | |
24 | Loggerf = func(format string, args ...interface{}) {} | |
25 | ) | |
26 | ||
27 | // UUID represents a UUID value. UUIDs can be compared and set to other values | |
28 | // and accessed by byte. | |
29 | type UUID [Size]byte | |
30 | ||
31 | // GenerateUUID creates a new, version 4 uuid. | |
32 | func GenerateUUID() (u UUID) { | |
33 | const ( | |
34 | // ensures we backoff for less than 450ms total. Use the following to | |
35 | // select new value, in units of 10ms: | |
36 | // n*(n+1)/2 = d -> n^2 + n - 2d -> n = (sqrt(8d + 1) - 1)/2 | |
37 | maxretries = 9 | |
38 | backoff = time.Millisecond * 10 | |
39 | ) | |
40 | ||
41 | var ( | |
42 | totalBackoff time.Duration | |
43 | count int | |
44 | retries int | |
45 | ) | |
46 | ||
47 | for { | |
48 | // This should never block but the read may fail. Because of this, | |
49 | // we just try to read the random number generator until we get | |
50 | // something. This is a very rare condition but may happen. | |
51 | b := time.Duration(retries) * backoff | |
52 | time.Sleep(b) | |
53 | totalBackoff += b | |
54 | ||
55 | n, err := io.ReadFull(rand.Reader, u[count:]) | |
56 | if err != nil { | |
57 | if retryOnError(err) && retries < maxretries { | |
58 | count += n | |
59 | retries++ | |
60 | Loggerf("error generating version 4 uuid, retrying: %v", err) | |
61 | continue | |
62 | } | |
63 | ||
64 | // Any other errors represent a system problem. What did someone | |
65 | // do to /dev/urandom? | |
66 | panic(fmt.Errorf("error reading random number generator, retried for %v: %v", totalBackoff.String(), err)) | |
67 | } | |
68 | ||
69 | break | |
70 | } | |
71 | ||
72 | u[6] = (u[6] & 0x0f) | 0x40 // set version byte | |
73 | u[8] = (u[8] & 0x3f) | 0x80 // set high order byte 0b10{8,9,a,b} | |
74 | ||
75 | return u | |
76 | } | |
77 | ||
78 | func (u UUID) String() string { | |
79 | return fmt.Sprintf(format, u[:4], u[4:6], u[6:8], u[8:10], u[10:]) | |
80 | } | |
81 | ||
82 | // retryOnError tries to detect whether or not retrying would be fruitful. | |
83 | func retryOnError(err error) bool { | |
84 | switch err := err.(type) { | |
85 | case *os.PathError: | |
86 | return retryOnError(err.Err) // unpack the target error | |
87 | case syscall.Errno: | |
88 | if err == syscall.EPERM { | |
89 | // EPERM represents an entropy pool exhaustion, a condition under | |
90 | // which we backoff and retry. | |
91 | return true | |
92 | } | |
93 | } | |
94 | ||
95 | return false | |
96 | } |
0 | package auth | |
1 | ||
2 | import ( | |
3 | "testing" | |
4 | ) | |
5 | ||
6 | const iterations = 1000 | |
7 | ||
8 | func TestUUID4Generation(t *testing.T) { | |
9 | for i := 0; i < iterations; i++ { | |
10 | u := GenerateUUID() | |
11 | ||
12 | if u[6]&0xf0 != 0x40 { | |
13 | t.Fatalf("version byte not correctly set: %v, %08b %08b", u, u[6], u[6]&0xf0) | |
14 | } | |
15 | ||
16 | if u[8]&0xc0 != 0x80 { | |
17 | t.Fatalf("top order 8th byte not correctly set: %v, %b", u, u[8]) | |
18 | } | |
19 | } | |
20 | } |
0 | package auth | |
1 | ||
2 | import ( | |
3 | "crypto/md5" | |
4 | "fmt" | |
5 | "net/url" | |
6 | "time" | |
7 | ) | |
8 | ||
9 | // An URLSigner provides URL signing utilities to sign URLs for Aliyun CDN | |
10 | // resources. | |
11 | // authentication document: https://help.aliyun.com/document_detail/85117.html | |
12 | type URLSigner struct { | |
13 | authType string | |
14 | privKey string | |
15 | } | |
16 | ||
17 | // NewURLSigner returns a new signer object. | |
18 | func NewURLSigner(authType string, privKey string) *URLSigner { | |
19 | return &URLSigner{ | |
20 | authType: authType, | |
21 | privKey: privKey, | |
22 | } | |
23 | } | |
24 | ||
25 | // Sign returns a signed aliyuncdn url based on authentication type | |
26 | func (s URLSigner) Sign(uri string, expires time.Time) (string, error) { | |
27 | r, err := url.Parse(uri) | |
28 | if err != nil { | |
29 | return "", fmt.Errorf("unable to parse url: %s", uri) | |
30 | } | |
31 | ||
32 | switch s.authType { | |
33 | case "a": | |
34 | return aTypeSign(r, s.privKey, expires), nil | |
35 | case "b": | |
36 | return bTypeSign(r, s.privKey, expires), nil | |
37 | case "c": | |
38 | return cTypeSign(r, s.privKey, expires), nil | |
39 | default: | |
40 | return "", fmt.Errorf("invalid authentication type") | |
41 | } | |
42 | } | |
43 | ||
44 | // sign by A type authentication method. | |
45 | // authentication document: https://help.aliyun.com/document_detail/85113.html | |
46 | func aTypeSign(r *url.URL, privateKey string, expires time.Time) string { | |
47 | //rand is a random uuid without "-" | |
48 | rand := GenerateUUID().String() | |
49 | // not use, "0" by default | |
50 | uid := "0" | |
51 | secret := fmt.Sprintf("%s-%d-%s-%s-%s", r.Path, expires.Unix(), rand, uid, privateKey) | |
52 | hashValue := md5.Sum([]byte(secret)) | |
53 | authKey := fmt.Sprintf("%d-%s-%s-%x", expires.Unix(), rand, uid, hashValue) | |
54 | if r.RawQuery == "" { | |
55 | return fmt.Sprintf("%s?auth_key=%s", r.String(), authKey) | |
56 | } | |
57 | return fmt.Sprintf("%s&auth_key=%s", r.String(), authKey) | |
58 | ||
59 | } | |
60 | ||
61 | // sign by B type authentication method. | |
62 | // authentication document: https://help.aliyun.com/document_detail/85114.html | |
63 | func bTypeSign(r *url.URL, privateKey string, expires time.Time) string { | |
64 | formatExp := expires.Format("200601021504") | |
65 | secret := privateKey + formatExp + r.Path | |
66 | hashValue := md5.Sum([]byte(secret)) | |
67 | signURL := fmt.Sprintf("%s://%s/%s/%x%s?%s", r.Scheme, r.Host, formatExp, hashValue, r.Path, r.RawQuery) | |
68 | return signURL | |
69 | } | |
70 | ||
71 | // sign by C type authentication method. | |
72 | // authentication document: https://help.aliyun.com/document_detail/85115.html | |
73 | func cTypeSign(r *url.URL, privateKey string, expires time.Time) string { | |
74 | hexExp := fmt.Sprintf("%x", expires.Unix()) | |
75 | secret := privateKey + r.Path + hexExp | |
76 | hashValue := md5.Sum([]byte(secret)) | |
77 | signURL := fmt.Sprintf("%s://%s/%x/%s%s?%s", r.Scheme, r.Host, hashValue, hexExp, r.Path, r.RawQuery) | |
78 | return signURL | |
79 | } |
0 | package auth | |
1 | ||
2 | import ( | |
3 | "crypto/md5" | |
4 | "fmt" | |
5 | "net/url" | |
6 | "reflect" | |
7 | "testing" | |
8 | "time" | |
9 | ) | |
10 | ||
11 | var ( | |
12 | testSignTime = time.Unix(1541064730, 0) | |
13 | testPrivKey = "12345678" | |
14 | ) | |
15 | ||
16 | func assertEqual(t *testing.T, name string, x, y interface{}) { | |
17 | if !reflect.DeepEqual(x, y) { | |
18 | t.Errorf("%s: Not equal! Expected='%v', Actual='%v'\n", name, x, y) | |
19 | t.FailNow() | |
20 | } | |
21 | } | |
22 | ||
23 | func TestAtypeAuth(t *testing.T) { | |
24 | r, _ := url.Parse("https://example.com/a?foo=bar") | |
25 | url := aTypeTest(r, testPrivKey, testSignTime) | |
26 | assertEqual(t, "testTypeA", "https://example.com/a?foo=bar&auth_key=1541064730-0-0-f9dd5ed1e274ab4b1d5f5745344bf28b", url) | |
27 | } | |
28 | ||
29 | func TestBtypeAuth(t *testing.T) { | |
30 | signer := NewURLSigner("b", testPrivKey) | |
31 | url, _ := signer.Sign("https://example.com/a?foo=bar", testSignTime) | |
32 | assertEqual(t, "testTypeB", "https://example.com/201811011732/3a19d83a89ccb00a73212420791b0123/a?foo=bar", url) | |
33 | } | |
34 | ||
35 | func TestCtypeAuth(t *testing.T) { | |
36 | signer := NewURLSigner("c", testPrivKey) | |
37 | url, _ := signer.Sign("https://example.com/a?foo=bar", testSignTime) | |
38 | assertEqual(t, "testTypeC", "https://example.com/7d6b308ce87beb16d9dba32d741220f6/5bdac81a/a?foo=bar", url) | |
39 | } | |
40 | ||
41 | func aTypeTest(r *url.URL, privateKey string, expires time.Time) string { | |
42 | //rand equals "0" in test case | |
43 | rand := "0" | |
44 | uid := "0" | |
45 | secret := fmt.Sprintf("%s-%d-%s-%s-%s", r.Path, expires.Unix(), rand, uid, privateKey) | |
46 | hashValue := md5.Sum([]byte(secret)) | |
47 | authKey := fmt.Sprintf("%d-%s-%s-%x", expires.Unix(), rand, uid, hashValue) | |
48 | if r.RawQuery == "" { | |
49 | return fmt.Sprintf("%s?auth_key=%s", r.String(), authKey) | |
50 | } | |
51 | return fmt.Sprintf("%s&auth_key=%s", r.String(), authKey) | |
52 | } |
8 | 8 | const ( |
9 | 9 | Web = "web" |
10 | 10 | Download = "download" |
11 | video = "video" | |
11 | Video = "video" | |
12 | 12 | LiveStream = "liveStream" |
13 | 13 | Ipaddr = "ipaddr" |
14 | 14 | Domain = "domain" |
26 | 26 | AccessControlMaxAge = "Access-Control-Max-Age" |
27 | 27 | ) |
28 | 28 | |
29 | var CdnTypes = []string{Web, Download, video, LiveStream} | |
29 | var CdnTypes = []string{Web, Download, Video, LiveStream} | |
30 | 30 | var SourceTypes = []string{Ipaddr, Domain, OSS} |
31 | 31 | var Scopes = []string{Domestic, Overseas, Global} |
32 | 32 | var HeaderKeys = []string{ContentType, CacheControl, ContentDisposition, ContentLanguage, Expires, AccessControlAllowMethods, AccessControlAllowOrigin, AccessControlMaxAge} |
0 | package cen | |
1 | ||
2 | import ( | |
3 | "os" | |
4 | ||
5 | "github.com/denverdino/aliyungo/common" | |
6 | ) | |
7 | ||
8 | // Interval for checking status in WaitForXXX method | |
9 | const DefaultWaitForInterval = 5 | |
10 | ||
11 | // Default timeout value for WaitForXXX method | |
12 | const DefaultTimeout = 60 | |
13 | ||
14 | type Client struct { | |
15 | common.Client | |
16 | } | |
17 | ||
18 | const ( | |
19 | // CENDefaultEndpoint is the default API endpoint of CEN services | |
20 | CENDefaultEndpoint = "https://cbn.aliyuncs.com" | |
21 | CENAPIVersion = "2017-09-12" | |
22 | CENServiceCode = "cen" | |
23 | ) | |
24 | ||
25 | // --------------------------------------- | |
26 | // NewCENClient creates a new instance of CEN client | |
27 | // --------------------------------------- | |
28 | func NewCENClient(accessKeyId, accessKeySecret string, regionID common.Region) *Client { | |
29 | return NewCENClientWithSecurityToken(accessKeyId, accessKeySecret, "", regionID) | |
30 | } | |
31 | ||
32 | func NewCENClientWithSecurityToken(accessKeyId string, accessKeySecret string, securityToken string, regionID common.Region) *Client { | |
33 | endpoint := os.Getenv("CEN_ENDPOINT") | |
34 | if endpoint == "" { | |
35 | endpoint = CENDefaultEndpoint | |
36 | } | |
37 | ||
38 | return NewCENClientWithEndpointAndSecurityToken(endpoint, accessKeyId, accessKeySecret, securityToken, regionID) | |
39 | } | |
40 | ||
41 | //only for Hangzhou Regional Domain | |
42 | func NewCENClientWithSecurityToken4RegionalDomain(accessKeyId string, accessKeySecret string, securityToken string, regionID common.Region) *Client { | |
43 | endpoint := os.Getenv("CEN_ENDPOINT") | |
44 | if endpoint == "" { | |
45 | endpoint = CENDefaultEndpoint | |
46 | } | |
47 | ||
48 | return NewCENClientWithEndpointAndSecurityToken4RegionalDomain(endpoint, accessKeyId, accessKeySecret, securityToken, regionID) | |
49 | } | |
50 | ||
51 | func NewCENClientWithEndpointAndSecurityToken(endpoint string, accessKeyId string, accessKeySecret string, securityToken string, regionID common.Region) *Client { | |
52 | client := &Client{} | |
53 | client.WithEndpoint(endpoint). | |
54 | WithVersion(CENAPIVersion). | |
55 | WithAccessKeyId(accessKeyId). | |
56 | WithAccessKeySecret(accessKeySecret). | |
57 | WithSecurityToken(securityToken). | |
58 | WithServiceCode(CENServiceCode). | |
59 | WithRegionID(regionID). | |
60 | InitClient() | |
61 | return client | |
62 | } | |
63 | ||
64 | func NewCENClientWithEndpointAndSecurityToken4RegionalDomain(endpoint string, accessKeyId string, accessKeySecret string, securityToken string, regionID common.Region) *Client { | |
65 | client := &Client{} | |
66 | client.WithEndpoint(endpoint). | |
67 | WithVersion(CENAPIVersion). | |
68 | WithAccessKeyId(accessKeyId). | |
69 | WithAccessKeySecret(accessKeySecret). | |
70 | WithSecurityToken(securityToken). | |
71 | WithServiceCode(CENServiceCode). | |
72 | WithRegionID(regionID). | |
73 | InitClient4RegionalDomain() | |
74 | return client | |
75 | } |
0 | package cen | |
1 | ||
2 | import ( | |
3 | "log" | |
4 | ||
5 | "github.com/denverdino/aliyungo/common" | |
6 | ) | |
7 | ||
8 | type PublishRouteEntriesArgs struct { | |
9 | CenId string | |
10 | ChildInstanceId string | |
11 | ChildInstanceRegionId string | |
12 | ChildInstanceRouteTableId string | |
13 | ChildInstanceType string | |
14 | DestinationCidrBlock string | |
15 | } | |
16 | ||
17 | type DescribePublishedRouteEntriesArgs struct { | |
18 | common.Pagination | |
19 | CenId string | |
20 | ChildInstanceId string | |
21 | ChildInstanceRegionId string | |
22 | ChildInstanceType string | |
23 | ChildInstanceRouteTableId string | |
24 | DestinationCidrBlock string | |
25 | } | |
26 | ||
27 | type DescribePublishedRouteEntriesResponse struct { | |
28 | common.Response | |
29 | common.PaginationResult | |
30 | PublishedRouteEntries struct { | |
31 | PublishedRouteEntry []PublishedRouteEntry | |
32 | } | |
33 | } | |
34 | ||
35 | type ConflictStatus string | |
36 | type NextHopType string | |
37 | ||
38 | const ( | |
39 | ConflictStatusConflict = ConflictStatus("conflict") | |
40 | ConflictStatusOverflow = ConflictStatus("overflow") | |
41 | ConflictStatusProhibited = ConflictStatus("prohibited") | |
42 | ) | |
43 | ||
44 | const ( | |
45 | NextHopTypeInstance = NextHopType("Instance") | |
46 | NextHopTypeHaVip = NextHopType("HaVip") | |
47 | NextHopTypeRouterInterface = NextHopType("RouterInterface") | |
48 | ) | |
49 | ||
50 | type PublishStatus string | |
51 | ||
52 | const ( | |
53 | PublishStatusPublished = PublishStatus("Published") | |
54 | PublishStatusNotPublished = PublishStatus("NonPublished") | |
55 | ) | |
56 | ||
57 | type RouteType string | |
58 | ||
59 | const ( | |
60 | RouteTypeSystem = RouteType("System") | |
61 | RouteTypeCustom = RouteType("Custom") | |
62 | RouteTypeBGP = RouteType("BGP") | |
63 | ) | |
64 | ||
65 | type PublishedRouteEntry struct { | |
66 | ChildInstanceRouteTableId string | |
67 | Conflicts struct { | |
68 | Conflict []Conflict | |
69 | } | |
70 | DestinationCidrBlock string | |
71 | NextHopId string | |
72 | ||
73 | NextHopType string | |
74 | OperationalMode bool | |
75 | PublishStatus string | |
76 | RouteType string | |
77 | } | |
78 | ||
79 | type Conflict struct { | |
80 | DestinationCidrBlock string | |
81 | InstanceId string | |
82 | InstanceType string | |
83 | RegionId string | |
84 | Status string | |
85 | } | |
86 | ||
87 | // PublishRouteEntries publish route | |
88 | // | |
89 | // You can read doc at https://help.aliyun.com/document_detail/85470.html | |
90 | func (client *Client) PublishRouteEntries(args *PublishRouteEntriesArgs) error { | |
91 | response := &common.Response{} | |
92 | err := client.Invoke("PublishRouteEntries", args, response) | |
93 | if err != nil { | |
94 | log.Printf("PublishRouteEntries: %s, %s\n", response.RequestId, err.Error()) | |
95 | } | |
96 | return err | |
97 | } | |
98 | ||
99 | // DescribePublishedRouteEntries describe published route | |
100 | // | |
101 | // You can read doc at https://help.aliyun.com/document_detail/85472.html | |
102 | func (client *Client) DescribePublishedRouteEntries( | |
103 | args *DescribePublishedRouteEntriesArgs, | |
104 | ) (response *DescribePublishedRouteEntriesResponse, err error) { | |
105 | ||
106 | response = &DescribePublishedRouteEntriesResponse{} | |
107 | ||
108 | err = client.Invoke("DescribePublishedRouteEntries", args, response) | |
109 | ||
110 | if err != nil { | |
111 | log.Printf("DescribePublishedRouteEntries: %v, %v\n", args, response) | |
112 | } | |
113 | ||
114 | return response, err | |
115 | } |
0 | package cen | |
1 | ||
2 | import ( | |
3 | "encoding/json" | |
4 | "fmt" | |
5 | "testing" | |
6 | ) | |
7 | ||
8 | var ( | |
9 | ak = "" | |
10 | sec = "" | |
11 | ) | |
12 | ||
13 | func TestDescribePublishedRoute(t *testing.T) { | |
14 | client := NewCENClient(ak, sec, "cn-shanghai") | |
15 | res, err := client.DescribePublishedRouteEntries( | |
16 | &DescribePublishedRouteEntriesArgs{ | |
17 | CenId: "cen-qhu4rn3cknrg5o4qhl", | |
18 | ChildInstanceType: "VPC", | |
19 | ChildInstanceRegionId: "cn-shanghai", | |
20 | ChildInstanceRouteTableId: "vtb-uf699blmsutb4wkbzqcmt", | |
21 | ChildInstanceId: "vpc-uf6ch2jfder4r0z51vtox", | |
22 | }, | |
23 | ) | |
24 | if err != nil { | |
25 | t.Errorf("describe: %s", err.Error()) | |
26 | t.FailNow() | |
27 | } | |
28 | fmt.Printf("Result: %+v", res) | |
29 | b, err := json.MarshalIndent(res, "", " ") | |
30 | fmt.Printf("%s", b) | |
31 | } | |
32 | ||
33 | func TestPublishedRoute(t *testing.T) { | |
34 | client := NewCENClient(ak, sec, "cn-shanghai") | |
35 | err := client.PublishRouteEntries( | |
36 | &PublishRouteEntriesArgs{ | |
37 | CenId: "cen-qhu4rn3cknrg5o4qhl", | |
38 | ChildInstanceType: "VPC", | |
39 | ChildInstanceRegionId: "cn-shanghai", | |
40 | ChildInstanceRouteTableId: "vtb-uf6nco4vj87ly556c589f", | |
41 | ChildInstanceId: "vpc-uf6ch2jfder4r0z51vtox", | |
42 | DestinationCidrBlock: "192.168.0.0/26", | |
43 | }, | |
44 | ) | |
45 | if err != nil { | |
46 | t.Errorf("publish: %s", err.Error()) | |
47 | t.FailNow() | |
48 | } | |
49 | } |
30 | 30 | |
31 | 31 | func (client *Client) SetDebug(debug bool) { |
32 | 32 | client.debug = debug |
33 | } | |
34 | ||
35 | // SetTransport sets transport to the http client | |
36 | func (client *Client) SetTransport(transport http.RoundTripper) { | |
37 | if client.httpClient == nil { | |
38 | client.httpClient = &http.Client{} | |
39 | } | |
40 | client.httpClient.Transport = transport | |
33 | 41 | } |
34 | 42 | |
35 | 43 | const ( |
4 | 4 | "encoding/json" |
5 | 5 | "errors" |
6 | 6 | "fmt" |
7 | "github.com/opentracing/opentracing-go/ext" | |
7 | 8 | "io/ioutil" |
8 | 9 | "log" |
10 | "net" | |
9 | 11 | "net/http" |
10 | 12 | "net/url" |
11 | 13 | "os" |
14 | 16 | "time" |
15 | 17 | |
16 | 18 | "github.com/denverdino/aliyungo/util" |
19 | "github.com/opentracing/opentracing-go" | |
17 | 20 | ) |
18 | 21 | |
19 | 22 | // RemovalPolicy.N add index to array item |
37 | 40 | regionID Region |
38 | 41 | businessInfo string |
39 | 42 | userAgent string |
43 | disableTrace bool | |
44 | span opentracing.Span | |
45 | logger *Logger | |
40 | 46 | } |
41 | 47 | |
42 | 48 | // Initialize properties of a client instance |
47 | 53 | ak += "&" |
48 | 54 | } |
49 | 55 | client.AccessKeySecret = ak |
50 | client.debug = false | |
51 | handshakeTimeout, err := strconv.Atoi(os.Getenv("TLSHandshakeTimeout")) | |
52 | if err != nil { | |
53 | handshakeTimeout = 0 | |
54 | } | |
55 | if handshakeTimeout == 0 { | |
56 | client.httpClient = &http.Client{} | |
57 | } else { | |
58 | t := &http.Transport{ | |
59 | TLSHandshakeTimeout: time.Duration(handshakeTimeout) * time.Second} | |
60 | client.httpClient = &http.Client{Transport: t} | |
61 | } | |
56 | client.InitClient() | |
62 | 57 | client.endpoint = endpoint |
63 | 58 | client.version = version |
64 | 59 | } |
70 | 65 | client.regionID = regionID |
71 | 66 | } |
72 | 67 | |
68 | // Initialize properties of a client instance including regionID | |
69 | //only for hz regional Domain | |
70 | func (client *Client) NewInit4RegionalDomain(endpoint, version, accessKeyId, accessKeySecret, serviceCode string, regionID Region) { | |
71 | client.Init(endpoint, version, accessKeyId, accessKeySecret) | |
72 | client.serviceCode = serviceCode | |
73 | client.regionID = regionID | |
74 | ||
75 | client.setEndpoint4RegionalDomain(client.regionID, client.serviceCode, client.AccessKeyId, client.AccessKeySecret, client.securityToken) | |
76 | } | |
77 | ||
73 | 78 | // Intialize client object when all properties are ready |
74 | 79 | func (client *Client) InitClient() *Client { |
75 | 80 | client.debug = false |
76 | handshakeTimeout, err := strconv.Atoi(os.Getenv("TLSHandshakeTimeout")) | |
77 | if err != nil { | |
78 | handshakeTimeout = 0 | |
79 | } | |
80 | if handshakeTimeout == 0 { | |
81 | client.httpClient = &http.Client{} | |
82 | } else { | |
83 | t := &http.Transport{ | |
84 | TLSHandshakeTimeout: time.Duration(handshakeTimeout) * time.Second} | |
85 | client.httpClient = &http.Client{Transport: t} | |
86 | } | |
81 | ||
82 | // create DefaultTransport manully, because transport doesn't has clone method in go 1.10 | |
83 | t := &http.Transport{ | |
84 | Proxy: http.ProxyFromEnvironment, | |
85 | DialContext: (&net.Dialer{ | |
86 | Timeout: 30 * time.Second, | |
87 | KeepAlive: 30 * time.Second, | |
88 | DualStack: true, | |
89 | }).DialContext, | |
90 | MaxIdleConns: 100, | |
91 | IdleConnTimeout: 90 * time.Second, | |
92 | TLSHandshakeTimeout: 10 * time.Second, | |
93 | ExpectContinueTimeout: 1 * time.Second, | |
94 | } | |
95 | ||
96 | handshakeTimeoutStr, ok := os.LookupEnv("TLSHandshakeTimeout") | |
97 | if ok { | |
98 | handshakeTimeout, err := strconv.Atoi(handshakeTimeoutStr) | |
99 | if err != nil { | |
100 | log.Printf("Get TLSHandshakeTimeout from env error: %v.", err) | |
101 | } else { | |
102 | t.TLSHandshakeTimeout = time.Duration(handshakeTimeout) * time.Second | |
103 | } | |
104 | } | |
105 | ||
106 | responseHeaderTimeoutStr, ok := os.LookupEnv("ResponseHeaderTimeout") | |
107 | if ok { | |
108 | responseHeaderTimeout, err := strconv.Atoi(responseHeaderTimeoutStr) | |
109 | if err != nil { | |
110 | log.Printf("Get ResponseHeaderTimeout from env error: %v.", err) | |
111 | } else { | |
112 | t.ResponseHeaderTimeout = time.Duration(responseHeaderTimeout) * time.Second | |
113 | } | |
114 | } | |
115 | ||
116 | expectContinueTimeoutStr, ok := os.LookupEnv("ExpectContinueTimeout") | |
117 | if ok { | |
118 | expectContinueTimeout, err := strconv.Atoi(expectContinueTimeoutStr) | |
119 | if err != nil { | |
120 | log.Printf("Get ExpectContinueTimeout from env error: %v.", err) | |
121 | } else { | |
122 | t.ExpectContinueTimeout = time.Duration(expectContinueTimeout) * time.Second | |
123 | } | |
124 | } | |
125 | ||
126 | idleConnTimeoutStr, ok := os.LookupEnv("IdleConnTimeout") | |
127 | if ok { | |
128 | idleConnTimeout, err := strconv.Atoi(idleConnTimeoutStr) | |
129 | if err != nil { | |
130 | log.Printf("Get IdleConnTimeout from env error: %v.", err) | |
131 | } else { | |
132 | t.IdleConnTimeout = time.Duration(idleConnTimeout) * time.Second | |
133 | } | |
134 | } | |
135 | ||
136 | client.httpClient = &http.Client{ | |
137 | Transport: t, | |
138 | } | |
139 | ||
140 | httpTimeoutStr, ok := os.LookupEnv("HttpTimeout") | |
141 | if ok { | |
142 | httpTimeout, err := strconv.Atoi(httpTimeoutStr) | |
143 | if err != nil { | |
144 | log.Printf("Get HttpTimeout from env error: %v.", err) | |
145 | } else { | |
146 | client.httpClient.Timeout = time.Duration(httpTimeout) * time.Second | |
147 | } | |
148 | } | |
149 | ||
150 | return client | |
151 | } | |
152 | ||
153 | // Intialize client object when all properties are ready | |
154 | //only for regional domain hz | |
155 | func (client *Client) InitClient4RegionalDomain() *Client { | |
156 | client.InitClient() | |
157 | //set endpoint | |
158 | client.setEndpoint4RegionalDomain(client.regionID, client.serviceCode, client.AccessKeyId, client.AccessKeySecret, client.securityToken) | |
87 | 159 | return client |
88 | 160 | } |
89 | 161 | |
104 | 176 | locationClient := NewLocationClient(accessKeyId, accessKeySecret, securityToken) |
105 | 177 | locationClient.SetDebug(true) |
106 | 178 | ep := locationClient.DescribeOpenAPIEndpoint(region, serviceCode) |
107 | if ep == "" { | |
108 | ep = loadEndpointFromFile(region, serviceCode) | |
109 | } | |
179 | ||
180 | if ep != "" { | |
181 | client.endpoint = ep | |
182 | } | |
183 | } | |
184 | ||
185 | // Get openapi endpoint accessed by ecs instance. | |
186 | // For some UnitRegions, the endpoint pattern is https://[product].[regionid].aliyuncs.com | |
187 | // For some CentralRegions, the endpoint pattern is https://[product].vpc-proxy.aliyuncs.com | |
188 | // The other region, the endpoint pattern is https://[product]-vpc.[regionid].aliyuncs.com | |
189 | func (client *Client) setEndpoint4RegionalDomain(region Region, serviceCode, accessKeyId, accessKeySecret, securityToken string) { | |
190 | if endpoint, ok := CentralDomainServices[serviceCode]; ok { | |
191 | client.endpoint = fmt.Sprintf("https://%s", endpoint) | |
192 | return | |
193 | } | |
194 | for _, service := range RegionalDomainServices { | |
195 | if service == serviceCode { | |
196 | if ep, ok := UnitRegions[region]; ok { | |
197 | client.endpoint = fmt.Sprintf("https://%s.%s.aliyuncs.com", serviceCode, ep) | |
198 | return | |
199 | } | |
200 | ||
201 | client.endpoint = fmt.Sprintf("https://%s%s.%s.aliyuncs.com", serviceCode, "-vpc", region) | |
202 | return | |
203 | } | |
204 | } | |
205 | locationClient := NewLocationClient(accessKeyId, accessKeySecret, securityToken) | |
206 | locationClient.SetDebug(true) | |
207 | ep := locationClient.DescribeOpenAPIEndpoint(region, serviceCode) | |
110 | 208 | |
111 | 209 | if ep != "" { |
112 | 210 | client.endpoint = ep |
198 | 296 | return client |
199 | 297 | } |
200 | 298 | |
299 | // WithUserAgent sets user agent to the request/response message | |
300 | func (client *Client) WithDisableTrace(disableTrace bool) *Client { | |
301 | client.SetDisableTrace(disableTrace) | |
302 | return client | |
303 | } | |
304 | ||
305 | // WithUserAgent sets user agent to the request/response message | |
306 | func (client *Client) WithSpan(span opentracing.Span) *Client { | |
307 | client.SetSpan(span) | |
308 | return client | |
309 | } | |
310 | ||
201 | 311 | // ---------------------------------------------------- |
202 | 312 | // SetXXX methods |
203 | 313 | // ---------------------------------------------------- |
205 | 315 | // SetEndpoint sets custom endpoint |
206 | 316 | func (client *Client) SetEndpoint(endpoint string) { |
207 | 317 | client.endpoint = endpoint |
318 | } | |
319 | ||
320 | func (client *Client) GetEndpoint() string { | |
321 | return client.endpoint | |
208 | 322 | } |
209 | 323 | |
210 | 324 | // SetEndpoint sets custom version |
256 | 370 | client.securityToken = securityToken |
257 | 371 | } |
258 | 372 | |
373 | // SetTransport sets transport to the http client | |
374 | func (client *Client) SetTransport(transport http.RoundTripper) { | |
375 | if client.httpClient == nil { | |
376 | client.httpClient = &http.Client{} | |
377 | } | |
378 | client.httpClient.Transport = transport | |
379 | } | |
380 | ||
381 | // SetDisableTrace close trace mode | |
382 | func (client *Client) SetDisableTrace(disableTrace bool) { | |
383 | client.disableTrace = disableTrace | |
384 | } | |
385 | ||
386 | // SetSpan set the parent span | |
387 | func (client *Client) SetSpan(span opentracing.Span) { | |
388 | client.span = span | |
389 | } | |
390 | ||
259 | 391 | func (client *Client) initEndpoint() error { |
260 | 392 | // if set any value to "CUSTOMIZED_ENDPOINT" could skip location service. |
261 | 393 | // example: export CUSTOMIZED_ENDPOINT=true |
263 | 395 | return nil |
264 | 396 | } |
265 | 397 | |
398 | if client.endpoint != "" { | |
399 | return nil | |
400 | } | |
401 | ||
266 | 402 | if client.serviceCode != "" && client.regionID != "" { |
267 | 403 | endpoint := client.getEndpointByLocation() |
268 | 404 | if endpoint == "" { |
274 | 410 | } |
275 | 411 | |
276 | 412 | // Invoke sends the raw HTTP request for ECS services |
277 | func (client *Client) Invoke(action string, args interface{}, response interface{}) error { | |
413 | func (client *Client) Invoke(action string, args interface{}, response interface{}) (err error) { | |
278 | 414 | if err := client.ensureProperties(); err != nil { |
279 | 415 | return err |
280 | 416 | } |
417 | ||
418 | // log request | |
419 | fieldMap := make(map[string]string) | |
420 | initLogMsg(fieldMap) | |
421 | defer func() { | |
422 | client.printLog(fieldMap, err) | |
423 | }() | |
424 | ||
425 | request := Request{} | |
426 | request.init(client.version, action, client.AccessKeyId, client.securityToken, client.regionID) | |
427 | ||
428 | query := util.ConvertToQueryValues(request) | |
429 | util.SetQueryValues(args, &query) | |
430 | ||
431 | // Sign request | |
432 | signature := util.CreateSignatureForRequest(ECSRequestMethod, &query, client.AccessKeySecret) | |
433 | ||
434 | // Generate the request URL | |
435 | requestURL := client.endpoint + "?" + query.Encode() + "&Signature=" + url.QueryEscape(signature) | |
436 | ||
437 | httpReq, err := http.NewRequest(ECSRequestMethod, requestURL, nil) | |
438 | ||
439 | if err != nil { | |
440 | return GetClientError(err) | |
441 | } | |
442 | ||
443 | // TODO move to util and add build val flag | |
444 | httpReq.Header.Set("X-SDK-Client", `AliyunGO/`+Version+client.businessInfo) | |
445 | httpReq.Header.Set("User-Agent", httpReq.UserAgent()+" "+client.userAgent) | |
446 | ||
447 | // Set tracer | |
448 | var span opentracing.Span | |
449 | if ok := opentracing.IsGlobalTracerRegistered(); ok && !client.disableTrace { | |
450 | tracer := opentracing.GlobalTracer() | |
451 | var rootCtx opentracing.SpanContext | |
452 | ||
453 | if client.span != nil { | |
454 | rootCtx = client.span.Context() | |
455 | } | |
456 | ||
457 | span = tracer.StartSpan( | |
458 | "AliyunGO-"+request.Action, | |
459 | opentracing.ChildOf(rootCtx), | |
460 | opentracing.Tag{string(ext.Component), "AliyunGO"}, | |
461 | opentracing.Tag{"ActionName", request.Action}) | |
462 | ||
463 | defer span.Finish() | |
464 | tracer.Inject( | |
465 | span.Context(), | |
466 | opentracing.HTTPHeaders, | |
467 | opentracing.HTTPHeadersCarrier(httpReq.Header)) | |
468 | } | |
469 | ||
470 | putMsgToMap(fieldMap, httpReq) | |
471 | t0 := time.Now() | |
472 | fieldMap["{start_time}"] = t0.Format("2006-01-02 15:04:05") | |
473 | httpResp, err := client.httpClient.Do(httpReq) | |
474 | t1 := time.Now() | |
475 | fieldMap["{cost}"] = t1.Sub(t0).String() | |
476 | if err != nil { | |
477 | if span != nil { | |
478 | ext.LogError(span, err) | |
479 | } | |
480 | return GetClientError(err) | |
481 | } | |
482 | fieldMap["{code}"] = strconv.Itoa(httpResp.StatusCode) | |
483 | fieldMap["{res_headers}"] = TransToString(httpResp.Header) | |
484 | statusCode := httpResp.StatusCode | |
485 | ||
486 | if client.debug { | |
487 | log.Printf("Invoke %s %s %d (%v)", ECSRequestMethod, requestURL, statusCode, t1.Sub(t0)) | |
488 | } | |
489 | ||
490 | if span != nil { | |
491 | ext.HTTPStatusCode.Set(span, uint16(httpResp.StatusCode)) | |
492 | } | |
493 | ||
494 | defer httpResp.Body.Close() | |
495 | body, err := ioutil.ReadAll(httpResp.Body) | |
496 | fieldMap["{res_body}"] = string(body) | |
497 | ||
498 | if err != nil { | |
499 | return GetClientError(err) | |
500 | } | |
501 | ||
502 | if client.debug { | |
503 | var prettyJSON bytes.Buffer | |
504 | err = json.Indent(&prettyJSON, body, "", " ") | |
505 | if err != nil { | |
506 | log.Printf("Failed in json.Indent: %v\n", err) | |
507 | } else { | |
508 | log.Printf("JSON body: %s\n", prettyJSON.String()) | |
509 | } | |
510 | } | |
511 | ||
512 | if statusCode >= 400 && statusCode <= 599 { | |
513 | errorResponse := ErrorResponse{} | |
514 | err = json.Unmarshal(body, &errorResponse) | |
515 | if err != nil { | |
516 | log.Printf("Failed in json.Unmarshal: %v\n", err) | |
517 | } | |
518 | ecsError := &Error{ | |
519 | ErrorResponse: errorResponse, | |
520 | StatusCode: statusCode, | |
521 | } | |
522 | return ecsError | |
523 | } | |
524 | ||
525 | err = json.Unmarshal(body, response) | |
526 | //log.Printf("%++v", response) | |
527 | if err != nil { | |
528 | return GetClientError(err) | |
529 | } | |
530 | ||
531 | return nil | |
532 | } | |
533 | ||
534 | // Invoke sends the raw HTTP request for ECS services | |
535 | func (client *Client) InvokeByFlattenMethod(action string, args interface{}, response interface{}) (err error) { | |
536 | if err := client.ensureProperties(); err != nil { | |
537 | return err | |
538 | } | |
539 | ||
540 | // log request | |
541 | fieldMap := make(map[string]string) | |
542 | initLogMsg(fieldMap) | |
543 | defer func() { | |
544 | client.printLog(fieldMap, err) | |
545 | }() | |
281 | 546 | |
282 | 547 | //init endpoint |
283 | 548 | if err := client.initEndpoint(); err != nil { |
288 | 553 | request.init(client.version, action, client.AccessKeyId, client.securityToken, client.regionID) |
289 | 554 | |
290 | 555 | query := util.ConvertToQueryValues(request) |
291 | util.SetQueryValues(args, &query) | |
556 | ||
557 | util.SetQueryValueByFlattenMethod(args, &query) | |
292 | 558 | |
293 | 559 | // Sign request |
294 | 560 | signature := util.CreateSignatureForRequest(ECSRequestMethod, &query, client.AccessKeySecret) |
304 | 570 | |
305 | 571 | // TODO move to util and add build val flag |
306 | 572 | httpReq.Header.Set("X-SDK-Client", `AliyunGO/`+Version+client.businessInfo) |
307 | ||
308 | 573 | httpReq.Header.Set("User-Agent", httpReq.UserAgent()+" "+client.userAgent) |
309 | 574 | |
575 | // Set tracer | |
576 | var span opentracing.Span | |
577 | if ok := opentracing.IsGlobalTracerRegistered(); ok && !client.disableTrace { | |
578 | tracer := opentracing.GlobalTracer() | |
579 | var rootCtx opentracing.SpanContext | |
580 | ||
581 | if client.span != nil { | |
582 | rootCtx = client.span.Context() | |
583 | } | |
584 | ||
585 | span = tracer.StartSpan( | |
586 | "AliyunGO-"+request.Action, | |
587 | opentracing.ChildOf(rootCtx), | |
588 | opentracing.Tag{string(ext.Component), "AliyunGO"}, | |
589 | opentracing.Tag{"ActionName", request.Action}) | |
590 | ||
591 | defer span.Finish() | |
592 | tracer.Inject( | |
593 | span.Context(), | |
594 | opentracing.HTTPHeaders, | |
595 | opentracing.HTTPHeadersCarrier(httpReq.Header)) | |
596 | } | |
597 | ||
598 | putMsgToMap(fieldMap, httpReq) | |
310 | 599 | t0 := time.Now() |
600 | fieldMap["{start_time}"] = t0.Format("2006-01-02 15:04:05") | |
311 | 601 | httpResp, err := client.httpClient.Do(httpReq) |
312 | 602 | t1 := time.Now() |
313 | if err != nil { | |
314 | return GetClientError(err) | |
315 | } | |
603 | fieldMap["{cost}"] = t1.Sub(t0).String() | |
604 | if err != nil { | |
605 | if span != nil { | |
606 | ext.LogError(span, err) | |
607 | } | |
608 | return GetClientError(err) | |
609 | } | |
610 | fieldMap["{code}"] = strconv.Itoa(httpResp.StatusCode) | |
611 | fieldMap["{res_headers}"] = TransToString(httpResp.Header) | |
316 | 612 | statusCode := httpResp.StatusCode |
317 | 613 | |
318 | 614 | if client.debug { |
319 | 615 | log.Printf("Invoke %s %s %d (%v)", ECSRequestMethod, requestURL, statusCode, t1.Sub(t0)) |
320 | 616 | } |
321 | 617 | |
618 | if span != nil { | |
619 | ext.HTTPStatusCode.Set(span, uint16(httpResp.StatusCode)) | |
620 | } | |
621 | ||
322 | 622 | defer httpResp.Body.Close() |
323 | 623 | body, err := ioutil.ReadAll(httpResp.Body) |
624 | fieldMap["{res_body}"] = string(body) | |
324 | 625 | |
325 | 626 | if err != nil { |
326 | 627 | return GetClientError(err) |
329 | 630 | if client.debug { |
330 | 631 | var prettyJSON bytes.Buffer |
331 | 632 | err = json.Indent(&prettyJSON, body, "", " ") |
332 | log.Println(string(prettyJSON.Bytes())) | |
633 | if err != nil { | |
634 | log.Printf("Failed in json.Indent: %v\n", err) | |
635 | } | |
636 | log.Println(prettyJSON.String()) | |
333 | 637 | } |
334 | 638 | |
335 | 639 | if statusCode >= 400 && statusCode <= 599 { |
336 | 640 | errorResponse := ErrorResponse{} |
337 | 641 | err = json.Unmarshal(body, &errorResponse) |
642 | if err != nil { | |
643 | log.Printf("Failed in json.Unmarshal: %v\n", err) | |
644 | } | |
338 | 645 | ecsError := &Error{ |
339 | 646 | ErrorResponse: errorResponse, |
340 | 647 | StatusCode: statusCode, |
352 | 659 | } |
353 | 660 | |
354 | 661 | // Invoke sends the raw HTTP request for ECS services |
355 | func (client *Client) InvokeByFlattenMethod(action string, args interface{}, response interface{}) error { | |
662 | //改进了一下上面那个方法,可以使用各种Http方法 | |
663 | //2017.1.30 增加了一个path参数,用来拓展访问的地址 | |
664 | func (client *Client) InvokeByAnyMethod(method, action, path string, args interface{}, response interface{}) (err error) { | |
356 | 665 | if err := client.ensureProperties(); err != nil { |
357 | 666 | return err |
358 | 667 | } |
359 | 668 | |
669 | // log request | |
670 | fieldMap := make(map[string]string) | |
671 | initLogMsg(fieldMap) | |
672 | defer func() { | |
673 | client.printLog(fieldMap, err) | |
674 | }() | |
675 | ||
360 | 676 | //init endpoint |
361 | if err := client.initEndpoint(); err != nil { | |
362 | return err | |
363 | } | |
364 | ||
365 | request := Request{} | |
366 | request.init(client.version, action, client.AccessKeyId, client.securityToken, client.regionID) | |
367 | ||
368 | query := util.ConvertToQueryValues(request) | |
369 | ||
370 | util.SetQueryValueByFlattenMethod(args, &query) | |
371 | ||
372 | // Sign request | |
373 | signature := util.CreateSignatureForRequest(ECSRequestMethod, &query, client.AccessKeySecret) | |
374 | ||
375 | // Generate the request URL | |
376 | requestURL := client.endpoint + "?" + query.Encode() + "&Signature=" + url.QueryEscape(signature) | |
377 | ||
378 | httpReq, err := http.NewRequest(ECSRequestMethod, requestURL, nil) | |
379 | ||
380 | if err != nil { | |
381 | return GetClientError(err) | |
382 | } | |
383 | ||
384 | // TODO move to util and add build val flag | |
385 | httpReq.Header.Set("X-SDK-Client", `AliyunGO/`+Version+client.businessInfo) | |
386 | ||
387 | httpReq.Header.Set("User-Agent", httpReq.UserAgent()+" "+client.userAgent) | |
388 | ||
389 | t0 := time.Now() | |
390 | httpResp, err := client.httpClient.Do(httpReq) | |
391 | t1 := time.Now() | |
392 | if err != nil { | |
393 | return GetClientError(err) | |
394 | } | |
395 | statusCode := httpResp.StatusCode | |
396 | ||
397 | if client.debug { | |
398 | log.Printf("Invoke %s %s %d (%v)", ECSRequestMethod, requestURL, statusCode, t1.Sub(t0)) | |
399 | } | |
400 | ||
401 | defer httpResp.Body.Close() | |
402 | body, err := ioutil.ReadAll(httpResp.Body) | |
403 | ||
404 | if err != nil { | |
405 | return GetClientError(err) | |
406 | } | |
407 | ||
408 | if client.debug { | |
409 | var prettyJSON bytes.Buffer | |
410 | err = json.Indent(&prettyJSON, body, "", " ") | |
411 | log.Println(string(prettyJSON.Bytes())) | |
412 | } | |
413 | ||
414 | if statusCode >= 400 && statusCode <= 599 { | |
415 | errorResponse := ErrorResponse{} | |
416 | err = json.Unmarshal(body, &errorResponse) | |
417 | ecsError := &Error{ | |
418 | ErrorResponse: errorResponse, | |
419 | StatusCode: statusCode, | |
420 | } | |
421 | return ecsError | |
422 | } | |
423 | ||
424 | err = json.Unmarshal(body, response) | |
425 | //log.Printf("%++v", response) | |
426 | if err != nil { | |
427 | return GetClientError(err) | |
428 | } | |
429 | ||
430 | return nil | |
431 | } | |
432 | ||
433 | // Invoke sends the raw HTTP request for ECS services | |
434 | //改进了一下上面那个方法,可以使用各种Http方法 | |
435 | //2017.1.30 增加了一个path参数,用来拓展访问的地址 | |
436 | func (client *Client) InvokeByAnyMethod(method, action, path string, args interface{}, response interface{}) error { | |
437 | if err := client.ensureProperties(); err != nil { | |
438 | return err | |
439 | } | |
440 | ||
441 | //init endpoint | |
442 | if err := client.initEndpoint(); err != nil { | |
443 | return err | |
444 | } | |
677 | //if err := client.initEndpoint(); err != nil { | |
678 | // return err | |
679 | //} | |
445 | 680 | |
446 | 681 | request := Request{} |
447 | 682 | request.init(client.version, action, client.AccessKeyId, client.securityToken, client.regionID) |
455 | 690 | // Generate the request URL |
456 | 691 | var ( |
457 | 692 | httpReq *http.Request |
458 | err error | |
459 | 693 | ) |
460 | 694 | if method == http.MethodGet { |
461 | 695 | requestURL := client.endpoint + path + "?" + data.Encode() |
475 | 709 | httpReq.Header.Set("X-SDK-Client", `AliyunGO/`+Version+client.businessInfo) |
476 | 710 | httpReq.Header.Set("User-Agent", httpReq.Header.Get("User-Agent")+" "+client.userAgent) |
477 | 711 | |
712 | // Set tracer | |
713 | var span opentracing.Span | |
714 | if ok := opentracing.IsGlobalTracerRegistered(); ok && !client.disableTrace { | |
715 | tracer := opentracing.GlobalTracer() | |
716 | var rootCtx opentracing.SpanContext | |
717 | ||
718 | if client.span != nil { | |
719 | rootCtx = client.span.Context() | |
720 | } | |
721 | ||
722 | span = tracer.StartSpan( | |
723 | "AliyunGO-"+request.Action, | |
724 | opentracing.ChildOf(rootCtx), | |
725 | opentracing.Tag{string(ext.Component), "AliyunGO"}, | |
726 | opentracing.Tag{"ActionName", request.Action}) | |
727 | ||
728 | defer span.Finish() | |
729 | tracer.Inject( | |
730 | span.Context(), | |
731 | opentracing.HTTPHeaders, | |
732 | opentracing.HTTPHeadersCarrier(httpReq.Header)) | |
733 | } | |
734 | ||
735 | putMsgToMap(fieldMap, httpReq) | |
478 | 736 | t0 := time.Now() |
737 | fieldMap["{start_time}"] = t0.Format("2006-01-02 15:04:05") | |
479 | 738 | httpResp, err := client.httpClient.Do(httpReq) |
480 | 739 | t1 := time.Now() |
481 | if err != nil { | |
482 | return GetClientError(err) | |
483 | } | |
740 | fieldMap["{cost}"] = t1.Sub(t0).String() | |
741 | if err != nil { | |
742 | if span != nil { | |
743 | ext.LogError(span, err) | |
744 | } | |
745 | return GetClientError(err) | |
746 | } | |
747 | fieldMap["{code}"] = strconv.Itoa(httpResp.StatusCode) | |
748 | fieldMap["{res_headers}"] = TransToString(httpResp.Header) | |
484 | 749 | statusCode := httpResp.StatusCode |
485 | 750 | |
486 | 751 | if client.debug { |
487 | 752 | log.Printf("Invoke %s %s %d (%v) %v", ECSRequestMethod, client.endpoint, statusCode, t1.Sub(t0), data.Encode()) |
488 | 753 | } |
489 | 754 | |
755 | if span != nil { | |
756 | ext.HTTPStatusCode.Set(span, uint16(httpResp.StatusCode)) | |
757 | } | |
758 | ||
490 | 759 | defer httpResp.Body.Close() |
491 | 760 | body, err := ioutil.ReadAll(httpResp.Body) |
761 | fieldMap["{res_body}"] = string(body) | |
492 | 762 | |
493 | 763 | if err != nil { |
494 | 764 | return GetClientError(err) |
497 | 767 | if client.debug { |
498 | 768 | var prettyJSON bytes.Buffer |
499 | 769 | err = json.Indent(&prettyJSON, body, "", " ") |
500 | log.Println(string(prettyJSON.Bytes())) | |
770 | log.Println(prettyJSON.String()) | |
501 | 771 | } |
502 | 772 | |
503 | 773 | if statusCode >= 400 && statusCode <= 599 { |
547 | 817 | StatusCode: 400, |
548 | 818 | } |
549 | 819 | } |
820 | ||
821 | func putMsgToMap(fieldMap map[string]string, request *http.Request) { | |
822 | fieldMap["{host}"] = request.Host | |
823 | fieldMap["{method}"] = request.Method | |
824 | fieldMap["{uri}"] = request.URL.RequestURI() | |
825 | fieldMap["{pid}"] = strconv.Itoa(os.Getpid()) | |
826 | fieldMap["{version}"] = strings.Split(request.Proto, "/")[1] | |
827 | hostname, _ := os.Hostname() | |
828 | fieldMap["{hostname}"] = hostname | |
829 | fieldMap["{req_headers}"] = TransToString(request.Header) | |
830 | fieldMap["{target}"] = request.URL.Path + request.URL.RawQuery | |
831 | } |
0 | 0 | package common |
1 | 1 | |
2 | import "os" | |
2 | import ( | |
3 | "fmt" | |
4 | "github.com/opentracing/opentracing-go" | |
5 | "github.com/stretchr/testify/assert" | |
6 | "github.com/uber/jaeger-client-go" | |
7 | jaegercfg "github.com/uber/jaeger-client-go/config" | |
8 | jaegerlog "github.com/uber/jaeger-client-go/log" | |
9 | "net/http" | |
10 | "os" | |
11 | "testing" | |
12 | ) | |
3 | 13 | |
4 | 14 | var ( |
5 | 15 | TestAccessKeyId = os.Getenv("AccessKeyId") |
17 | 27 | } |
18 | 28 | return testDebugClient |
19 | 29 | } |
30 | ||
31 | func TestClient_SetTransport(t *testing.T) { | |
32 | client := NewTestClientForDebug() | |
33 | transport := &myTransport{} | |
34 | client.SetTransport(transport) | |
35 | if client.httpClient.Transport.(*myTransport) != transport { | |
36 | t.Fail() | |
37 | } | |
38 | } | |
39 | ||
40 | type myTransport struct{} | |
41 | ||
42 | func (m *myTransport) RoundTrip(req *http.Request) (*http.Response, error) { | |
43 | return http.DefaultTransport.RoundTrip(req) | |
44 | } | |
45 | ||
46 | func Test_InitClient4RegionalDomain(t *testing.T) { | |
47 | ||
48 | var tests = []struct { | |
49 | service string | |
50 | version string | |
51 | endpoint string | |
52 | }{ | |
53 | {"ecs", "2014-05-26", "https://ecs-cn-hangzhou.aliyuncs.com"}, | |
54 | {"pvtz", "2018-01-01", "https://pvtz.aliyuncs.com"}, | |
55 | {"slb", "2014-05-15", "https://slb.aliyuncs.com"}, | |
56 | {"vpc", "2016-04-28", "https://vpc.aliyuncs.com"}, | |
57 | } | |
58 | ||
59 | for _, test := range tests { | |
60 | for _, region := range ValidRegions { | |
61 | if region == Qingdao || region == HangZhouFinance { | |
62 | continue | |
63 | } | |
64 | ||
65 | client := &Client{} | |
66 | client.SetDebug(true) | |
67 | client.WithEndpoint(test.endpoint). | |
68 | WithVersion(test.version). | |
69 | WithAccessKeyId(TestAccessKeyId). | |
70 | WithAccessKeySecret(TestAccessKeySecret). | |
71 | WithSecurityToken(TestSecurityToken). | |
72 | WithServiceCode(test.service). | |
73 | WithRegionID(region). | |
74 | InitClient4RegionalDomain() | |
75 | ||
76 | if endpoint, ok := CentralDomainServices[test.service]; ok { | |
77 | domain := fmt.Sprintf("https://%s", endpoint) | |
78 | if client.endpoint != domain { | |
79 | t.Fail() | |
80 | } | |
81 | continue | |
82 | } | |
83 | ||
84 | if ep, ok := UnitRegions[region]; ok { | |
85 | domain := fmt.Sprintf("https://%s.%s.aliyuncs.com", test.service, ep) | |
86 | if client.endpoint != domain { | |
87 | t.Fail() | |
88 | } | |
89 | continue | |
90 | } | |
91 | ||
92 | domain := fmt.Sprintf("https://%s%s.%s.aliyuncs.com", test.service, "-vpc", region) | |
93 | if client.endpoint != domain { | |
94 | t.Fail() | |
95 | } | |
96 | } | |
97 | ||
98 | } | |
99 | } | |
100 | ||
101 | func Test_InvokeTracer(t *testing.T) { | |
102 | client := NewTestClientForDebug() | |
103 | assert.NotNil(t, client) | |
104 | args := &DescribeEndpointsArgs{ | |
105 | Id: Hangzhou, | |
106 | ServiceCode: "ecs", | |
107 | Type: "openAPI", | |
108 | } | |
109 | // not set global tracer | |
110 | resp, err := client.DescribeEndpoints(args) | |
111 | t.Log(resp) | |
112 | assert.Nil(t, err) | |
113 | ||
114 | //set global tracer, no root span | |
115 | var cfg = jaegercfg.Configuration{ | |
116 | ServiceName: "client test", | |
117 | Sampler: &jaegercfg.SamplerConfig{ | |
118 | Type: jaeger.SamplerTypeConst, | |
119 | Param: 1, | |
120 | }, | |
121 | Reporter: &jaegercfg.ReporterConfig{ | |
122 | LogSpans: true, | |
123 | }, | |
124 | } | |
125 | jLogger := jaegerlog.StdLogger | |
126 | tracer, closer, _ := cfg.NewTracer( | |
127 | jaegercfg.Logger(jLogger), | |
128 | ) | |
129 | opentracing.InitGlobalTracer(tracer) | |
130 | resp, err = client.DescribeEndpoints(args) | |
131 | t.Log(resp) | |
132 | assert.Nil(t, err) | |
133 | ||
134 | // set global tracer, with root span | |
135 | parentSpan := tracer.StartSpan("root") | |
136 | fmt.Println(parentSpan) | |
137 | client.SetSpan(parentSpan) | |
138 | resp, err = client.DescribeEndpoints(args) | |
139 | t.Log(resp) | |
140 | assert.Nil(t, err) | |
141 | ||
142 | // set disable trace | |
143 | client.SetDisableTrace(true) | |
144 | client.SetSpan(parentSpan) | |
145 | resp, err = client.DescribeEndpoints(args) | |
146 | t.Log(resp) | |
147 | assert.Nil(t, err) | |
148 | ||
149 | parentSpan.Finish() | |
150 | closer.Close() | |
151 | } |
3 | 3 | "encoding/xml" |
4 | 4 | "fmt" |
5 | 5 | "io/ioutil" |
6 | "log" | |
6 | 7 | "os" |
7 | 8 | "strings" |
9 | "sync" | |
8 | 10 | "time" |
9 | "log" | |
10 | 11 | ) |
11 | 12 | |
12 | 13 | const ( |
18 | 19 | ) |
19 | 20 | |
20 | 21 | var ( |
21 | endpoints = make(map[Region]map[string]string) | |
22 | //endpoints = make(map[Region]map[string]string) | |
23 | ||
24 | endpoints = sync.Map{} | |
22 | 25 | |
23 | 26 | SpecailEnpoints = map[Region]map[string]string{ |
24 | 27 | APNorthEast1: { |
50 | 53 | "slb": "https://slb.eu-central-1.aliyuncs.com", |
51 | 54 | "rds": "https://rds.eu-central-1.aliyuncs.com", |
52 | 55 | "vpc": "https://vpc.eu-central-1.aliyuncs.com", |
56 | }, | |
57 | EUWest1: { | |
58 | "ecs": "https://ecs.eu-west-1.aliyuncs.com", | |
59 | "slb": "https://slb.eu-west-1.aliyuncs.com", | |
60 | "rds": "https://rds.eu-west-1.aliyuncs.com", | |
61 | "vpc": "https://vpc.eu-west-1.aliyuncs.com", | |
53 | 62 | }, |
54 | 63 | Zhangjiakou: { |
55 | 64 | "ecs": "https://ecs.cn-zhangjiakou.aliyuncs.com", |
122 | 131 | } |
123 | 132 | |
124 | 133 | func getProductRegionEndpoint(region Region, serviceCode string) string { |
125 | if sp, ok := endpoints[region]; ok { | |
126 | if endpoint, ok := sp[serviceCode]; ok { | |
127 | return endpoint | |
128 | } | |
129 | } | |
130 | ||
134 | ||
135 | if sp, ok := endpoints.Load(region); ok { | |
136 | spt, ok := sp.(*sync.Map) | |
137 | if ok { | |
138 | if endp, ok := spt.Load(serviceCode); ok { | |
139 | return endp.(string) | |
140 | } | |
141 | } | |
142 | } | |
131 | 143 | return "" |
132 | 144 | } |
133 | 145 | |
134 | 146 | func setProductRegionEndpoint(region Region, serviceCode string, endpoint string) { |
135 | endpoints[region] = map[string]string{ | |
136 | serviceCode: endpoint, | |
137 | } | |
147 | m := sync.Map{} | |
148 | m.Store(serviceCode, endpoint) | |
149 | endpoints.Store(region, &m) | |
138 | 150 | } |
139 | 151 | |
140 | 152 | func (client *LocationClient) DescribeOpenAPIEndpoint(region Region, serviceCode string) string { |
160 | 172 | } |
161 | 173 | |
162 | 174 | if err != nil || endpoint == nil || len(endpoint.Endpoints.Endpoint) <= 0 { |
163 | log.Printf("aliyungo: can not get endpoint from service, use default. endpoint=[%v], error=[%v]\n",endpoint, err) | |
175 | log.Printf("aliyungo: can not get endpoint from service, use default. endpoint=[%v], error=[%v]\n", endpoint, err) | |
164 | 176 | return "" |
165 | 177 | } |
166 | 178 |
1335 | 1335 | <Product><ProductName>Slb</ProductName><DomainName>slb.eu-central-1.aliyuncs.com</DomainName></Product> |
1336 | 1336 | </Products> |
1337 | 1337 | </Endpoint> |
1338 | <Endpoint name="eu-west-1"> | |
1339 | <RegionIds><RegionId>eu-west-1</RegionId></RegionIds> | |
1340 | <Products> | |
1341 | <Product><ProductName>Rds</ProductName><DomainName>rds.eu-west-1.aliyuncs.com</DomainName></Product> | |
1342 | <Product><ProductName>Ecs</ProductName><DomainName>ecs.eu-west-1.aliyuncs.com</DomainName></Product> | |
1343 | <Product><ProductName>Vpc</ProductName><DomainName>vpc.eu-west-1.aliyuncs.com</DomainName></Product> | |
1344 | <Product><ProductName>Kms</ProductName><DomainName>kms.eu-west-1.aliyuncs.com</DomainName></Product> | |
1345 | <Product><ProductName>Cms</ProductName><DomainName>metrics.cn-hangzhou.aliyuncs.com</DomainName></Product> | |
1346 | <Product><ProductName>Slb</ProductName><DomainName>slb.eu-west-1.aliyuncs.com</DomainName></Product> | |
1347 | </Products> | |
1348 | </Endpoint> | |
1338 | 1349 | <Endpoint name="cn-zhangjiakou"> |
1339 | 1350 | <RegionIds><RegionId>cn-zhangjiakou</RegionId></RegionIds> |
1340 | 1351 | <Products> |
0 | package common | |
1 | ||
2 | import ( | |
3 | "encoding/json" | |
4 | "github.com/denverdino/aliyungo/common/utils" | |
5 | "io" | |
6 | "log" | |
7 | "os" | |
8 | "strings" | |
9 | "time" | |
10 | ) | |
11 | ||
12 | var logChannel string | |
13 | var defaultChannel = "AliyunGO" | |
14 | ||
15 | type Logger struct { | |
16 | *log.Logger | |
17 | formatTemplate string | |
18 | isOpen bool | |
19 | lastLogMsg string | |
20 | } | |
21 | ||
22 | var defaultLoggerTemplate = `{time} {channel}: "{method} {uri} HTTP/{version}" {code} {cost} {hostname}` | |
23 | var loggerParam = []string{"{time}", "{start_time}", "{ts}", "{channel}", "{pid}", "{host}", "{method}", "{uri}", "{version}", "{target}", "{hostname}", "{code}", "{error}", "{req_headers}", "{res_body}", "{res_headers}", "{cost}"} | |
24 | ||
25 | func initLogMsg(fieldMap map[string]string) { | |
26 | for _, value := range loggerParam { | |
27 | fieldMap[value] = "" | |
28 | } | |
29 | } | |
30 | ||
31 | func (client *Client) SetLogger(level string, channel string, out io.Writer, template string) { | |
32 | if level == "" { | |
33 | level = "info" | |
34 | } | |
35 | ||
36 | logChannel = "AliyunGO" | |
37 | if channel != "" { | |
38 | logChannel = channel | |
39 | } | |
40 | log := log.New(out, "["+strings.ToUpper(level)+"]", log.Lshortfile) | |
41 | if template == "" { | |
42 | template = defaultLoggerTemplate | |
43 | } | |
44 | ||
45 | client.logger = &Logger{ | |
46 | Logger: log, | |
47 | formatTemplate: template, | |
48 | isOpen: true, | |
49 | } | |
50 | } | |
51 | ||
52 | func (client *Client) GetLogger() *Logger { | |
53 | return client.logger | |
54 | } | |
55 | ||
56 | func (client *Client) GetLoggerMsg() string { | |
57 | if client.logger == nil { | |
58 | client.SetLogger("", "", os.Stdout, "") | |
59 | } | |
60 | return client.logger.lastLogMsg | |
61 | } | |
62 | ||
63 | func (client *Client) OpenLogger() { | |
64 | if client.logger == nil { | |
65 | client.SetLogger("", "", os.Stdout, "") | |
66 | } | |
67 | client.logger.isOpen = true | |
68 | } | |
69 | ||
70 | func (client *Client) CloseLogger() { | |
71 | if client.logger != nil { | |
72 | client.logger.isOpen = false | |
73 | } | |
74 | } | |
75 | ||
76 | func (client *Client) SetTemplate(template string) { | |
77 | if client.logger == nil { | |
78 | client.SetLogger("", "", os.Stdout, "") | |
79 | } | |
80 | client.logger.formatTemplate = template | |
81 | } | |
82 | ||
83 | func (client *Client) GetTemplate() string { | |
84 | if client.logger == nil { | |
85 | client.SetLogger("", "", os.Stdout, "") | |
86 | } | |
87 | return client.logger.formatTemplate | |
88 | } | |
89 | ||
90 | func TransToString(object interface{}) string { | |
91 | byt, err := json.Marshal(object) | |
92 | if err != nil { | |
93 | return "" | |
94 | } | |
95 | return string(byt) | |
96 | } | |
97 | ||
98 | func (client *Client) printLog(fieldMap map[string]string, err error) { | |
99 | if err != nil { | |
100 | fieldMap["{error}"] = err.Error() | |
101 | } | |
102 | fieldMap["{time}"] = time.Now().Format("2006-01-02 15:04:05") | |
103 | fieldMap["{ts}"] = utils.GetTimeInFormatISO8601() | |
104 | fieldMap["{channel}"] = logChannel | |
105 | if client.logger != nil { | |
106 | logMsg := client.logger.formatTemplate | |
107 | for key, value := range fieldMap { | |
108 | logMsg = strings.Replace(logMsg, key, value, -1) | |
109 | } | |
110 | client.logger.lastLogMsg = logMsg | |
111 | if client.logger.isOpen == true { | |
112 | client.logger.Output(2, logMsg) | |
113 | } | |
114 | } | |
115 | } |
0 | package common | |
1 | ||
2 | import ( | |
3 | "bytes" | |
4 | "github.com/stretchr/testify/assert" | |
5 | "testing" | |
6 | ) | |
7 | ||
8 | func Test_Client_Logger(t *testing.T) { | |
9 | client := NewTestClientForDebug() | |
10 | assert.NotNil(t, client) | |
11 | args := &DescribeEndpointsArgs{ | |
12 | Id: Hangzhou, | |
13 | ServiceCode: "ecs", | |
14 | Type: "openAPI", | |
15 | } | |
16 | // without logger | |
17 | resp, err := client.DescribeEndpoints(args) | |
18 | t.Log(resp) | |
19 | assert.Nil(t, err) | |
20 | ||
21 | // with logger | |
22 | wr := new(bytes.Buffer) | |
23 | assert.Nil(t, err) | |
24 | template := `{time} {channel}: {method} {host} {uri} HTTP/{version} {code} {cost} {hostname} {req_headers} {error} {res_body}` | |
25 | client.SetLogger("", "openapi", wr, template) | |
26 | resp, err = client.DescribeEndpoints(args) | |
27 | t.Log(wr.String()) | |
28 | t.Log(resp) | |
29 | assert.Nil(t, err) | |
30 | } |
13 | 13 | Zhangjiakou = Region("cn-zhangjiakou") |
14 | 14 | Huhehaote = Region("cn-huhehaote") |
15 | 15 | |
16 | Chengdu = Region("cn-chengdu") | |
17 | ||
16 | 18 | APSouthEast1 = Region("ap-southeast-1") |
17 | 19 | APNorthEast1 = Region("ap-northeast-1") |
18 | 20 | APSouthEast2 = Region("ap-southeast-2") |
27 | 29 | MEEast1 = Region("me-east-1") |
28 | 30 | |
29 | 31 | EUCentral1 = Region("eu-central-1") |
32 | EUWest1 = Region("eu-west-1") | |
30 | 33 | |
31 | 34 | ShenZhenFinance = Region("cn-shenzhen-finance-1") |
32 | 35 | ShanghaiFinance = Region("cn-shanghai-finance-1") |
36 | HangZhouFinance = Region("cn-hangzhou-finance-1") | |
37 | ||
38 | CNNorth2Gov1 = Region("cn-north-2-gov-1") | |
39 | RUSWest1 = Region("rus-west-1") | |
33 | 40 | ) |
34 | 41 | |
35 | 42 | var ValidRegions = []Region{ |
38 | 45 | APNorthEast1, APSouthEast1, APSouthEast2, APSouthEast3, APSouthEast5, |
39 | 46 | APSouth1, |
40 | 47 | MEEast1, |
41 | EUCentral1, | |
42 | ShenZhenFinance, ShanghaiFinance, | |
48 | EUCentral1, EUWest1, | |
49 | ShenZhenFinance, ShanghaiFinance, HangZhouFinance, CNNorth2Gov1, | |
43 | 50 | } |
44 | 51 | |
45 | 52 | // IsValidRegion checks if r is an Ali supported region. |
12 | 12 | PrePaid = InstanceChargeType("PrePaid") |
13 | 13 | PostPaid = InstanceChargeType("PostPaid") |
14 | 14 | ) |
15 | ||
16 | var SpecialDeployedProducts = map[string]map[Region]interface{}{ | |
17 | "vpc": { | |
18 | Hangzhou: Hangzhou, | |
19 | Shenzhen: Shenzhen, | |
20 | APSouthEast1: APSouthEast1, | |
21 | USWest1: USWest1, | |
22 | USEast1: USEast1, | |
23 | Chengdu: Chengdu, | |
24 | Zhangjiakou: Zhangjiakou, | |
25 | Huhehaote: Huhehaote, | |
26 | APSouthEast3: APSouthEast3, | |
27 | EUCentral1: EUCentral1, | |
28 | EUWest1: EUWest1, | |
29 | APSouth1: APSouth1, | |
30 | APNorthEast1: APNorthEast1, | |
31 | APSouthEast5: APSouthEast5, | |
32 | APSouthEast2: APSouthEast2, | |
33 | MEEast1: MEEast1, | |
34 | CNNorth2Gov1: CNNorth2Gov1, | |
35 | }, | |
36 | } | |
37 | ||
38 | var CentralDomainServices = map[string]string{ | |
39 | "pvtz": "pvtz.vpc-proxy.aliyuncs.com", | |
40 | } | |
41 | ||
42 | var RegionalDomainServices = []string{ | |
43 | "ecs", | |
44 | "vpc", | |
45 | "slb", | |
46 | } | |
47 | ||
48 | // Unit-Domain of central product | |
49 | var UnitRegions = map[Region]interface{}{ | |
50 | Hangzhou: Hangzhou, | |
51 | Shenzhen: Shenzhen, | |
52 | APSouthEast1: APSouthEast1, | |
53 | USWest1: USWest1, | |
54 | USEast1: USEast1, | |
55 | Chengdu: Chengdu, | |
56 | Zhangjiakou: Zhangjiakou, | |
57 | Huhehaote: Huhehaote, | |
58 | APSouthEast3: APSouthEast3, | |
59 | EUCentral1: EUCentral1, | |
60 | EUWest1: EUWest1, | |
61 | APSouth1: APSouth1, | |
62 | APNorthEast1: APNorthEast1, | |
63 | APSouthEast5: APSouthEast5, | |
64 | APSouthEast2: APSouthEast2, | |
65 | CNNorth2Gov1: CNNorth2Gov1, | |
66 | //MEEast1: MEEast1, | |
67 | //RUSWest1: RUSWest1, | |
68 | //Beijing: Beijing, | |
69 | //Shanghai: Shanghai, | |
70 | //Hongkong: Hongkong, | |
71 | //ShanghaiFinance: ShanghaiFinance, | |
72 | //ShenZhenFinance: ShenZhenFinance, | |
73 | HangZhouFinance: Hangzhou, | |
74 | } | |
15 | 75 | |
16 | 76 | type DescribeEndpointArgs struct { |
17 | 77 | Id Region |
0 | package utils | |
1 | ||
2 | import "time" | |
3 | ||
4 | func GetTimeInFormatISO8601() (timeStr string) { | |
5 | gmt := time.FixedZone("GMT", 0) | |
6 | ||
7 | return time.Now().In(gmt).Format("2006-01-02T15:04:05Z") | |
8 | } |
75 | 75 | client.userAgent = userAgent |
76 | 76 | } |
77 | 77 | |
78 | // SetEndpoint sets customer endpoint | |
79 | func (client *Client) SetEndpoint(endpoint string) { | |
80 | client.endpoint = endpoint | |
81 | } | |
82 | ||
83 | // SetTransport sets transport to the http client | |
84 | func (client *Client) SetTransport(transport http.RoundTripper) { | |
85 | if client.httpClient == nil { | |
86 | client.httpClient = &http.Client{} | |
87 | } | |
88 | client.httpClient.Transport = transport | |
89 | } | |
90 | ||
78 | 91 | type Request struct { |
79 | 92 | Method string |
80 | 93 | URL string |
172 | 185 | |
173 | 186 | if client.debug { |
174 | 187 | var prettyJSON bytes.Buffer |
175 | err = json.Indent(&prettyJSON, body, "", " ") | |
176 | log.Println(string(prettyJSON.Bytes())) | |
188 | _ = json.Indent(&prettyJSON, body, "", " ") | |
189 | log.Println(prettyJSON.String()) | |
177 | 190 | } |
178 | 191 | |
179 | 192 | if statusCode >= 400 && statusCode <= 599 { |
180 | 193 | errorResponse := common.ErrorResponse{} |
181 | err = json.Unmarshal(body, &errorResponse) | |
194 | _ = json.Unmarshal(body, &errorResponse) | |
182 | 195 | ecsError := &common.Error{ |
183 | 196 | ErrorResponse: errorResponse, |
184 | 197 | StatusCode: statusCode, |
186 | 199 | return ecsError |
187 | 200 | } |
188 | 201 | |
189 | if response != nil { | |
202 | if response != nil && len(body) > 0 { | |
190 | 203 | err = json.Unmarshal(body, response) |
191 | 204 | //log.Printf("%++v", response) |
192 | 205 | if err != nil { |
10 | 10 | "fmt" |
11 | 11 | |
12 | 12 | "encoding/json" |
13 | ||
13 | 14 | "github.com/denverdino/aliyungo/common" |
14 | 15 | "github.com/denverdino/aliyungo/ecs" |
15 | 16 | ) |
26 | 27 | DeleteFailed = ClusterState("deleteFailed") |
27 | 28 | Deleted = ClusterState("deleted") |
28 | 29 | InActive = ClusterState("inactive") |
30 | ||
31 | ClusterTypeKubernetes = "Kubernetes" | |
32 | ClusterTypeManagedKubernetes = "ManagedKubernetes" | |
33 | ||
34 | ClusterTypeServerlessKubernetes = "Ask" | |
35 | ||
36 | ProfileServerlessKubernetes = "Serverless" | |
29 | 37 | ) |
38 | ||
39 | var NodeStableClusterState = []ClusterState{Running, Updating, Failed, DeleteFailed, Deleted, InActive} | |
40 | ||
41 | var NodeUnstableClusterState = []ClusterState{Initial, Scaling, Deleting} | |
30 | 42 | |
31 | 43 | type NodeStatus struct { |
32 | 44 | Health int64 `json:"health"` |
59 | 71 | NodeStatus string `json:"node_status"` |
60 | 72 | DockerVersion string `json:"docker_version"` |
61 | 73 | ClusterType string `json:"cluster_type"` |
74 | Profile string `json:"profile"` | |
62 | 75 | } |
63 | 76 | |
64 | 77 | func (client *Client) DescribeClusters(nameFilter string) (clusters []ClusterType, err error) { |
91 | 104 | ECSImageID string `json:"ecs_image_id,omitempty"` |
92 | 105 | IOOptimized ecs.IoOptimized `json:"io_optimized"` |
93 | 106 | ReleaseEipFlag bool `json:"release_eip_flag"` |
94 | } | |
95 | ||
96 | type ClusterCreationResponse struct { | |
107 | NeedSLB bool `json:"need_slb"` | |
108 | } | |
109 | ||
110 | type ClusterCommonResponse struct { | |
97 | 111 | Response |
98 | ClusterID string `json:"cluster_id"` | |
99 | } | |
100 | ||
101 | func (client *Client) CreateCluster(region common.Region, args *ClusterCreationArgs) (cluster ClusterCreationResponse, err error) { | |
112 | ClusterID string `json:"cluster_id"` | |
113 | Token string `json:"token,omitempty"` | |
114 | TaskId string `json:"task_id,omitempty"` | |
115 | InstanceId string `json:"instanceId"` | |
116 | } | |
117 | ||
118 | //Deprecated | |
119 | func (client *Client) CreateCluster(region common.Region, args *ClusterCreationArgs) (cluster ClusterCommonResponse, err error) { | |
102 | 120 | err = client.Invoke(region, http.MethodPost, "/clusters", nil, args, &cluster) |
103 | 121 | return |
104 | 122 | } |
126 | 144 | SNatEntry bool `json:"SNatEntry,omitempty"` |
127 | 145 | } |
128 | 146 | |
147 | // Deprecated | |
129 | 148 | type KubernetesCreationArgs struct { |
130 | DisableRollback bool `json:"disable_rollback"` | |
131 | Name string `json:"name"` | |
132 | TimeoutMins int64 `json:"timeout_mins"` | |
133 | ZoneId string `json:"zoneid,omitempty"` | |
134 | VPCID string `json:"vpcid,omitempty"` | |
135 | VSwitchId string `json:"vswitchid,omitempty"` | |
136 | ContainerCIDR string `json:"container_cidr,omitempty"` | |
137 | ServiceCIDR string `json:"service_cidr,omitempty"` | |
149 | DisableRollback bool `json:"disable_rollback"` | |
150 | Name string `json:"name"` | |
151 | TimeoutMins int64 `json:"timeout_mins"` | |
152 | ZoneId string `json:"zoneid,omitempty"` | |
153 | VPCID string `json:"vpcid,omitempty"` | |
154 | RegionId string `json:"region_id,omitempty"` | |
155 | VSwitchId string `json:"vswitchid,omitempty"` | |
156 | VSwitchIds []string `json:"vswitch_ids,omitempty"` | |
157 | ImageId string `json:"image_id"` | |
158 | ContainerCIDR string `json:"container_cidr,omitempty"` | |
159 | ServiceCIDR string `json:"service_cidr,omitempty"` | |
160 | ||
138 | 161 | MasterInstanceType string `json:"master_instance_type,omitempty"` |
139 | 162 | MasterSystemDiskSize int64 `json:"master_system_disk_size,omitempty"` |
140 | 163 | MasterSystemDiskCategory ecs.DiskCategory `json:"master_system_disk_category,omitempty"` |
164 | ||
165 | MasterInstanceChargeType string `json:"master_instance_charge_type"` | |
166 | MasterPeriodUnit string `json:"master_period_unit"` | |
167 | MasterPeriod int `json:"master_period"` | |
168 | MasterAutoRenew bool `json:"master_auto_renew"` | |
169 | MasterAutoRenewPeriod int `json:"master_auto_renew_period"` | |
170 | ||
141 | 171 | WorkerInstanceType string `json:"worker_instance_type,omitempty"` |
172 | WorkerInstanceTypes []string `json:"worker_instance_types,omitempty"` | |
142 | 173 | WorkerSystemDiskSize int64 `json:"worker_system_disk_size,omitempty"` |
143 | 174 | WorkerSystemDiskCategory ecs.DiskCategory `json:"worker_system_disk_category,omitempty"` |
144 | WorkerDataDisk bool `json:"worker_data_disk,omitempty"` | |
145 | WorkerDataDiskCategory string `json:"worker_data_disk_category,omitempty"` | |
175 | WorkerDataDisk bool `json:"worker_data_disk"` | |
176 | WorkerDataDiskCategory ecs.DiskCategory `json:"worker_data_disk_category,omitempty"` | |
146 | 177 | WorkerDataDiskSize int64 `json:"worker_data_disk_size,omitempty"` |
147 | LoginPassword string `json:"login_password,omitempty"` | |
148 | KeyPair string `json:"key_pair,omitempty"` | |
149 | NumOfNodes int64 `json:"num_of_nodes,omitempty"` | |
150 | SNatEntry bool `json:"snat_entry,omitempty"` | |
151 | SSHFlags bool `json:"ssh_flags,omitempty"` | |
152 | CloudMonitorFlags bool `json:"cloud_monitor_flags,omitempty"` | |
178 | ||
179 | WorkerInstanceChargeType string `json:"worker_instance_charge_type"` | |
180 | WorkerPeriodUnit string `json:"worker_period_unit"` | |
181 | WorkerPeriod int `json:"worker_period"` | |
182 | WorkerAutoRenew bool `json:"worker_auto_renew"` | |
183 | WorkerAutoRenewPeriod int `json:"worker_auto_renew_period"` | |
184 | ||
185 | LoginPassword string `json:"login_password,omitempty"` | |
186 | KeyPair string `json:"key_pair,omitempty"` | |
187 | UserCA string `json:"user_ca,omitempty"` | |
188 | NumOfNodes int64 `json:"num_of_nodes,omitempty"` | |
189 | SNatEntry bool `json:"snat_entry"` | |
190 | SSHFlags bool `json:"ssh_flags"` | |
191 | CloudMonitorFlags bool `json:"cloud_monitor_flags"` | |
192 | NodeCIDRMask string `json:"node_cidr_mask,omitempty"` | |
193 | LoggingType string `json:"logging_type,omitempty"` | |
194 | SLSProjectName string `json:"sls_project_name,omitempty"` | |
195 | PublicSLB bool `json:"public_slb"` | |
153 | 196 | |
154 | 197 | ClusterType string `json:"cluster_type"` |
155 | 198 | Network string `json:"network,omitempty"` |
158 | 201 | StackParams KubernetesStackArgs `json:"stack_params,omitempty"` |
159 | 202 | } |
160 | 203 | |
204 | // Deprecated | |
161 | 205 | type KubernetesMultiAZCreationArgs struct { |
162 | DisableRollback bool `json:"disable_rollback"` | |
163 | Name string `json:"name"` | |
164 | TimeoutMins int64 `json:"timeout_mins"` | |
165 | ClusterType string `json:"cluster_type"` | |
166 | MultiAZ bool `json:"multi_az,omitempty"` | |
167 | VPCID string `json:"vpcid,omitempty"` | |
168 | ContainerCIDR string `json:"container_cidr"` | |
169 | ServiceCIDR string `json:"service_cidr"` | |
170 | VSwitchIdA string `json:"vswitch_id_a,omitempty"` | |
171 | VSwitchIdB string `json:"vswitch_id_b,omitempty"` | |
172 | VSwitchIdC string `json:"vswitch_id_c,omitempty"` | |
206 | DisableRollback bool `json:"disable_rollback"` | |
207 | Name string `json:"name"` | |
208 | TimeoutMins int64 `json:"timeout_mins"` | |
209 | ClusterType string `json:"cluster_type"` | |
210 | MultiAZ bool `json:"multi_az"` | |
211 | VPCID string `json:"vpcid,omitempty"` | |
212 | ImageId string `json:"image_id"` | |
213 | ContainerCIDR string `json:"container_cidr"` | |
214 | ServiceCIDR string `json:"service_cidr"` | |
215 | VSwitchIdA string `json:"vswitch_id_a,omitempty"` | |
216 | VSwitchIdB string `json:"vswitch_id_b,omitempty"` | |
217 | VSwitchIdC string `json:"vswitch_id_c,omitempty"` | |
218 | ||
173 | 219 | MasterInstanceTypeA string `json:"master_instance_type_a,omitempty"` |
174 | 220 | MasterInstanceTypeB string `json:"master_instance_type_b,omitempty"` |
175 | 221 | MasterInstanceTypeC string `json:"master_instance_type_c,omitempty"` |
176 | 222 | MasterSystemDiskCategory ecs.DiskCategory `json:"master_system_disk_category"` |
177 | 223 | MasterSystemDiskSize int64 `json:"master_system_disk_size"` |
224 | ||
225 | MasterInstanceChargeType string `json:"master_instance_charge_type"` | |
226 | MasterPeriodUnit string `json:"master_period_unit"` | |
227 | MasterPeriod int `json:"master_period"` | |
228 | MasterAutoRenew bool `json:"master_auto_renew"` | |
229 | MasterAutoRenewPeriod int `json:"master_auto_renew_period"` | |
230 | ||
178 | 231 | WorkerInstanceTypeA string `json:"worker_instance_type_a,omitempty"` |
179 | 232 | WorkerInstanceTypeB string `json:"worker_instance_type_b,omitempty"` |
180 | 233 | WorkerInstanceTypeC string `json:"worker_instance_type_c,omitempty"` |
181 | 234 | WorkerSystemDiskCategory ecs.DiskCategory `json:"worker_system_disk_category"` |
182 | 235 | WorkerSystemDiskSize int64 `json:"worker_system_disk_size"` |
183 | 236 | WorkerDataDisk bool `json:"worker_data_disk"` |
184 | WorkerDataDiskCategory string `json:"worker_data_disk_category"` | |
237 | WorkerDataDiskCategory ecs.DiskCategory `json:"worker_data_disk_category"` | |
185 | 238 | WorkerDataDiskSize int64 `json:"worker_data_disk_size"` |
186 | NumOfNodesA int64 `json:"num_of_nodes_a"` | |
187 | NumOfNodesB int64 `json:"num_of_nodes_b"` | |
188 | NumOfNodesC int64 `json:"num_of_nodes_c"` | |
189 | LoginPassword string `json:"login_password,omitempty"` | |
190 | KeyPair string `json:"key_pair,omitempty"` | |
191 | SSHFlags bool `json:"ssh_flags"` | |
192 | CloudMonitorFlags bool `json:"cloud_monitor_flags"` | |
239 | ||
240 | WorkerInstanceChargeType string `json:"worker_instance_charge_type"` | |
241 | WorkerPeriodUnit string `json:"worker_period_unit"` | |
242 | WorkerPeriod int `json:"worker_period"` | |
243 | WorkerAutoRenew bool `json:"worker_auto_renew"` | |
244 | WorkerAutoRenewPeriod int `json:"worker_auto_renew_period"` | |
245 | ||
246 | NumOfNodesA int64 `json:"num_of_nodes_a"` | |
247 | NumOfNodesB int64 `json:"num_of_nodes_b"` | |
248 | NumOfNodesC int64 `json:"num_of_nodes_c"` | |
249 | LoginPassword string `json:"login_password,omitempty"` | |
250 | KeyPair string `json:"key_pair,omitempty"` | |
251 | UserCA string `json:"user_ca,omitempty"` | |
252 | SSHFlags bool `json:"ssh_flags"` | |
253 | CloudMonitorFlags bool `json:"cloud_monitor_flags"` | |
254 | NodeCIDRMask string `json:"node_cidr_mask,omitempty"` | |
255 | LoggingType string `json:"logging_type,omitempty"` | |
256 | SLSProjectName string `json:"sls_project_name,omitempty"` | |
257 | PublicSLB bool `json:"public_slb"` | |
193 | 258 | |
194 | 259 | KubernetesVersion string `json:"kubernetes_version,omitempty"` |
195 | 260 | Network string `json:"network,omitempty"` |
196 | 261 | } |
197 | 262 | |
198 | func (client *Client) CreateKubernetesMultiAZCluster(region common.Region, args *KubernetesMultiAZCreationArgs) (cluster ClusterCreationResponse, err error) { | |
263 | // Deprecated | |
264 | func (client *Client) CreateKubernetesMultiAZCluster(region common.Region, args *KubernetesMultiAZCreationArgs) (cluster ClusterCommonResponse, err error) { | |
199 | 265 | err = client.Invoke(region, http.MethodPost, "/clusters", nil, args, &cluster) |
200 | 266 | return |
201 | 267 | } |
202 | 268 | |
203 | func (client *Client) CreateKubernetesCluster(region common.Region, args *KubernetesCreationArgs) (cluster ClusterCreationResponse, err error) { | |
269 | // Deprecated | |
270 | func (client *Client) CreateKubernetesCluster(region common.Region, args *KubernetesCreationArgs) (cluster ClusterCommonResponse, err error) { | |
204 | 271 | err = client.Invoke(region, http.MethodPost, "/clusters", nil, args, &cluster) |
205 | 272 | return |
206 | 273 | } |
213 | 280 | SubClass string `json:"SubClass"` |
214 | 281 | } |
215 | 282 | |
283 | // deprecated | |
216 | 284 | type KubernetesClusterParameter struct { |
217 | ServiceCidr string `json:"ServiceCIDR"` | |
218 | ContainerCidr string `json:"ContainerCIDR"` | |
219 | DockerVersion string `json:"DockerVersion"` | |
220 | EtcdVersion string `json:"EtcdVersion"` | |
221 | KubernetesVersion string `json:"KubernetesVersion"` | |
222 | VPCID string `json:"VpcId"` | |
223 | KeyPair string `json:"KeyPair"` | |
224 | MasterSystemDiskCategory string `json:"MasterSystemDiskCategory"` | |
225 | MasterSystemDiskSize string `json:"MasterSystemDiskSize"` | |
226 | WorkerSystemDiskCategory string `json:"WorkerSystemDiskCategory"` | |
227 | WorkerSystemDiskSize string `json:"WorkerSystemDiskSize"` | |
228 | ZoneId string `json:"ZoneId"` | |
285 | ServiceCidr string `json:"ServiceCIDR"` | |
286 | ContainerCidr string `json:"ContainerCIDR"` | |
287 | DockerVersion string `json:"DockerVersion"` | |
288 | EtcdVersion string `json:"EtcdVersion"` | |
289 | KubernetesVersion string `json:"KubernetesVersion"` | |
290 | VPCID string `json:"VpcId"` | |
291 | ImageId string `json:"ImageId"` | |
292 | KeyPair string `json:"KeyPair"` | |
293 | ||
294 | MasterSystemDiskCategory ecs.DiskCategory `json:"MasterSystemDiskCategory"` | |
295 | MasterSystemDiskSize string `json:"MasterSystemDiskSize"` | |
296 | MasterImageId string `json:"MasterImageId"` | |
297 | ||
298 | MasterInstanceChargeType string `json:"MasterInstanceChargeType"` | |
299 | MasterPeriodUnit string `json:"MasterPeriodUnit"` | |
300 | MasterPeriod string `json:"MasterPeriod"` | |
301 | MasterAutoRenew *bool | |
302 | RawMasterAutoRenew string `json:"MasterAutoRenew"` | |
303 | MasterAutoRenewPeriod string `json:"MasterAutoRenewPeriod"` | |
304 | ||
305 | WorkerSystemDiskCategory ecs.DiskCategory `json:"WorkerSystemDiskCategory"` | |
306 | WorkerSystemDiskSize string `json:"WorkerSystemDiskSize"` | |
307 | WorkerImageId string `json:"WorkerImageId"` | |
308 | WorkerDataDisk *bool | |
309 | RawWorkerDataDisk string `json:"WorkerDataDisk"` | |
310 | WorkerDataDiskCategory ecs.DiskCategory `json:"WorkerDataDiskCategory"` | |
311 | WorkerDataDiskSize string `json:"WorkerDataDiskSize"` | |
312 | ||
313 | WorkerInstanceChargeType string `json:"WorkerInstanceChargeType"` | |
314 | WorkerPeriodUnit string `json:"WorkerPeriodUnit"` | |
315 | WorkerPeriod string `json:"WorkerPeriod"` | |
316 | WorkerAutoRenew *bool | |
317 | RawWorkerAutoRenew string `json:"WorkerAutoRenew"` | |
318 | WorkerAutoRenewPeriod string `json:"WorkerAutoRenewPeriod"` | |
319 | ||
320 | ZoneId string `json:"ZoneId"` | |
321 | NodeCIDRMask string `json:"NodeCIDRMask"` | |
322 | LoggingType string `json:"LoggingType"` | |
323 | SLSProjectName string `json:"SLSProjectName"` | |
324 | PublicSLB *bool | |
325 | RawPublicSLB string `json:"PublicSLB"` | |
229 | 326 | |
230 | 327 | // Single AZ |
231 | 328 | MasterInstanceType string `json:"MasterInstanceType"` |
248 | 345 | VSwitchIdC string `json:"VSwitchIdC"` |
249 | 346 | } |
250 | 347 | |
348 | // Deprecated | |
251 | 349 | type KubernetesCluster struct { |
252 | 350 | ClusterType |
253 | 351 | |
277 | 375 | Parameters KubernetesClusterParameter `json:"parameters"` |
278 | 376 | } |
279 | 377 | |
378 | // Deprecated | |
280 | 379 | func (client *Client) DescribeKubernetesCluster(id string) (cluster KubernetesCluster, err error) { |
281 | 380 | err = client.Invoke("", http.MethodGet, "/clusters/"+id, nil, nil, &cluster) |
282 | 381 | if err != nil { |
283 | 382 | return cluster, err |
284 | 383 | } |
384 | ||
285 | 385 | var metaData KubernetesClusterMetaData |
286 | 386 | err = json.Unmarshal([]byte(cluster.RawMetaData), &metaData) |
387 | if err != nil { | |
388 | return cluster, err | |
389 | } | |
287 | 390 | cluster.MetaData = metaData |
288 | 391 | cluster.RawMetaData = "" |
289 | return | |
290 | } | |
291 | ||
392 | ||
393 | return | |
394 | } | |
395 | ||
396 | // Deprecated | |
292 | 397 | type ClusterResizeArgs struct { |
293 | 398 | Size int64 `json:"size"` |
294 | 399 | InstanceType string `json:"instance_type"` |
303 | 408 | Name string `json:"name"` |
304 | 409 | } |
305 | 410 | |
411 | // Deprecated | |
306 | 412 | func (client *Client) ResizeCluster(clusterID string, args *ClusterResizeArgs) error { |
307 | 413 | return client.Invoke("", http.MethodPut, "/clusters/"+clusterID, nil, args, nil) |
308 | 414 | } |
309 | 415 | |
310 | 416 | // deprecated |
311 | // use ResizeKubernetesCluster instead | |
417 | // use ScaleKubernetesCluster instead | |
312 | 418 | func (client *Client) ResizeKubernetes(clusterID string, args *KubernetesCreationArgs) error { |
313 | 419 | return client.Invoke("", http.MethodPut, "/clusters/"+clusterID, nil, args, nil) |
314 | 420 | } |
315 | 421 | |
422 | // Deprecated | |
316 | 423 | type KubernetesClusterResizeArgs struct { |
317 | 424 | DisableRollback bool `json:"disable_rollback"` |
318 | 425 | TimeoutMins int64 `json:"timeout_mins"` |
319 | 426 | LoginPassword string `json:"login_password,omitempty"` |
320 | 427 | |
321 | 428 | // Single AZ |
322 | WorkerInstanceType string `json:"worker_instance_type"` | |
323 | NumOfNodes int64 `json:"num_of_nodes"` | |
429 | WorkerInstanceType string `json:"worker_instance_type"` | |
430 | WorkerInstanceTypes []string `json:"worker_instance_types"` | |
431 | NumOfNodes int64 `json:"num_of_nodes"` | |
324 | 432 | |
325 | 433 | // Multi AZ |
326 | 434 | WorkerInstanceTypeA string `json:"worker_instance_type_a"` |
331 | 439 | NumOfNodesC int64 `json:"num_of_nodes_c"` |
332 | 440 | } |
333 | 441 | |
442 | // deprecated | |
443 | // use ScaleKubernetesCluster instead | |
334 | 444 | func (client *Client) ResizeKubernetesCluster(clusterID string, args *KubernetesClusterResizeArgs) error { |
335 | 445 | return client.Invoke("", http.MethodPut, "/clusters/"+clusterID, nil, args, nil) |
336 | 446 | } |
337 | 447 | |
448 | // Deprecated | |
449 | type KubernetesClusterScaleArgs struct { | |
450 | LoginPassword string `json:"login_password,omitempty"` | |
451 | KeyPair string `json:"key_pair,omitempty"` | |
452 | WorkerInstanceTypes []string `json:"worker_instance_types"` | |
453 | WorkerSystemDiskSize int64 `json:"worker_system_disk_size"` | |
454 | WorkerSystemDiskCategory ecs.DiskCategory `json:"worker_system_disk_category"` | |
455 | WorkerDataDisk bool `json:"worker_data_disk"` | |
456 | Count int `json:"count"` | |
457 | ||
458 | // Edge worker related args | |
459 | IsEdgeWorker bool `json:"is_edge_worker"` | |
460 | EnsRegionId string `json:"ens_region_id"` | |
461 | EnsInternetChargeType string `json:"ens_internet_charge_type"` | |
462 | ||
463 | //data disk | |
464 | WorkerDataDiskCategory ecs.DiskCategory `json:"worker_data_disk_category"` | |
465 | WorkerDataDiskSize int64 `json:"worker_data_disk_size"` | |
466 | WorkerDataDiskEncrypted string `json:"worker_data_disk_encrypted"` | |
467 | WorkerDataDiskKMSKeyId string `json:"worker_data_disk_kms_key_id"` | |
468 | } | |
469 | ||
470 | // Deprecated | |
471 | func (client *Client) ScaleKubernetesCluster(clusterID string, args *KubernetesClusterScaleArgs) error { | |
472 | return client.Invoke("", http.MethodPost, "/api/v2/clusters/"+clusterID, nil, args, nil) | |
473 | } | |
474 | ||
475 | // Deprecated | |
338 | 476 | func (client *Client) ModifyClusterName(clusterID, clusterName string) error { |
339 | 477 | return client.Invoke("", http.MethodPost, "/clusters/"+clusterID+"/name/"+clusterName, nil, nil, nil) |
340 | 478 | } |
341 | 479 | |
480 | // Deprecated | |
342 | 481 | func (client *Client) DeleteCluster(clusterID string) error { |
343 | 482 | return client.Invoke("", http.MethodDelete, "/clusters/"+clusterID, nil, nil, nil) |
344 | 483 | } |
354 | 493 | return |
355 | 494 | } |
356 | 495 | |
496 | type ClusterEndpoints struct { | |
497 | ApiServerEndpoint string `json:"api_server_endpoint"` | |
498 | DashboardEndpoint string `json:"dashboard_endpoint"` | |
499 | MiranaEndpoint string `json:"mirana_endpoint"` | |
500 | ReverseTunnelEndpoint string `json:"reverse_tunnel_endpoint"` | |
501 | IntranetApiServerEndpoint string `json:"intranet_api_server_endpoint"` | |
502 | } | |
503 | ||
504 | func (client *Client) GetClusterEndpoints(id string) (clusterEndpoints ClusterEndpoints, err error) { | |
505 | err = client.Invoke("", http.MethodGet, "/clusters/"+id+"/endpoints", nil, nil, &clusterEndpoints) | |
506 | return | |
507 | } | |
508 | ||
357 | 509 | type ClusterConfig struct { |
358 | 510 | Config string `json:"config"` |
359 | 511 | } |
360 | 512 | |
513 | // deprecated | |
514 | // Please use new api DescribeClusterUserConfig | |
361 | 515 | func (client *Client) GetClusterConfig(id string) (config ClusterConfig, err error) { |
362 | 516 | err = client.Invoke("", http.MethodGet, "/k8s/"+id+"/user_config", nil, nil, &config) |
363 | 517 | return |
374 | 528 | HostName string `json:"host_name"` |
375 | 529 | ImageId string `json:"image_id"` |
376 | 530 | InstanceId string `json:"instance_id"` |
531 | NodeName string `json:"node_name"` | |
377 | 532 | } |
378 | 533 | |
379 | 534 | type GetKubernetesClusterNodesResponse struct { |
382 | 537 | Nodes []KubernetesNodeType `json:"nodes"` |
383 | 538 | } |
384 | 539 | |
385 | func (client *Client) GetKubernetesClusterNodes(id string, pagination common.Pagination) (nodes []KubernetesNodeType, paginationResult *PaginationResult, err error) { | |
540 | // GetKubernetesClusterNodes is used to get cluster nodes or node pool nodes | |
541 | func (client *Client) GetKubernetesClusterNodes(id string, pagination common.Pagination, nodepoolId string) (nodes []KubernetesNodeType, paginationResult *PaginationResult, err error) { | |
386 | 542 | response := &GetKubernetesClusterNodesResponse{} |
387 | err = client.Invoke("", http.MethodGet, "/clusters/"+id+"/nodes?pageNumber="+strconv.Itoa(pagination.PageNumber)+"&pageSize="+strconv.Itoa(pagination.PageSize), nil, nil, &response) | |
543 | if nodepoolId != "" { | |
544 | err = client.Invoke("", http.MethodGet, "/clusters/"+id+"/nodes?nodepool_id="+nodepoolId+"&pageNumber="+strconv.Itoa(pagination.PageNumber)+"&pageSize="+strconv.Itoa(pagination.PageSize), nil, nil, &response) | |
545 | } else { | |
546 | err = client.Invoke("", http.MethodGet, "/clusters/"+id+"/nodes?pageNumber="+strconv.Itoa(pagination.PageNumber)+"&pageSize="+strconv.Itoa(pagination.PageSize), nil, nil, &response) | |
547 | } | |
388 | 548 | if err != nil { |
389 | 549 | return nil, nil, err |
390 | 550 | } |
394 | 554 | |
395 | 555 | const ClusterDefaultTimeout = 300 |
396 | 556 | const DefaultWaitForInterval = 10 |
397 | const DefaultPreSleepTime = 240 | |
557 | const DefaultPreCheckSleepTime = 20 | |
558 | const DefaultPreSleepTime = 220 | |
398 | 559 | |
399 | 560 | // WaitForCluster waits for instance to given status |
400 | 561 | // when instance.NotFound wait until timeout |
402 | 563 | if timeout <= 0 { |
403 | 564 | timeout = ClusterDefaultTimeout |
404 | 565 | } |
566 | ||
567 | // Sleep 20 second to check cluster creating or failed | |
568 | sleep := math.Min(float64(timeout), float64(DefaultPreCheckSleepTime)) | |
569 | time.Sleep(time.Duration(sleep) * time.Second) | |
570 | ||
405 | 571 | cluster, err := client.DescribeCluster(clusterId) |
406 | 572 | if err != nil { |
407 | 573 | return err |
574 | } else if cluster.State == Failed { | |
575 | return fmt.Errorf("Waitting for cluster %s %s failed. Looking the specified reason in the web console.", clusterId, status) | |
408 | 576 | } else if cluster.State == status { |
409 | 577 | //TODO |
410 | 578 | return nil |
411 | 579 | } |
580 | ||
412 | 581 | // Create or Reset cluster usually cost at least 4 min, so there will sleep a long time before polling |
413 | sleep := math.Min(float64(timeout), float64(DefaultPreSleepTime)) | |
582 | sleep = math.Min(float64(timeout), float64(DefaultPreSleepTime)) | |
414 | 583 | time.Sleep(time.Duration(sleep) * time.Second) |
415 | 584 | |
416 | 585 | for { |
41 | 41 | } |
42 | 42 | |
43 | 43 | for _, cluster := range clusters { |
44 | if cluster.ClusterType != "Kubernetes" { | |
44 | if cluster.ClusterType != "Kubernetes" && cluster.ClusterType != "ManagedKubernetes" { | |
45 | 45 | continue |
46 | 46 | } |
47 | 47 | t.Logf("Cluster: %++v", cluster) |
50 | 50 | t.Errorf("Failed to DescribeCluster: %v", err) |
51 | 51 | } |
52 | 52 | t.Logf("Cluster Describe: %++v", c) |
53 | t.Logf("Cluster KeyPair %v", c.Parameters.KeyPair) | |
54 | 53 | |
55 | 54 | if c.MetaData.MultiAZ || c.MetaData.SubClass == "3az" { |
56 | 55 | t.Logf("%v is a MultiAZ kubernetes cluster", c.ClusterID) |
57 | t.Logf("Cluster VSWA ID %v", c.Parameters.VSwitchIdA) | |
58 | t.Logf("Cluster VSWB ID %v", c.Parameters.VSwitchIdB) | |
59 | t.Logf("Cluster VSWC ID %v", c.Parameters.VSwitchIdC) | |
60 | t.Logf("Cluster MasterInstanceTypeA %v", c.Parameters.MasterInstanceTypeA) | |
61 | t.Logf("Cluster MasterInstanceTypeB %v", c.Parameters.MasterInstanceTypeB) | |
62 | t.Logf("Cluster MasterInstanceTypeC %v", c.Parameters.MasterInstanceTypeC) | |
63 | t.Logf("Cluster NumOfNodeA %v", c.Parameters.NumOfNodesA) | |
64 | t.Logf("Cluster NumOfNodeB %v", c.Parameters.NumOfNodesB) | |
65 | t.Logf("Cluster NumOfNodeC %v", c.Parameters.NumOfNodesC) | |
66 | 56 | } else { |
67 | t.Logf("%v is a single kubernetes cluster", c.ClusterID) | |
68 | t.Logf("Cluster VSW ID %v", c.Parameters.VSwitchID) | |
69 | t.Logf("Cluster MasterInstanceType %v", c.Parameters.MasterInstanceType) | |
70 | t.Logf("Cluster NumOfNode %v", c.Parameters.NumOfNodes) | |
57 | if cluster.ClusterType == "ManagedKubernetes" { | |
58 | t.Logf("%v is a Managed kubernetes cluster", c.ClusterID) | |
59 | } else { | |
60 | t.Logf("%v is a SingleAZ kubernetes cluster", c.ClusterID) | |
61 | } | |
71 | 62 | } |
72 | 63 | } |
73 | 64 | } |
95 | 86 | t.Logf("Cluster certs: %++v", certs) |
96 | 87 | |
97 | 88 | } |
89 | } | |
90 | ||
91 | func _TestGetClusterEndpoints(t *testing.T) { | |
92 | client := NewTestClientForDebug() | |
93 | clusterId := "c213c31b97430433c87afe4852b6a08ef" | |
94 | clusterEndpoints, err := client.GetClusterEndpoints(clusterId) | |
95 | if err != nil { | |
96 | t.Fatalf("Failed to GetClusterEndpoints: %v", err) | |
97 | } | |
98 | t.Logf("Succeed getting clusterEndpoints %v", clusterEndpoints) | |
98 | 99 | } |
99 | 100 | |
100 | 101 | func _TestCreateClusters(t *testing.T) { |
154 | 155 | WorkerDataDisk: true, |
155 | 156 | WorkerDataDiskCategory: "cloud_efficiency", |
156 | 157 | WorkerDataDiskSize: 100, |
158 | PublicSLB: true, | |
159 | NodeCIDRMask: "25", | |
160 | LoggingType: "SLS", | |
161 | SLSProjectName: "k8s-test-my-terraform-singleaz", | |
157 | 162 | } |
158 | 163 | cluster, err := client.CreateKubernetesCluster(common.Hangzhou, &args) |
159 | 164 | if err != nil { |
163 | 168 | t.Logf("Cluster: %++v", cluster) |
164 | 169 | } |
165 | 170 | |
166 | func _TestCreateKubernetesMultiAZCluster(t *testing.T) { | |
167 | ||
168 | client := NewTestClientForDebug() | |
169 | ||
170 | args := KubernetesMultiAZCreationArgs{ | |
171 | Name: "multiaz-test1", | |
172 | ClusterType: "Kubernetes", | |
173 | DisableRollback: true, | |
174 | MultiAZ: true, | |
175 | VPCID: "vpc-id", | |
176 | VSwitchIdA: "vsw-id1", | |
177 | VSwitchIdB: "vsw-id2", | |
178 | VSwitchIdC: "vsw-id3", | |
179 | NumOfNodesA: 1, | |
180 | NumOfNodesB: 1, | |
181 | NumOfNodesC: 1, | |
182 | MasterInstanceTypeA: "ecs.sn1ne.large", | |
183 | MasterInstanceTypeB: "ecs.sn1ne.large", | |
184 | MasterInstanceTypeC: "ecs.sn1ne.large", | |
171 | func _TestCreateManagedKubernetesCluster(t *testing.T) { | |
172 | ||
173 | client := NewTestClientForDebug() | |
174 | ||
175 | args := KubernetesCreationArgs{ | |
176 | Name: "single-managed-az-k8s", | |
177 | ClusterType: "ManagedKubernetes", | |
178 | DisableRollback: true, | |
179 | //VPCID: "vpc-id", | |
180 | //VSwitchId: "vsw-id", | |
181 | ZoneId: "cn-hangzhou-g", | |
182 | SNatEntry: true, | |
183 | NumOfNodes: 2, | |
184 | MasterInstanceType: "ecs.sn1ne.large", | |
185 | 185 | MasterSystemDiskCategory: "cloud_efficiency", |
186 | 186 | MasterSystemDiskSize: 40, |
187 | WorkerInstanceTypeA: "ecs.sn1ne.large", | |
188 | WorkerInstanceTypeB: "ecs.sn1ne.large", | |
189 | WorkerInstanceTypeC: "ecs.sn1ne.large", | |
187 | WorkerInstanceType: "ecs.sn1ne.large", | |
190 | 188 | WorkerSystemDiskCategory: "cloud_efficiency", |
191 | 189 | WorkerSystemDiskSize: 40, |
192 | 190 | SSHFlags: true, |
193 | ContainerCIDR: "172.17.0.0/16", | |
194 | ServiceCIDR: "172.20.0.0/20", | |
191 | ContainerCIDR: "172.16.0.0/16", | |
192 | ServiceCIDR: "172.19.0.0/20", | |
195 | 193 | LoginPassword: "test-password123", |
196 | 194 | WorkerDataDisk: true, |
197 | 195 | WorkerDataDiskCategory: "cloud_efficiency", |
198 | 196 | WorkerDataDiskSize: 100, |
197 | PublicSLB: true, | |
198 | NodeCIDRMask: "25", | |
199 | LoggingType: "SLS", | |
200 | SLSProjectName: "k8s-test-my-terraform-singleaz", | |
201 | } | |
202 | cluster, err := client.CreateKubernetesCluster(common.Hangzhou, &args) | |
203 | if err != nil { | |
204 | t.Fatalf("Failed to CreateKubernetesCluster: %v", err) | |
205 | } | |
206 | ||
207 | t.Logf("Cluster: %++v", cluster) | |
208 | } | |
209 | ||
210 | func _TestCreateKubernetesMultiAZCluster(t *testing.T) { | |
211 | ||
212 | client := NewTestClientForDebug() | |
213 | ||
214 | args := KubernetesMultiAZCreationArgs{ | |
215 | Name: "multiaz-test", | |
216 | ClusterType: "Kubernetes", | |
217 | DisableRollback: true, | |
218 | MultiAZ: true, | |
219 | VPCID: "vpc-id", | |
220 | VSwitchIdA: "vsw-id1", | |
221 | VSwitchIdB: "vsw-id2", | |
222 | VSwitchIdC: "vsw-id3", | |
223 | NumOfNodesA: 1, | |
224 | NumOfNodesB: 1, | |
225 | NumOfNodesC: 1, | |
226 | ||
227 | MasterInstanceTypeA: "ecs.ic5.xlarge", | |
228 | MasterInstanceTypeB: "ecs.ic5.xlarge", | |
229 | MasterInstanceTypeC: "ecs.ic5.xlarge", | |
230 | MasterSystemDiskCategory: "cloud_efficiency", | |
231 | MasterSystemDiskSize: 40, | |
232 | ||
233 | MasterInstanceChargeType: "PrePaid", | |
234 | MasterPeriodUnit: "Week", | |
235 | MasterPeriod: 1, | |
236 | MasterAutoRenew: true, | |
237 | MasterAutoRenewPeriod: 1, | |
238 | ||
239 | WorkerInstanceTypeA: "ecs.ic5.xlarge", | |
240 | WorkerInstanceTypeB: "ecs.ic5.xlarge", | |
241 | WorkerInstanceTypeC: "ecs.ic5.xlarge", | |
242 | WorkerSystemDiskCategory: "cloud_efficiency", | |
243 | WorkerSystemDiskSize: 40, | |
244 | ||
245 | WorkerInstanceChargeType: "PrePaid", | |
246 | WorkerPeriodUnit: "Week", | |
247 | WorkerPeriod: 1, | |
248 | WorkerAutoRenew: true, | |
249 | WorkerAutoRenewPeriod: 1, | |
250 | ||
251 | SSHFlags: true, | |
252 | ContainerCIDR: "172.20.0.0/16", | |
253 | ServiceCIDR: "172.21.0.0/20", | |
254 | LoginPassword: "test-password123", | |
255 | ImageId: "centos_7_03_64_20G_alibase_20170818.vhd", | |
256 | KubernetesVersion: "1.11.2", | |
257 | WorkerDataDisk: true, | |
258 | WorkerDataDiskCategory: "cloud_efficiency", | |
259 | WorkerDataDiskSize: 100, | |
260 | NodeCIDRMask: "25", | |
261 | LoggingType: "SLS", | |
262 | SLSProjectName: "k8s-test-my-terraform", | |
199 | 263 | } |
200 | 264 | cluster, err := client.CreateKubernetesMultiAZCluster(common.Hangzhou, &args) |
201 | 265 | if err != nil { |
205 | 269 | t.Logf("Cluster: %++v", cluster) |
206 | 270 | } |
207 | 271 | |
208 | func _TestResizeKubernetesCluster(t *testing.T) { | |
209 | client := NewTestClientForDebug() | |
210 | ||
211 | args := KubernetesClusterResizeArgs{ | |
212 | DisableRollback: true, | |
213 | TimeoutMins: 60, | |
214 | LoginPassword: "test-password123", | |
215 | WorkerInstanceType: "ecs.sn1ne.large", | |
216 | NumOfNodes: 2, | |
217 | } | |
218 | ||
219 | err := client.ResizeKubernetesCluster("c3419330390a94906bcacc55bfa9dd21f", &args) | |
220 | if err != nil { | |
221 | t.Fatalf("Failed to TestResizeKubernetesCluster: %v", err) | |
222 | } | |
223 | } | |
272 | func TestScaleKubernetesCluster(t *testing.T) { | |
273 | // Comment below to test | |
274 | //t.SkipNow() | |
275 | ||
276 | client := NewTestClientForDebug() | |
277 | ||
278 | args := KubernetesClusterScaleArgs{ | |
279 | LoginPassword: "test-password123", | |
280 | WorkerInstanceTypes: []string{"ecs.sn1ne.large"}, | |
281 | WorkerSystemDiskCategory: "cloud_ssd", | |
282 | WorkerSystemDiskSize: int64(40), | |
283 | Count: 2, | |
284 | WorkerDataDisk: true, | |
285 | WorkerDataDiskCategory: "cloud_ssd", | |
286 | WorkerDataDiskSize: int64(200), | |
287 | } | |
288 | ||
289 | err := client.ScaleKubernetesCluster(TestClusterId, &args) | |
290 | if err != nil { | |
291 | t.Fatalf("Failed to TestScaleKubernetesCluster: %v", err) | |
292 | } | |
293 | } | |
294 | ||
295 | func Test_GetKubernetesClusterNodes(t *testing.T) { | |
296 | client := NewTestClientForDebug() | |
297 | ||
298 | resp, _, err := client.GetKubernetesClusterNodes(TestClusterId, common.Pagination{PageNumber: 1, PageSize: 1000}, NodePoolId) | |
299 | if err != nil { | |
300 | t.Errorf("Error %++v", err) | |
301 | } else { | |
302 | t.Logf("response: %++v", resp) | |
303 | } | |
304 | } |
1 | 1 | |
2 | 2 | import ( |
3 | 3 | "os" |
4 | "strconv" | |
4 | 5 | |
5 | 6 | "github.com/denverdino/aliyungo/common" |
6 | 7 | ) |
8 | 9 | //Modify with your Access Key Id and Access Key Secret |
9 | 10 | |
10 | 11 | var ( |
11 | TestAccessKeyId = os.Getenv("AccessKeyId") | |
12 | TestAccessKeySecret = os.Getenv("AccessKeySecret") | |
13 | TestSecurityToken = os.Getenv("SecurityToken") | |
14 | TestRegionID = common.Region(os.Getenv("RegionId")) | |
12 | TestAccessKeyId = os.Getenv("AccessKeyId") | |
13 | TestAccessKeySecret = os.Getenv("AccessKeySecret") | |
14 | TestSecurityToken = os.Getenv("SecurityToken") | |
15 | TestRegionID = common.Region(os.Getenv("RegionId")) | |
16 | TestVpcId = os.Getenv("VpcId") | |
17 | TestVSwitchId = os.Getenv("VSwitchId") | |
18 | TestServiceCIDR = os.Getenv("ServiceCIDR") | |
19 | TestClusterId = os.Getenv("ClusterId") | |
20 | TestPrivateIpAddress, _ = strconv.ParseBool(os.Getenv("PrivateIpAddress")) | |
21 | TestToken = os.Getenv("Token") | |
22 | TestLoggingType = os.Getenv("LoggingType") | |
15 | 23 | ) |
16 | 24 | |
17 | 25 | var testClient *Client |
0 | package cs | |
1 | ||
2 | import ( | |
3 | "testing" | |
4 | ) | |
5 | ||
6 | func Test_ModifyCluster(t *testing.T) { | |
7 | client := NewTestClientForDebug() | |
8 | ||
9 | args := &ModifyClusterArgs{ | |
10 | DeletionProtection: false, | |
11 | MaintenanceWindow: MaintenanceWindow{ | |
12 | Enable: true, | |
13 | MaintenanceTime: "2020-12-02T13:06:50.224Z", | |
14 | Duration: "3h", | |
15 | WeeklyPeriod: "Wednesday", | |
16 | }, | |
17 | } | |
18 | ||
19 | err := client.ModifyCluster(TestClusterId, args) | |
20 | if err != nil { | |
21 | t.Errorf("Error %++v", err) | |
22 | } else { | |
23 | t.Logf("OK") | |
24 | } | |
25 | } | |
26 | ||
27 | func Test_UpgradeCluster(t *testing.T) { | |
28 | client := NewTestClientForDebug() | |
29 | ||
30 | args := &UpgradeClusterArgs{ | |
31 | Version: "1.14.8-aliyun.1", | |
32 | } | |
33 | ||
34 | err := client.UpgradeCluster(TestClusterId, args) | |
35 | if err != nil { | |
36 | t.Errorf("Error %++v", err) | |
37 | } else { | |
38 | t.Logf("OK") | |
39 | } | |
40 | } | |
41 | ||
42 | func Test_CancelUpgradeCluster(t *testing.T) { | |
43 | client := NewTestClientForDebug() | |
44 | ||
45 | err := client.CancelUpgradeCluster(TestClusterId) | |
46 | if err != nil { | |
47 | t.Errorf("Error %++v", err) | |
48 | } else { | |
49 | t.Logf("OK") | |
50 | } | |
51 | } | |
52 | ||
53 | func Test_QueryUpgradeClusterResult(t *testing.T) { | |
54 | client := NewTestClientForDebug() | |
55 | ||
56 | result, err := client.QueryUpgradeClusterResult(TestClusterId) | |
57 | if err != nil { | |
58 | t.Errorf("Error %++v", err) | |
59 | } else { | |
60 | t.Logf("OK, result: %++v", result) | |
61 | } | |
62 | } | |
63 | ||
64 | func Test_CreateDelicatedKubernetesCluster(t *testing.T) { | |
65 | t.SkipNow() | |
66 | client := NewTestClientForDebug() | |
67 | ||
68 | request := &DelicatedKubernetesClusterCreationRequest{} | |
69 | response, err := client.CreateDelicatedKubernetesCluster(request) | |
70 | if err != nil { | |
71 | t.Fatalf("Error %++v", err) | |
72 | } else { | |
73 | t.Logf("Response %++v", response) | |
74 | } | |
75 | } | |
76 | ||
77 | func Test_CreateManagedKubernetesCluster(t *testing.T) { | |
78 | t.SkipNow() | |
79 | client := NewTestClientForDebug() | |
80 | ||
81 | request := &ManagedKubernetesClusterCreationRequest{} | |
82 | ||
83 | response, err := client.CreateManagedKubernetesCluster(request) | |
84 | if err != nil { | |
85 | t.Fatalf("Error %++v", err) | |
86 | } else { | |
87 | t.Logf("Response %++v", response) | |
88 | } | |
89 | } | |
90 | ||
91 | func Test_DescribeKubernetesClusterDetail(t *testing.T) { | |
92 | client := NewTestClientForDebug() | |
93 | ||
94 | cluster, err := client.DescribeKubernetesClusterDetail(TestClusterId) | |
95 | ||
96 | if err != nil { | |
97 | t.Fatalf("Error %++v", err) | |
98 | } else { | |
99 | t.Logf("Response = %++v", cluster) | |
100 | t.Logf("MetaData = %++v", cluster.GetMetaData()) | |
101 | } | |
102 | } | |
103 | ||
104 | func Test_ScaleOutKubernetesCluster(t *testing.T) { | |
105 | client := NewTestClientForDebug() | |
106 | ||
107 | request := &ScaleOutKubernetesClusterRequest{ | |
108 | LoginPassword: "Hello1234", | |
109 | WorkerVSwitchIds: []string{"vsw-xxxx"}, | |
110 | WorkerInstanceTypes: []string{"ecs.n4.xlarge"}, | |
111 | WorkerInstanceChargeType: "PostPaid", | |
112 | WorkerPeriod: 1, | |
113 | WorkerPeriodUnit: "1", | |
114 | WorkerAutoRenew: true, | |
115 | WorkerAutoRenewPeriod: 1, | |
116 | WorkerDataDisk: true, | |
117 | WorkerDataDisks: []DataDisk{ | |
118 | { | |
119 | Category: "cloud_ssd", | |
120 | Size: "200", | |
121 | }, | |
122 | { | |
123 | Category: "cloud_ssd", | |
124 | Size: "300", | |
125 | }, | |
126 | }, | |
127 | Tags: []Tag{ | |
128 | {Key: "k-aaa", | |
129 | Value: "v-aaa", | |
130 | }, | |
131 | }, | |
132 | Count: 2, | |
133 | } | |
134 | ||
135 | response, err := client.ScaleOutKubernetesCluster(TestClusterId, request) | |
136 | if err != nil { | |
137 | t.Fatalf("Error %++v", err) | |
138 | } else { | |
139 | t.Logf("Response %++v", response) | |
140 | } | |
141 | } | |
142 | ||
143 | func Test_DeleteKubernetesClusterNodes(t *testing.T) { | |
144 | client := NewTestClientForDebug() | |
145 | ||
146 | request := &DeleteKubernetesClusterNodesRequest{ | |
147 | ReleaseNode: false, | |
148 | Nodes: []string{"cn-beijing.192.168.0.128"}, | |
149 | } | |
150 | ||
151 | response, err := client.DeleteKubernetesClusterNodes(TestClusterId, request) | |
152 | if err != nil { | |
153 | t.Fatalf("Error %++v", err) | |
154 | } else { | |
155 | t.Logf("Response %++v", response) | |
156 | } | |
157 | } |
0 | package cs | |
1 | ||
2 | import ( | |
3 | "encoding/json" | |
4 | "fmt" | |
5 | "github.com/denverdino/aliyungo/ecs" | |
6 | "net/http" | |
7 | "time" | |
8 | ||
9 | "github.com/denverdino/aliyungo/common" | |
10 | ) | |
11 | ||
12 | type TaskState string | |
13 | ||
14 | const ( | |
15 | // task status | |
16 | Task_Status_Running = "running" | |
17 | Task_Status_Success = "Success" | |
18 | Task_Status_Failed = "Failed" | |
19 | ||
20 | // upgrade state | |
21 | UpgradeStep_NotStart = "not_start" | |
22 | UpgradeStep_Prechecking = "prechecking" | |
23 | UpgradeStep_Upgrading = "upgrading" | |
24 | UpgradeStep_Pause = "pause" | |
25 | UpgradeStep_Success = "success" | |
26 | ) | |
27 | ||
28 | type WeeklyPeriod string | |
29 | type MaintenanceTime string | |
30 | ||
31 | // maintenance window | |
32 | type MaintenanceWindow struct { | |
33 | Enable bool `json:"enable"` | |
34 | MaintenanceTime MaintenanceTime `json:"maintenance_time"` | |
35 | Duration string `json:"duration"` | |
36 | Recurrence string `json:"recurrence,omitempty"` | |
37 | WeeklyPeriod WeeklyPeriod `json:"weekly_period"` | |
38 | } | |
39 | ||
40 | //modify cluster,include DeletionProtection and so on | |
41 | type ModifyClusterArgs struct { | |
42 | DeletionProtection bool `json:"deletion_protection"` | |
43 | ResourceGroupId string `json:"resource_group_id"` | |
44 | MaintenanceWindow MaintenanceWindow `json:"maintenance_window"` | |
45 | } | |
46 | ||
47 | type UpgradeClusterArgs struct { | |
48 | Version string `json:"version"` | |
49 | } | |
50 | ||
51 | type UpgradeClusterResult struct { | |
52 | Status TaskState `json:"status"` | |
53 | PrecheckReportId string `json:"precheck_report_id"` | |
54 | UpgradeStep string `json:"upgrade_step"` | |
55 | ErrorMessage string `json:"error_message"` | |
56 | *UpgradeTask `json:"upgrade_task,omitempty"` | |
57 | } | |
58 | ||
59 | type UpgradeTask struct { | |
60 | FieldRetries int `json:"retries,omitempty"` | |
61 | FieldCreatedAt time.Time `json:"created_at"` | |
62 | FieldMessage string `json:"message,omitempty"` | |
63 | FieldStatus string `json:"status"` // empty|running|success|failed | |
64 | FieldFinishedAt time.Time `json:"finished_at,omitempty"` | |
65 | UpgradeStatus UpgradeStatus `json:"upgrade_status"` | |
66 | } | |
67 | ||
68 | type UpgradeStatus struct { | |
69 | State string `json:"state"` | |
70 | Phase string `json:"phase"` // {Master1, Master2, Master3, Nodes} | |
71 | Total int `json:"total"` | |
72 | Succeeded int `json:"succeeded"` | |
73 | Failed string `json:"failed"` | |
74 | Events []Event `json:"events"` | |
75 | IsCanceled bool `json:"is_canceled"` | |
76 | } | |
77 | ||
78 | type Event struct { | |
79 | Timestamp time.Time | |
80 | Type string | |
81 | Reason string | |
82 | Message string | |
83 | Source string | |
84 | } | |
85 | ||
86 | //modify cluster | |
87 | func (client *Client) ModifyCluster(clusterId string, args *ModifyClusterArgs) error { | |
88 | return client.Invoke("", http.MethodPut, "/api/v2/clusters/"+clusterId, nil, args, nil) | |
89 | } | |
90 | ||
91 | //upgrade cluster | |
92 | func (client *Client) UpgradeCluster(clusterId string, args *UpgradeClusterArgs) error { | |
93 | return client.Invoke("", http.MethodPost, fmt.Sprintf("/api/v2/clusters/%s/upgrade", clusterId), nil, args, nil) | |
94 | } | |
95 | ||
96 | //cancel upgrade cluster | |
97 | func (client *Client) CancelUpgradeCluster(clusterId string) error { | |
98 | return client.Invoke("", http.MethodPost, fmt.Sprintf("/api/v2/clusters/%s/upgrade/cancel", clusterId), nil, nil, nil) | |
99 | } | |
100 | ||
101 | func (client *Client) QueryUpgradeClusterResult(clusterId string) (*UpgradeClusterResult, error) { | |
102 | cluster := &UpgradeClusterResult{} | |
103 | err := client.Invoke("", http.MethodGet, fmt.Sprintf("/api/v2/clusters/%s/upgrade/status", clusterId), nil, nil, cluster) | |
104 | if err != nil { | |
105 | return nil, err | |
106 | } | |
107 | return cluster, nil | |
108 | } | |
109 | ||
110 | //Cluster Info | |
111 | type KubernetesClusterType string | |
112 | ||
113 | var ( | |
114 | DelicatedKubernetes = KubernetesClusterType("Kubernetes") | |
115 | ManagedKubernetes = KubernetesClusterType("ManagedKubernetes") | |
116 | ) | |
117 | ||
118 | type KubernetesClusterProfile string | |
119 | ||
120 | var ( | |
121 | Profile4Serverless = KubernetesClusterProfile("Serverless") | |
122 | ) | |
123 | ||
124 | type ProxyMode string | |
125 | ||
126 | var ( | |
127 | IPTables = "iptables" | |
128 | IPVS = "ipvs" | |
129 | ) | |
130 | ||
131 | type Effect string | |
132 | ||
133 | var ( | |
134 | TaintNoExecute = "NoExecute" | |
135 | TaintNoSchedule = "NoSchedule" | |
136 | TaintPreferNoSchedule = "PreferNoSchedule" | |
137 | ) | |
138 | ||
139 | type ClusterArgs struct { | |
140 | DisableRollback bool `json:"disable_rollback"` | |
141 | TimeoutMins int `json:"timeout_mins"` | |
142 | ||
143 | Name string `json:"name"` | |
144 | ClusterType KubernetesClusterType `json:"cluster_type"` | |
145 | Profile string `json:"profile"` | |
146 | KubernetesVersion string `json:"kubernetes_version"` | |
147 | DeletionProtection bool `json:"deletion_protection"` | |
148 | ||
149 | NodeCidrMask string `json:"node_cidr_mask"` | |
150 | UserCa string `json:"user_ca"` | |
151 | ||
152 | OsType string `json:"os_type"` | |
153 | Platform string `json:"platform"` | |
154 | ||
155 | UserData string `json:"user_data"` | |
156 | ||
157 | NodePortRange string `json:"node_port_range"` | |
158 | NodeNameMode string `json:"node_name_mode"` | |
159 | ||
160 | //ImageId | |
161 | ImageId string `json:"image_id"` | |
162 | ||
163 | PodVswitchIds []string `json:"pod_vswitch_ids"` // eni多网卡模式下,需要传额外的vswitchid给addon | |
164 | ||
165 | LoginPassword string `json:"login_password"` //和KeyPair 二选一 | |
166 | KeyPair string `json:"key_pair"` ////LoginPassword 二选一 | |
167 | ||
168 | RegionId common.Region `json:"region_id"` | |
169 | VpcId string `json:"vpcid"` | |
170 | ContainerCidr string `json:"container_cidr"` | |
171 | ServiceCidr string `json:"service_cidr"` | |
172 | ||
173 | CloudMonitorFlags bool `json:"cloud_monitor_flags"` | |
174 | ||
175 | SecurityGroupId string `json:"security_group_id"` | |
176 | IsEnterpriseSecurityGroup bool `json:"is_enterprise_security_group"` | |
177 | EndpointPublicAccess bool `json:"endpoint_public_access"` | |
178 | LoadBalancerSpec string `json:"load_balancer_spec"` //api server slb实例规格 | |
179 | ProxyMode ProxyMode `json:"proxy_mode"` | |
180 | SnatEntry bool `json:"snat_entry"` | |
181 | ResourceGroupId string `json:"resource_group_id"` | |
182 | ||
183 | Addons []Addon `json:"addons"` | |
184 | Tags []Tag `json:"tags"` | |
185 | ||
186 | Taints []Taint `json:"taints"` | |
187 | ||
188 | ApiAudiences string `json:"api_audiences,omitempty"` | |
189 | ServiceAccountIssuer string `json:"service_account_issuer,omitempty"` | |
190 | CustomSAN string `json:"custom_san,omitempty"` | |
191 | ClusterSpec string `json:"cluster_spec"` | |
192 | Timezone string `json:"timezone"` | |
193 | ClusterDomain string `json:"cluster_domain"` | |
194 | RdsInstances []string `json:"rds_instances"` | |
195 | EncryptionProviderKey string `json:"encryption_provider_key"` | |
196 | MaintenanceWindow MaintenanceWindow `json:"maintenance_window"` | |
197 | ||
198 | //controlplane log parms | |
199 | ControlplaneLogProject string `json:"controlplane_log_project"` | |
200 | ControlplaneLogTTL string `json:"controlplane_log_ttl"` | |
201 | ControlplaneComponents []string `json:"controlplane_log_components"` | |
202 | ||
203 | // Operating system hardening | |
204 | SocEnabled *bool `json:"soc_enabled"` | |
205 | CisEnabled *bool `json:"cis_enabled"` | |
206 | } | |
207 | ||
208 | //addon | |
209 | type Addon struct { | |
210 | Name string `json:"name"` | |
211 | Version string `json:"version"` | |
212 | Config string `json:"config"` | |
213 | Disabled bool `json:"disabled"` // 是否禁止默认安装 | |
214 | } | |
215 | ||
216 | //taint | |
217 | type Taint struct { | |
218 | Key string `json:"key"` | |
219 | Value string `json:"value"` | |
220 | Effect Effect `json:"effect"` | |
221 | } | |
222 | ||
223 | type Label struct { | |
224 | Key string `json:"key"` | |
225 | Value string `json:"value"` | |
226 | } | |
227 | ||
228 | type MasterArgs struct { | |
229 | MasterCount int `json:"master_count"` | |
230 | MasterVSwitchIds []string `json:"master_vswitch_ids"` | |
231 | MasterInstanceTypes []string `json:"master_instance_types"` | |
232 | ||
233 | MasterInstanceChargeType string `json:"master_instance_charge_type"` | |
234 | MasterPeriod int `json:"master_period"` | |
235 | MasterPeriodUnit string `json:"master_period_unit"` | |
236 | ||
237 | MasterAutoRenew bool `json:"master_auto_renew"` | |
238 | MasterAutoRenewPeriod int `json:"master_auto_renew_period"` | |
239 | ||
240 | MasterSystemDiskCategory ecs.DiskCategory `json:"master_system_disk_category"` | |
241 | MasterSystemDiskSize int64 `json:"master_system_disk_size"` | |
242 | MasterSystemDiskPerformanceLevel string `json:"master_system_disk_performance_level"` | |
243 | ||
244 | MasterDataDisks []DataDisk `json:"master_data_disks"` //支持多个数据盘 | |
245 | ||
246 | //support hpc/scc | |
247 | MasterHpcClusterId string `json:"master_hpc_cluster_id"` | |
248 | MasterDeploymentSetId string `json:"master_deploymentset_id"` | |
249 | ||
250 | //master node deletion protection | |
251 | MasterDeletionProtection *bool `json:"master_deletion_protection"` | |
252 | ||
253 | // disk snapshot policy | |
254 | MasterSnapshotPolicyId string `json:"master_system_disk_snapshot_policy_id"` | |
255 | } | |
256 | ||
257 | type WorkerArgs struct { | |
258 | WorkerVSwitchIds []string `json:"worker_vswitch_ids"` | |
259 | WorkerInstanceTypes []string `json:"worker_instance_types"` | |
260 | ||
261 | NumOfNodes int64 `json:"num_of_nodes"` | |
262 | ||
263 | WorkerInstanceChargeType string `json:"worker_instance_charge_type"` | |
264 | WorkerPeriod int `json:"worker_period"` | |
265 | WorkerPeriodUnit string `json:"worker_period_unit"` | |
266 | ||
267 | WorkerAutoRenew bool `json:"worker_auto_renew"` | |
268 | WorkerAutoRenewPeriod int `json:"worker_auto_renew_period"` | |
269 | ||
270 | WorkerSystemDiskCategory ecs.DiskCategory `json:"worker_system_disk_category"` | |
271 | WorkerSystemDiskSize int64 `json:"worker_system_disk_size"` | |
272 | WorkerSystemDiskPerformanceLevel string `json:"worker_system_disk_performance_level"` | |
273 | ||
274 | WorkerDataDisk bool `json:"worker_data_disk"` | |
275 | WorkerDataDisks []DataDisk `json:"worker_data_disks"` //支持多个数据盘 | |
276 | ||
277 | WorkerHpcClusterId string `json:"worker_hpc_cluster_id"` | |
278 | WorkerDeploymentSetId string `json:"worker_deploymentset_id"` | |
279 | ||
280 | //worker node deletion protection | |
281 | WorkerDeletionProtection *bool `json:"worker_deletion_protection"` | |
282 | ||
283 | //Runtime only for worker nodes | |
284 | Runtime Runtime `json:"runtime"` | |
285 | ||
286 | // disk snapshot policy | |
287 | WorkerSnapshotPolicyId string `json:"worker_system_disk_snapshot_policy_id"` | |
288 | } | |
289 | ||
290 | type ScaleOutKubernetesClusterRequest struct { | |
291 | LoginPassword string `json:"login_password"` //和KeyPair 二选一 | |
292 | KeyPair string `json:"key_pair"` ////LoginPassword 二选一 | |
293 | ||
294 | WorkerVSwitchIds []string `json:"worker_vswitch_ids"` | |
295 | WorkerInstanceTypes []string `json:"worker_instance_types"` | |
296 | ||
297 | WorkerInstanceChargeType string `json:"worker_instance_charge_type"` | |
298 | WorkerPeriod int `json:"worker_period"` | |
299 | WorkerPeriodUnit string `json:"worker_period_unit"` | |
300 | ||
301 | WorkerAutoRenew bool `json:"worker_auto_renew"` | |
302 | WorkerAutoRenewPeriod int `json:"worker_auto_renew_period"` | |
303 | ||
304 | WorkerSystemDiskCategory ecs.DiskCategory `json:"worker_system_disk_category"` | |
305 | WorkerSystemDiskSize int64 `json:"worker_system_disk_size"` | |
306 | WorkerSnapshotPolicyId string `json:"worker_system_disk_snapshot_policy_id"` | |
307 | WorkerSystemDiskPerformanceLevel string `json:"worker_system_disk_performance_level"` | |
308 | ||
309 | WorkerDataDisk bool `json:"worker_data_disk"` | |
310 | WorkerDataDisks []DataDisk `json:"worker_data_disks"` //支持多个数据盘 | |
311 | ||
312 | Tags []Tag `json:"tags"` | |
313 | Taints []Taint `json:"taints"` | |
314 | ImageId string `json:"image_id"` | |
315 | ||
316 | UserData string `json:"user_data"` | |
317 | ||
318 | Count int64 `json:"count"` | |
319 | CpuPolicy string `json:"cpu_policy"` | |
320 | Runtime Runtime `json:"runtime"` | |
321 | CloudMonitorFlags bool `json:"cloud_monitor_flags"` | |
322 | RdsInstances []string ` json:"rds_instances"` | |
323 | } | |
324 | ||
325 | //datadiks | |
326 | type DataDisk struct { | |
327 | Category string `json:"category"` | |
328 | KMSKeyId string `json:"kms_key_id"` | |
329 | Encrypted string `json:"encrypted"` // true|false | |
330 | Device string `json:"device"` // could be /dev/xvd[a-z]. If not specification, will use default value. | |
331 | Size string `json:"size"` | |
332 | DiskName string `json:"name"` | |
333 | AutoSnapshotPolicyId string `json:"auto_snapshot_policy_id"` | |
334 | PerformanceLevel string `json:"performance_Level"` | |
335 | } | |
336 | ||
337 | type NodePoolDataDisk struct { | |
338 | Category string `json:"category"` | |
339 | KMSKeyId string `json:"kms_key_id"` | |
340 | Encrypted string `json:"encrypted"` // true|false | |
341 | Device string `json:"device"` // could be /dev/xvd[a-z]. If not specification, will use default value. | |
342 | Size int `json:"size"` | |
343 | DiskName string `json:"name"` | |
344 | AutoSnapshotPolicyId string `json:"auto_snapshot_policy_id"` | |
345 | PerformanceLevel string `json:"performance_Level"` | |
346 | } | |
347 | ||
348 | //runtime | |
349 | type Runtime struct { | |
350 | Name string `json:"name"` | |
351 | Version string `json:"version"` | |
352 | RuntimeClass []string `json:"runtimeClass,omitempty"` | |
353 | Exist bool `json:"exist"` | |
354 | AvailableNetworkComponents []string `json:"availableNetworkComponents,omitempty"` | |
355 | } | |
356 | ||
357 | //DelicatedKubernetes | |
358 | type DelicatedKubernetesClusterCreationRequest struct { | |
359 | ClusterArgs | |
360 | MasterArgs | |
361 | WorkerArgs | |
362 | } | |
363 | ||
364 | //ManagedKubernetes | |
365 | type ManagedKubernetesClusterCreationRequest struct { | |
366 | ClusterArgs | |
367 | WorkerArgs | |
368 | } | |
369 | ||
370 | //Validate | |
371 | ||
372 | //Create DelicatedKubernetes Cluster | |
373 | func (client *Client) CreateDelicatedKubernetesCluster(request *DelicatedKubernetesClusterCreationRequest) (*ClusterCommonResponse, error) { | |
374 | response := &ClusterCommonResponse{} | |
375 | path := "/clusters" | |
376 | if request.ResourceGroupId != "" { | |
377 | // 创建集群到指定资源组 | |
378 | path = fmt.Sprintf("/resource_groups/%s/clusters", request.ResourceGroupId) | |
379 | } | |
380 | err := client.Invoke(request.RegionId, http.MethodPost, path, nil, request, response) | |
381 | if err != nil { | |
382 | return nil, err | |
383 | } | |
384 | ||
385 | return response, nil | |
386 | } | |
387 | ||
388 | //Create ManagedKubernetes Cluster | |
389 | func (client *Client) CreateManagedKubernetesCluster(request *ManagedKubernetesClusterCreationRequest) (*ClusterCommonResponse, error) { | |
390 | response := &ClusterCommonResponse{} | |
391 | path := "/clusters" | |
392 | if request.ResourceGroupId != "" { | |
393 | // 创建集群到指定资源组 | |
394 | path = fmt.Sprintf("/resource_groups/%s/clusters", request.ResourceGroupId) | |
395 | } | |
396 | err := client.Invoke(request.RegionId, http.MethodPost, path, nil, request, response) | |
397 | if err != nil { | |
398 | return nil, err | |
399 | } | |
400 | ||
401 | return response, nil | |
402 | } | |
403 | ||
404 | //ScaleKubernetesCluster | |
405 | func (client *Client) ScaleOutKubernetesCluster(clusterId string, request *ScaleOutKubernetesClusterRequest) (*ClusterCommonResponse, error) { | |
406 | response := &ClusterCommonResponse{} | |
407 | err := client.Invoke("", http.MethodPost, fmt.Sprintf("/api/v2/clusters/%s", clusterId), nil, request, response) | |
408 | if err != nil { | |
409 | return nil, err | |
410 | } | |
411 | ||
412 | return response, nil | |
413 | } | |
414 | ||
415 | //DeleteClusterNodes | |
416 | type DeleteKubernetesClusterNodesRequest struct { | |
417 | ReleaseNode bool `json:"release_node"` //if set to true, the ecs instance will be released | |
418 | Nodes []string `json:"nodes"` //the format is regionId.instanceId|Ip ,for example cn-hangzhou.192.168.1.2 or cn-hangzhou.i-abc | |
419 | DrainNode bool `json:"drain_node"` //same as Nodes | |
420 | } | |
421 | ||
422 | //DeleteClusterNodes | |
423 | func (client *Client) DeleteKubernetesClusterNodes(clusterId string, request *DeleteKubernetesClusterNodesRequest) (*common.Response, error) { | |
424 | response := &common.Response{} | |
425 | err := client.Invoke("", http.MethodPost, fmt.Sprintf("/api/v2/clusters/%s/nodes/remove", clusterId), nil, request, response) | |
426 | if err != nil { | |
427 | return nil, err | |
428 | } | |
429 | ||
430 | return response, nil | |
431 | } | |
432 | ||
433 | //Cluster definition | |
434 | type KubernetesClusterDetail struct { | |
435 | RegionId common.Region `json:"region_id"` | |
436 | ||
437 | Name string `json:"name"` | |
438 | ClusterId string `json:"cluster_id"` | |
439 | Size int64 `json:"size"` | |
440 | ClusterType KubernetesClusterType `json:"cluster_type"` | |
441 | Profile string `json:"profile"` | |
442 | ||
443 | VpcId string `json:"vpc_id"` | |
444 | VSwitchIds string `json:"vswitch_id"` | |
445 | SecurityGroupId string `json:"security_group_id"` | |
446 | IngressLoadbalancerId string `json:"external_loadbalancer_id"` | |
447 | ResourceGroupId string `json:"resource_group_id"` | |
448 | NetworkMode string `json:"network_mode"` | |
449 | ContainerCIDR string `json:"subnet_cidr"` | |
450 | ||
451 | Tags []Tag `json:"tags"` | |
452 | State string `json:"state"` | |
453 | ||
454 | InitVersion string `json:"init_version"` | |
455 | CurrentVersion string `json:"current_version"` | |
456 | PrivateZone bool `json:"private_zone"` | |
457 | DeletionProtection bool `json:"deletion_protection"` | |
458 | MetaData string `json:"meta_data"` | |
459 | ||
460 | Created time.Time `json:"created"` | |
461 | Updated time.Time `json:"updated"` | |
462 | ||
463 | WorkerRamRoleName string `json:"worker_ram_role_name"` | |
464 | ClusterSpec string `json:"cluster_spec"` | |
465 | OSType string `json:"os_type"` | |
466 | MasterURL string `json:"master_url"` | |
467 | MaintenanceWindow MaintenanceWindow `json:"maintenance_window"` | |
468 | } | |
469 | ||
470 | //GetMetaData | |
471 | func (c *KubernetesClusterDetail) GetMetaData() map[string]interface{} { | |
472 | m := make(map[string]interface{}) | |
473 | _ = json.Unmarshal([]byte(c.MetaData), &m) | |
474 | return m | |
475 | } | |
476 | ||
477 | //查询集群详情 | |
478 | func (client *Client) DescribeKubernetesClusterDetail(clusterId string) (*KubernetesClusterDetail, error) { | |
479 | cluster := &KubernetesClusterDetail{} | |
480 | err := client.Invoke("", http.MethodGet, "/clusters/"+clusterId, nil, nil, cluster) | |
481 | if err != nil { | |
482 | return nil, err | |
483 | } | |
484 | return cluster, nil | |
485 | } | |
486 | ||
487 | //DeleteKubernetesCluster | |
488 | func (client *Client) DeleteKubernetesCluster(clusterId string) error { | |
489 | return client.Invoke("", http.MethodDelete, "/clusters/"+clusterId, nil, nil, nil) | |
490 | } |
0 | package cs | |
1 | ||
2 | import ( | |
3 | "fmt" | |
4 | "github.com/denverdino/aliyungo/common" | |
5 | "github.com/denverdino/aliyungo/ecs" | |
6 | "net/http" | |
7 | "time" | |
8 | ) | |
9 | ||
10 | type SpotPrice struct { | |
11 | InstanceType string `json:"instance_type"` | |
12 | PriceLimit string `json:"price_limit"` | |
13 | } | |
14 | ||
15 | type NodePoolInfo struct { | |
16 | NodePoolId string `json:"nodepool_id"` | |
17 | RegionId common.Region `json:"region_id"` | |
18 | Name string `json:"name"` | |
19 | Created time.Time `json:"created"` | |
20 | Updated time.Time `json:"updated"` | |
21 | IsDefault bool `json:"is_default"` | |
22 | NodePoolType string `json:"type"` | |
23 | ResourceGroupId string `json:"resource_group_id"` | |
24 | } | |
25 | ||
26 | type ScalingGroup struct { | |
27 | VpcId string `json:"vpc_id"` | |
28 | VswitchIds []string `json:"vswitch_ids"` | |
29 | InstanceTypes []string `json:"instance_types"` | |
30 | LoginPassword string `json:"login_password"` | |
31 | KeyPair string `json:"key_pair"` | |
32 | SecurityGroupId string `json:"security_group_id"` | |
33 | SecurityGroupIds []string `json:"security_group_ids"` | |
34 | SystemDiskCategory ecs.DiskCategory `json:"system_disk_category"` | |
35 | SystemDiskSize int64 `json:"system_disk_size"` | |
36 | SystemDiskPerformanceLevel string `json:"system_disk_performance_level"` | |
37 | SystemDiskEncryptAlgorithm string `json:"system_disk_encrypt_algorithm"` | |
38 | SystemDiskEncrypted bool `json:"system_disk_encrypted"` | |
39 | SystemDiskKMSKeyId string `json:"system_disk_kms_key_id"` | |
40 | DataDisks []NodePoolDataDisk `json:"data_disks"` //支持多个数据盘 | |
41 | Tags []Tag `json:"tags"` | |
42 | ImageId string `json:"image_id"` | |
43 | Platform string `json:"platform"` | |
44 | OSType string `json:"os_type"` | |
45 | ImageType string `json:"image_type"` | |
46 | InstanceChargeType string `json:"instance_charge_type"` | |
47 | Period int `json:"period"` | |
48 | PeriodUnit string `json:"period_unit"` | |
49 | AutoRenew bool `json:"auto_renew"` | |
50 | AutoRenewPeriod int `json:"auto_renew_period"` | |
51 | // spot实例 | |
52 | SpotStrategy string `json:"spot_strategy"` | |
53 | SpotPriceLimit []SpotPrice `json:"spot_price_limit"` | |
54 | ||
55 | RdsInstances []string `json:"rds_instances"` | |
56 | ScalingPolicy string `json:"scaling_policy"` | |
57 | ScalingGroupId string `json:"scaling_group_id"` | |
58 | ||
59 | WorkerSnapshotPolicyId string `json:"worker_system_disk_snapshot_policy_id"` | |
60 | // 公网ip | |
61 | InternetChargeType string `json:"internet_charge_type"` | |
62 | InternetMaxBandwidthOut int `json:"internet_max_bandwidth_out"` | |
63 | // Operating system hardening | |
64 | SocEnabled *bool `json:"soc_enabled"` | |
65 | CisEnabled *bool `json:"cis_enabled"` | |
66 | // ipv6 | |
67 | SupportIPv6 bool `json:"support_ipv6"` | |
68 | // deploymentset | |
69 | DeploymentSetId string `json:"deploymentset_id"` | |
70 | DesiredSize *int64 `json:"desired_size,omitempty"` | |
71 | } | |
72 | ||
73 | type AutoScaling struct { | |
74 | Enable bool `json:"enable"` | |
75 | MaxInstances int64 `json:"max_instances"` | |
76 | MinInstances int64 `json:"min_instances"` | |
77 | Type string `json:"type"` | |
78 | // eip | |
79 | IsBindEip *bool `json:"is_bond_eip"` | |
80 | // value: PayByBandwidth / PayByTraffic | |
81 | EipInternetChargeType string `json:"eip_internet_charge_type"` | |
82 | // default 5 | |
83 | EipBandWidth int64 `json:"eip_bandwidth"` | |
84 | } | |
85 | ||
86 | type KubernetesConfig struct { | |
87 | NodeNameMode string `json:"node_name_mode"` | |
88 | Taints []Taint `json:"taints"` | |
89 | Labels []Label `json:"labels"` | |
90 | CpuPolicy string `json:"cpu_policy"` | |
91 | UserData string `json:"user_data"` | |
92 | ||
93 | Runtime string `json:"runtime,omitempty"` | |
94 | RuntimeVersion string `json:"runtime_version"` | |
95 | CmsEnabled bool `json:"cms_enabled"` | |
96 | OverwriteHostname bool `json:"overwrite_hostname"` | |
97 | Unschedulable bool `json:"unschedulable"` | |
98 | } | |
99 | ||
100 | // 加密计算节点池 | |
101 | type TEEConfig struct { | |
102 | TEEType string `json:"tee_type"` | |
103 | TEEEnable bool `json:"tee_enable"` | |
104 | } | |
105 | ||
106 | // 托管节点池配置 | |
107 | type Management struct { | |
108 | Enable bool `json:"enable"` | |
109 | AutoRepair bool `json:"auto_repair"` | |
110 | UpgradeConf UpgradeConf `json:"upgrade_config"` | |
111 | } | |
112 | ||
113 | type UpgradeConf struct { | |
114 | AutoUpgrade bool `json:"auto_upgrade"` | |
115 | Surge int64 `json:"surge"` | |
116 | SurgePercentage int64 `json:"surge_percentage,omitempty"` | |
117 | MaxUnavailable int64 `json:"max_unavailable"` | |
118 | KeepSurgeOnFailed bool `json:"keep_surge_on_failed"` | |
119 | } | |
120 | ||
121 | type CreateNodePoolRequest struct { | |
122 | RegionId common.Region `json:"region_id"` | |
123 | Count int64 `json:"count"` | |
124 | NodePoolInfo `json:"nodepool_info"` | |
125 | ScalingGroup `json:"scaling_group"` | |
126 | KubernetesConfig `json:"kubernetes_config"` | |
127 | AutoScaling `json:"auto_scaling"` | |
128 | TEEConfig `json:"tee_config"` | |
129 | Management `json:"management"` | |
130 | } | |
131 | ||
132 | type BasicNodePool struct { | |
133 | NodePoolInfo `json:"nodepool_info"` | |
134 | NodePoolStatus `json:"status"` | |
135 | } | |
136 | ||
137 | type NodePoolStatus struct { | |
138 | TotalNodes int `json:"total_nodes"` | |
139 | OfflineNodes int `json:"offline_nodes"` | |
140 | ServingNodes int `json:"serving_nodes"` | |
141 | //DesiredNodes int `json:"desired_nodes"` | |
142 | RemovingNodes int `json:"removing_nodes"` | |
143 | FailedNodes int `json:"failed_nodes"` | |
144 | InitialNodes int `json:"initial_nodes"` | |
145 | HealthyNodes int `json:"healthy_nodes"` | |
146 | State string `json:"state"` | |
147 | } | |
148 | ||
149 | type NodePoolDetail struct { | |
150 | BasicNodePool | |
151 | KubernetesConfig `json:"kubernetes_config"` | |
152 | ScalingGroup `json:"scaling_group"` | |
153 | AutoScaling `json:"auto_scaling"` | |
154 | TEEConfig `json:"tee_config"` | |
155 | Management `json:"management"` | |
156 | } | |
157 | ||
158 | type CreateNodePoolResponse struct { | |
159 | Response | |
160 | NodePoolID string `json:"nodepool_id"` | |
161 | Message string `json:"Message"` | |
162 | TaskID string `json:"task_id"` | |
163 | } | |
164 | ||
165 | type UpdateNodePoolRequest struct { | |
166 | RegionId common.Region `json:"region_id"` | |
167 | Count int64 `json:"count"` | |
168 | NodePoolInfo `json:"nodepool_info"` | |
169 | ScalingGroup `json:"scaling_group"` | |
170 | KubernetesConfig `json:"kubernetes_config"` | |
171 | AutoScaling `json:"auto_scaling"` | |
172 | Management `json:"management"` | |
173 | } | |
174 | ||
175 | type NodePoolsDetail struct { | |
176 | Response | |
177 | NodePools []NodePoolDetail `json:"nodepools"` | |
178 | } | |
179 | ||
180 | func (client *Client) CreateNodePool(request *CreateNodePoolRequest, clusterId string) (*CreateNodePoolResponse, error) { | |
181 | response := &CreateNodePoolResponse{} | |
182 | err := client.Invoke(request.RegionId, http.MethodPost, fmt.Sprintf("/clusters/%s/nodepools", clusterId), nil, request, response) | |
183 | if err != nil { | |
184 | return nil, err | |
185 | } | |
186 | ||
187 | return response, nil | |
188 | } | |
189 | ||
190 | func (client *Client) DescribeNodePoolDetail(clusterId, nodePoolId string) (*NodePoolDetail, error) { | |
191 | nodePool := &NodePoolDetail{} | |
192 | err := client.Invoke("", http.MethodGet, fmt.Sprintf("/clusters/%s/nodepools/%s", clusterId, nodePoolId), nil, nil, nodePool) | |
193 | if err != nil { | |
194 | return nil, err | |
195 | } | |
196 | return nodePool, nil | |
197 | } | |
198 | ||
199 | func (client *Client) DescribeClusterNodePools(clusterId string) (*[]NodePoolDetail, error) { | |
200 | nodePools := &NodePoolsDetail{} | |
201 | err := client.Invoke("", http.MethodGet, fmt.Sprintf("/clusters/%s/nodepools", clusterId), nil, nil, nodePools) | |
202 | if err != nil { | |
203 | return nil, err | |
204 | } | |
205 | return &nodePools.NodePools, nil | |
206 | } | |
207 | ||
208 | func (client *Client) UpdateNodePool(clusterId string, nodePoolId string, request *UpdateNodePoolRequest) (*Response, error) { | |
209 | response := &Response{} | |
210 | err := client.Invoke(request.RegionId, http.MethodPut, fmt.Sprintf("/clusters/%s/nodepools/%s", clusterId, nodePoolId), nil, request, response) | |
211 | if err != nil { | |
212 | return nil, err | |
213 | } | |
214 | ||
215 | return response, nil | |
216 | } | |
217 | ||
218 | func (client *Client) DeleteNodePool(clusterId, nodePoolId string) error { | |
219 | return client.Invoke("", http.MethodDelete, fmt.Sprintf("/clusters/%s/nodepools/%s", clusterId, nodePoolId), nil, nil, nil) | |
220 | } |
0 | package cs | |
1 | ||
2 | import ( | |
3 | "os" | |
4 | "strings" | |
5 | "testing" | |
6 | ) | |
7 | ||
8 | var ( | |
9 | VpcId = os.Getenv("VpcId") | |
10 | VswitchIds = os.Getenv("VswitchIds") | |
11 | LoginPassword = os.Getenv("LoginPassword") | |
12 | NodePoolId = os.Getenv("NodePoolId") | |
13 | ) | |
14 | ||
15 | func Test_CreateNodePool(t *testing.T) { | |
16 | client := NewTestClientForDebug() | |
17 | ||
18 | args := &CreateNodePoolRequest{ | |
19 | Count: 1, | |
20 | RegionId: TestRegionID, | |
21 | NodePoolInfo: NodePoolInfo{ | |
22 | Name: "test-npl", | |
23 | NodePoolType: "ess", | |
24 | }, | |
25 | ScalingGroup: ScalingGroup{ | |
26 | VpcId: VpcId, | |
27 | VswitchIds: strings.Split(VswitchIds, ","), | |
28 | InstanceTypes: []string{"ecs.n6.large"}, | |
29 | LoginPassword: LoginPassword, | |
30 | SystemDiskCategory: "cloud_efficiency", | |
31 | SystemDiskSize: 120, | |
32 | DataDisks: []NodePoolDataDisk{{Size: 100, Category: "cloud_ssd"}}, | |
33 | }, | |
34 | KubernetesConfig: KubernetesConfig{ | |
35 | NodeNameMode: "customized,aliyun.com,5,test", | |
36 | }, | |
37 | } | |
38 | ||
39 | resp, err := client.CreateNodePool(args, TestClusterId) | |
40 | if err != nil { | |
41 | t.Errorf("Error %++v", err) | |
42 | } else { | |
43 | t.Logf("response: %++v", resp) | |
44 | } | |
45 | } | |
46 | ||
47 | func Test_DescribeNodePoolDetail(t *testing.T) { | |
48 | client := NewTestClientForDebug() | |
49 | ||
50 | resp, err := client.DescribeNodePoolDetail(TestClusterId, NodePoolId) | |
51 | if err != nil { | |
52 | t.Errorf("Error %++v", err) | |
53 | } else { | |
54 | t.Logf("response: %++v", resp) | |
55 | } | |
56 | } | |
57 | ||
58 | func Test_UpdateNodePool(t *testing.T) { | |
59 | client := NewTestClientForDebug() | |
60 | ||
61 | args := &UpdateNodePoolRequest{ | |
62 | Count: 2, | |
63 | RegionId: TestRegionID, | |
64 | ScalingGroup: ScalingGroup{ | |
65 | InstanceTypes: []string{"ecs.n4.large"}, | |
66 | }, | |
67 | } | |
68 | ||
69 | resp, err := client.UpdateNodePool(TestClusterId, NodePoolId, args) | |
70 | if err != nil { | |
71 | t.Errorf("Error %++v", err) | |
72 | } else { | |
73 | t.Logf("response: %++v", resp) | |
74 | } | |
75 | } | |
76 | ||
77 | func Test_DeleteNodePool(t *testing.T) { | |
78 | client := NewTestClientForDebug() | |
79 | ||
80 | err := client.DeleteNodePool(TestClusterId, NodePoolId) | |
81 | if err != nil { | |
82 | t.Errorf("Error %++v", err) | |
83 | } else { | |
84 | t.Logf("success") | |
85 | } | |
86 | } | |
87 | ||
88 | func Test_DescribeClusterNodePools(t *testing.T) { | |
89 | client := NewTestClientForDebug() | |
90 | ||
91 | resp, err := client.DescribeClusterNodePools(TestClusterId) | |
92 | if err != nil { | |
93 | t.Errorf("Error %++v", err) | |
94 | } else { | |
95 | t.Logf("response: %++v", resp) | |
96 | } | |
97 | } |
66 | 66 | client.userAgent = userAgent |
67 | 67 | } |
68 | 68 | |
69 | // SetTransport sets transport to the http client | |
70 | func (client *ProjectClient) SetTransport(transport http.RoundTripper) { | |
71 | if client.httpClient == nil { | |
72 | client.httpClient = &http.Client{} | |
73 | } | |
74 | client.httpClient.Transport = transport | |
75 | } | |
76 | ||
69 | 77 | func (client *ProjectClient) ClusterId() string { |
70 | 78 | return client.clusterId |
71 | 79 | } |
133 | 141 | |
134 | 142 | if client.debug { |
135 | 143 | var prettyJSON bytes.Buffer |
136 | err = json.Indent(&prettyJSON, body, "", " ") | |
137 | log.Println(string(prettyJSON.Bytes())) | |
144 | _ = json.Indent(&prettyJSON, body, "", " ") | |
145 | log.Println(prettyJSON.String()) | |
138 | 146 | } |
139 | 147 | |
140 | 148 | if statusCode >= 400 && statusCode <= 599 { |
141 | 149 | errorResponse := common.ErrorResponse{} |
142 | err = json.Unmarshal(body, &errorResponse) | |
150 | _ = json.Unmarshal(body, &errorResponse) | |
143 | 151 | ecsError := &common.Error{ |
144 | 152 | ErrorResponse: errorResponse, |
145 | 153 | StatusCode: statusCode, |
0 | package cs | |
1 | ||
2 | import ( | |
3 | "fmt" | |
4 | "github.com/denverdino/aliyungo/common" | |
5 | "net/http" | |
6 | "net/url" | |
7 | "strconv" | |
8 | "time" | |
9 | ) | |
10 | ||
11 | type ServerlessCreationArgs struct { | |
12 | ClusterType KubernetesClusterType `json:"cluster_type"` | |
13 | Profile KubernetesClusterProfile `json:"profile"` | |
14 | Name string `json:"name"` | |
15 | RegionId string `json:"region_id"` | |
16 | VpcId string `json:"vpcid"` | |
17 | VSwitchId string `json:"vswitch_id"` | |
18 | VswitchIds []string `json:"vswitch_ids"` | |
19 | EndpointPublicAccess bool `json:"public_slb"` | |
20 | PrivateZone bool `json:"private_zone"` | |
21 | NatGateway bool `json:"nat_gateway"` | |
22 | KubernetesVersion string `json:"kubernetes_version"` | |
23 | DeletionProtection bool `json:"deletion_protection"` | |
24 | SecurityGroupId string `json:"security_group_id"` | |
25 | Tags []Tag `json:"tags"` | |
26 | Addons []Addon `json:"addons"` | |
27 | ResourceGroupId string `json:"resource_group_id"` | |
28 | ClusterSpec string `json:"cluster_spec"` | |
29 | LoadBalancerSpec string `json:"load_balancer_spec"` //api server slb实例规格 | |
30 | ServiceCIDR string `json:"service_cidr"` | |
31 | TimeZone string `json:"timezone"` | |
32 | ServiceDiscoveryTypes []string `json:"service_discovery_types"` | |
33 | ZoneID string `json:"zone_id"` | |
34 | LoggingType string `json:"logging_type"` | |
35 | SLSProjectName string `json:"sls_project_name"` | |
36 | SnatEntry bool `json:"snat_entry"` | |
37 | } | |
38 | ||
39 | type ServerlessClusterResponse struct { | |
40 | ClusterId string `json:"cluster_id"` | |
41 | Name string `json:"name"` | |
42 | ClusterType KubernetesClusterType `json:"cluster_type"` | |
43 | RegionId string `json:"region_id"` | |
44 | State ClusterState `json:"state"` | |
45 | VpcId string `json:"vpc_id"` | |
46 | VSwitchId string `json:"vswitch_id"` | |
47 | SecurityGroupId string `json:"security_group_id"` | |
48 | Tags []Tag `json:"tags"` | |
49 | Created time.Time `json:"created"` | |
50 | Updated time.Time `json:"updated"` | |
51 | InitVersion string `json:"init_version"` | |
52 | CurrentVersion string `json:"current_version"` | |
53 | PrivateZone bool `json:"private_zone"` | |
54 | DeletionProtection bool `json:"deletion_protection"` | |
55 | ResourceGroupId string `json:"resource_group_id"` | |
56 | ClusterSpec string `json:"cluster_spec"` | |
57 | Profile string `json:"profile"` | |
58 | } | |
59 | ||
60 | type Tag struct { | |
61 | Key string `json:"key"` | |
62 | Value string `json:"value"` | |
63 | } | |
64 | ||
65 | func (this *ServerlessCreationArgs) Validate() error { | |
66 | if this.Name == "" || this.RegionId == "" || this.VpcId == "" { | |
67 | return common.GetCustomError("InvalidParameters", "The name,region_id,vpc_id not allowed empty") | |
68 | } | |
69 | return nil | |
70 | } | |
71 | ||
72 | //create Serverless cluster | |
73 | func (client *Client) CreateServerlessKubernetesCluster(args *ServerlessCreationArgs) (*ClusterCommonResponse, error) { | |
74 | if args == nil { | |
75 | return nil, common.GetCustomError("InvalidArgs", "The args is nil ") | |
76 | } | |
77 | ||
78 | if err := args.Validate(); err != nil { | |
79 | return nil, err | |
80 | } | |
81 | ||
82 | cluster := &ClusterCommonResponse{} | |
83 | path := "/clusters" | |
84 | if args.ResourceGroupId != "" { | |
85 | // 创建集群到指定资源组 | |
86 | path = fmt.Sprintf("/resource_groups/%s/clusters", args.ResourceGroupId) | |
87 | } | |
88 | err := client.Invoke(common.Region(args.RegionId), http.MethodPost, path, nil, args, &cluster) | |
89 | if err != nil { | |
90 | return nil, err | |
91 | } | |
92 | return cluster, nil | |
93 | } | |
94 | ||
95 | //describe Serverless cluster | |
96 | func (client *Client) DescribeServerlessKubernetesCluster(clusterId string) (*ServerlessClusterResponse, error) { | |
97 | cluster := &ServerlessClusterResponse{} | |
98 | err := client.Invoke("", http.MethodGet, "/clusters/"+clusterId, nil, nil, cluster) | |
99 | if err != nil { | |
100 | return nil, err | |
101 | } | |
102 | return cluster, nil | |
103 | } | |
104 | ||
105 | //describe Serverless clsuters | |
106 | func (client *Client) DescribeServerlessKubernetesClusters() ([]*ServerlessClusterResponse, error) { | |
107 | allClusters := make([]*ServerlessClusterResponse, 0) | |
108 | askClusters := make([]*ServerlessClusterResponse, 0) | |
109 | ||
110 | err := client.Invoke("", http.MethodGet, "/clusters", nil, nil, &allClusters) | |
111 | if err != nil { | |
112 | return askClusters, err | |
113 | } | |
114 | ||
115 | for _, cluster := range allClusters { | |
116 | // Ask 1.0/2.0 | |
117 | if cluster.ClusterType == ClusterTypeServerlessKubernetes { | |
118 | askClusters = append(askClusters, cluster) | |
119 | } | |
120 | // Ask 3.0 | |
121 | if cluster.ClusterType == ClusterTypeManagedKubernetes && cluster.Profile == ProfileServerlessKubernetes { | |
122 | askClusters = append(askClusters, cluster) | |
123 | } | |
124 | } | |
125 | ||
126 | return askClusters, nil | |
127 | } | |
128 | ||
129 | //new api for get cluster kube user config | |
130 | func (client *Client) DescribeClusterUserConfig(clusterId string, privateIpAddress bool) (*ClusterConfig, error) { | |
131 | config := &ClusterConfig{} | |
132 | query := url.Values{} | |
133 | query.Add("PrivateIpAddress", strconv.FormatBool(privateIpAddress)) | |
134 | ||
135 | err := client.Invoke("", http.MethodGet, "/k8s/"+clusterId+"/user_config", query, nil, &config) | |
136 | if err != nil { | |
137 | return nil, err | |
138 | } | |
139 | return config, nil | |
140 | } |
0 | package cs | |
1 | ||
2 | import ( | |
3 | "fmt" | |
4 | "testing" | |
5 | "time" | |
6 | ) | |
7 | ||
8 | func Test_CreateServerlessKubernetesCluster(t *testing.T) { | |
9 | client := NewTestClientForDebug() | |
10 | ||
11 | tags := make([]Tag, 0) | |
12 | tags = append(tags, Tag{ | |
13 | Key: "key-a", | |
14 | Value: "key-a", | |
15 | }) | |
16 | ||
17 | tags = append(tags, Tag{ | |
18 | Key: "key-b", | |
19 | Value: "key-b", | |
20 | }) | |
21 | ||
22 | tags = append(tags, Tag{ | |
23 | Key: "key-c", | |
24 | Value: "key-c", | |
25 | }) | |
26 | ||
27 | args := &ServerlessCreationArgs{ | |
28 | ClusterType: ClusterTypeManagedKubernetes, | |
29 | Profile: ProfileServerlessKubernetes, | |
30 | Name: fmt.Sprintf("Serverless-cluster-%d", time.Now().Unix()), | |
31 | RegionId: string(TestRegionID), | |
32 | VpcId: TestVpcId, | |
33 | VswitchIds: []string{TestVSwitchId}, | |
34 | ServiceCIDR: TestServiceCIDR, | |
35 | LoggingType: TestLoggingType, | |
36 | PrivateZone: true, | |
37 | EndpointPublicAccess: true, | |
38 | NatGateway: true, | |
39 | DeletionProtection: true, | |
40 | Tags: tags, | |
41 | } | |
42 | ||
43 | response, err := client.CreateServerlessKubernetesCluster(args) | |
44 | if err != nil { | |
45 | t.Errorf("Error %++v", err) | |
46 | } else { | |
47 | t.Logf("Response = %++v", response) | |
48 | } | |
49 | } | |
50 | ||
51 | func Test_DescribeCluster(t *testing.T) { | |
52 | client := NewTestClientForDebug() | |
53 | ||
54 | cluster, err := client.DescribeServerlessKubernetesCluster(TestClusterId) | |
55 | if err != nil { | |
56 | t.Errorf("Error = %++v", err) | |
57 | } else { | |
58 | t.Logf("Cluster = %#v", cluster) | |
59 | t.Logf("%v ", cluster.Created) | |
60 | } | |
61 | } | |
62 | ||
63 | func Test_DescribeClusterUserConfig(t *testing.T) { | |
64 | client := NewTestClientForDebug() | |
65 | ||
66 | config, err := client.DescribeClusterUserConfig(TestClusterId, TestPrivateIpAddress) | |
67 | if err != nil { | |
68 | t.Errorf("Error = %++v", err) | |
69 | } else { | |
70 | t.Logf("Config = %#v", config) | |
71 | } | |
72 | } | |
73 | ||
74 | func Test_DeleteServerlessCluster(t *testing.T) { | |
75 | client := NewTestClientForDebug() | |
76 | ||
77 | err := client.DeleteCluster(TestClusterId) | |
78 | if err != nil { | |
79 | t.Errorf("Error = %++v", err) | |
80 | } else { | |
81 | t.Logf("OK") | |
82 | } | |
83 | } | |
84 | ||
85 | func Test_DescribeServerlessKubernetesClusters(t *testing.T) { | |
86 | client := NewTestClientForDebug() | |
87 | clusters, err := client.DescribeServerlessKubernetesClusters() | |
88 | if err != nil { | |
89 | t.Errorf("Error = %++v", err) | |
90 | } else { | |
91 | for _, cluster := range clusters { | |
92 | t.Logf("Cluster = %#v", cluster) | |
93 | } | |
94 | } | |
95 | } |
0 | package cs | |
1 | ||
2 | import ( | |
3 | "fmt" | |
4 | "github.com/denverdino/aliyungo/common" | |
5 | "net/http" | |
6 | ) | |
7 | ||
8 | type ClusterTokenReqeust struct { | |
9 | //token 过期时间,如果不填写,则默认24小时过期 | |
10 | Expired int64 `json:"expired"` | |
11 | IsPermanently bool `json:"is_permanently"` | |
12 | } | |
13 | ||
14 | type ClusterTokenResponse struct { | |
15 | Created int64 ` json:"created"` | |
16 | Updated int64 `json:"updated"` | |
17 | Expired int64 ` json:"expired"` | |
18 | ||
19 | ClusterID string ` json:"cluster_id"` | |
20 | ||
21 | Token string ` json:"token"` | |
22 | IsActive int ` json:"is_active"` | |
23 | } | |
24 | ||
25 | func (client *Client) CreateClusterToken(clusterId string, request *ClusterTokenReqeust) (*ClusterTokenResponse, error) { | |
26 | response := &ClusterTokenResponse{} | |
27 | err := client.Invoke("", http.MethodPost, "/clusters/"+clusterId+"/token", nil, request, response) | |
28 | return response, err | |
29 | } | |
30 | ||
31 | func (client *Client) RevokeToken(token string) error { | |
32 | return client.Invoke("", http.MethodDelete, "/token/"+token+"/revoke", nil, nil, nil) | |
33 | } | |
34 | ||
35 | func (client *Client) DescribeClusterTokens(clusterId string) ([]*ClusterTokenResponse, error) { | |
36 | response := make([]*ClusterTokenResponse, 0) | |
37 | err := client.Invoke("", http.MethodGet, "/clusters/"+clusterId+"/tokens", nil, nil, &response) | |
38 | return response, err | |
39 | } | |
40 | ||
41 | func (client *Client) DescribeClusterToken(clusterId, token string) (*ClusterTokenResponse, error) { | |
42 | if clusterId == "" || token == "" { | |
43 | return nil, common.GetCustomError("InvalidParamter", "The clusterId or token is empty") | |
44 | } | |
45 | tokenInfo := &ClusterTokenResponse{} | |
46 | err := client.Invoke("", http.MethodGet, fmt.Sprintf("/clusters/%s/tokens/%s", clusterId, token), nil, nil, tokenInfo) | |
47 | return tokenInfo, err | |
48 | } |
0 | package cs | |
1 | ||
2 | import ( | |
3 | "testing" | |
4 | "time" | |
5 | ) | |
6 | ||
7 | func Test_CreateClusterToken(t *testing.T) { | |
8 | client := NewTestClientForDebug() | |
9 | ||
10 | req := &ClusterTokenReqeust{ | |
11 | Expired: time.Now().Unix() + 86400, | |
12 | IsPermanently: false, | |
13 | } | |
14 | ||
15 | token, err := client.CreateClusterToken(TestClusterId, req) | |
16 | if err != nil { | |
17 | t.Fatalf("Error %++v", err) | |
18 | } else { | |
19 | t.Logf("Token = %++v", token) | |
20 | } | |
21 | } | |
22 | ||
23 | func Test_RevokeClusterToken(t *testing.T) { | |
24 | client := NewTestClientForDebug() | |
25 | req := &ClusterTokenReqeust{ | |
26 | Expired: time.Now().Unix() + 86400, | |
27 | IsPermanently: false, | |
28 | } | |
29 | ||
30 | token, err := client.CreateClusterToken(TestClusterId, req) | |
31 | if err != nil { | |
32 | t.Fatalf("Error = %++v", err) | |
33 | } else { | |
34 | err = client.RevokeToken(token.Token) | |
35 | if err != nil { | |
36 | t.Fatalf("Error = %++v", err) | |
37 | } else { | |
38 | tokens, err := client.DescribeClusterTokens(TestClusterId) | |
39 | if err != nil { | |
40 | t.Fatalf("Error %++v", err) | |
41 | } else { | |
42 | for _, token := range tokens { | |
43 | t.Logf("Token = %++v", token) | |
44 | } | |
45 | } | |
46 | } | |
47 | } | |
48 | } | |
49 | ||
50 | func Test_DescribeClusterTokens(t *testing.T) { | |
51 | client := NewTestClientForDebug() | |
52 | ||
53 | tokens, err := client.DescribeClusterTokens(TestClusterId) | |
54 | if err != nil { | |
55 | t.Fatalf("Error %++v", err) | |
56 | } else { | |
57 | for _, token := range tokens { | |
58 | t.Logf("Token = %++v", token) | |
59 | } | |
60 | } | |
61 | } | |
62 | ||
63 | func Test_DescribeClusterToken(t *testing.T) { | |
64 | client := NewTestClientForDebug() | |
65 | ||
66 | token, err := client.DescribeClusterToken(TestClusterId, TestToken) | |
67 | if err != nil { | |
68 | t.Fatalf("Error %++v", err) | |
69 | } else { | |
70 | t.Logf("Token = %++v", token) | |
71 | } | |
72 | } |
63 | 63 | return NewECSClientWithEndpointAndSecurityToken(endpoint, accessKeyId, accessKeySecret, securityToken, regionID) |
64 | 64 | } |
65 | 65 | |
66 | //only for Hangzhou Regional Domain | |
67 | func NewECSClientWithSecurityToken4RegionalDomain(accessKeyId string, accessKeySecret string, securityToken string, regionID common.Region) *Client { | |
68 | endpoint := os.Getenv("ECS_ENDPOINT") | |
69 | if endpoint != "" { | |
70 | return NewECSClientWithSecurityToken(accessKeyId, accessKeySecret, securityToken, regionID) | |
71 | } | |
72 | ||
73 | return NewECSClientWithEndpointAndSecurityToken4RegionalDomain(endpoint, accessKeyId, accessKeySecret, securityToken, regionID) | |
74 | } | |
75 | ||
66 | 76 | func NewECSClientWithEndpoint(endpoint string, accessKeyId string, accessKeySecret string, regionID common.Region) *Client { |
67 | 77 | return NewECSClientWithEndpointAndSecurityToken(endpoint, accessKeyId, accessKeySecret, "", regionID) |
68 | 78 | } |
77 | 87 | WithServiceCode(ECSServiceCode). |
78 | 88 | WithRegionID(regionID). |
79 | 89 | InitClient() |
90 | return client | |
91 | } | |
92 | ||
93 | func NewECSClientWithEndpointAndSecurityToken4RegionalDomain(endpoint string, accessKeyId string, accessKeySecret string, securityToken string, regionID common.Region) *Client { | |
94 | client := &Client{} | |
95 | client.WithEndpoint(endpoint). | |
96 | WithVersion(ECSAPIVersion). | |
97 | WithAccessKeyId(accessKeyId). | |
98 | WithAccessKeySecret(accessKeySecret). | |
99 | WithSecurityToken(securityToken). | |
100 | WithServiceCode(ECSServiceCode). | |
101 | WithRegionID(regionID). | |
102 | InitClient4RegionalDomain() | |
80 | 103 | return client |
81 | 104 | } |
82 | 105 | |
96 | 119 | return NewVPCClientWithEndpointAndSecurityToken(endpoint, accessKeyId, accessKeySecret, securityToken, regionID) |
97 | 120 | } |
98 | 121 | |
122 | //Only for Hangzhou | |
123 | func NewVPCClientWithSecurityToken4RegionalDomain(accessKeyId string, accessKeySecret string, securityToken string, regionID common.Region) *Client { | |
124 | endpoint := os.Getenv("VPC_ENDPOINT") | |
125 | if endpoint != "" { | |
126 | return NewVPCClientWithEndpointAndSecurityToken(endpoint, accessKeyId, accessKeySecret, securityToken, regionID) | |
127 | } | |
128 | ||
129 | return NewVPCClientWithEndpointAndSecurityToken4RegionalDomain(endpoint, accessKeyId, accessKeySecret, securityToken, regionID) | |
130 | } | |
131 | ||
99 | 132 | func NewVPCClientWithEndpoint(endpoint string, accessKeyId string, accessKeySecret string, regionID common.Region) *Client { |
100 | 133 | return NewVPCClientWithEndpointAndSecurityToken(endpoint, accessKeyId, accessKeySecret, "", regionID) |
101 | 134 | } |
113 | 146 | return client |
114 | 147 | } |
115 | 148 | |
149 | //Only for Hangzhou | |
150 | func NewVPCClientWithEndpointAndSecurityToken4RegionalDomain(endpoint string, accessKeyId string, accessKeySecret string, securityToken string, regionID common.Region) *Client { | |
151 | client := &Client{} | |
152 | client.WithEndpoint(endpoint). | |
153 | WithVersion(VPCAPIVersion). | |
154 | WithAccessKeyId(accessKeyId). | |
155 | WithAccessKeySecret(accessKeySecret). | |
156 | WithSecurityToken(securityToken). | |
157 | WithServiceCode(VPCServiceCode). | |
158 | WithRegionID(regionID). | |
159 | InitClient4RegionalDomain() | |
160 | return client | |
161 | } | |
162 | ||
116 | 163 | // --------------------------------------- |
117 | 164 | // NewVPCClientWithRegion creates a new instance of VPC client automatically get endpoint |
118 | 165 | // --------------------------------------- |
0 | 0 | package ecs |
1 | 1 | |
2 | 2 | import ( |
3 | "github.com/denverdino/aliyungo/common" | |
4 | "github.com/magiconair/properties/assert" | |
5 | "os" | |
3 | 6 | "testing" |
4 | 7 | ) |
5 | 8 | |
72 | 75 | } |
73 | 76 | } |
74 | 77 | } |
78 | ||
79 | func Test_NewVPCClientWithSecurityToken4RegionalDomain(t *testing.T) { | |
80 | client := NewVPCClientWithSecurityToken4RegionalDomain(TestAccessKeyId, TestAccessKeySecret, TestSecurityToken, common.Beijing) | |
81 | assert.Equal(t, client.GetEndpoint(), "https://vpc-vpc.cn-beijing.aliyuncs.com") | |
82 | ||
83 | os.Setenv("VPC_ENDPOINT", "vpc.aliyuncs.com") | |
84 | client = NewVPCClientWithSecurityToken4RegionalDomain(TestAccessKeyId, TestAccessKeySecret, TestSecurityToken, common.Beijing) | |
85 | assert.Equal(t, client.GetEndpoint(), "vpc.aliyuncs.com") | |
86 | } |
13 | 13 | TestSecurityToken = os.Getenv("SecurityToken") |
14 | 14 | TestRegionID = common.Region(os.Getenv("RegionId")) |
15 | 15 | TestVpcId = os.Getenv("VpcId") |
16 | TestVswitchID = os.Getenv("TestVswitchID") | |
16 | 17 | |
17 | 18 | TestInstanceId = os.Getenv("InstanceId") |
18 | TestSecurityGroupId = "MY_TEST_SECURITY_GROUP_ID" | |
19 | TestImageId = "MY_IMAGE_ID" | |
19 | TestSecurityGroupId = os.Getenv("TestSecurityGroupId") | |
20 | TestResourceGroupId = os.Getenv("TestResourceGroupId") | |
21 | TestImageId = os.Getenv("TestImageId") | |
20 | 22 | TestAccountId = "MY_TEST_ACCOUNT_ID" //Get from https://account.console.aliyun.com |
21 | TestInstanceType = "ecs.n4.large" | |
23 | TestInstanceType = os.Getenv("InstanceType") | |
22 | 24 | TestVSwitchID = "MY_TEST_VSWITCHID" |
23 | 25 | |
24 | 26 | TestIAmRich = false |
58 | 60 | |
59 | 61 | func NetTestLocationClientForDebug() *Client { |
60 | 62 | if testLocationClient == nil { |
61 | testLocationClient = NewECSClient(TestAccessKeyId, TestAccessKeySecret, TestRegionID) | |
63 | testLocationClient = NewECSClientWithSecurityToken4RegionalDomain(TestAccessKeyId, TestAccessKeySecret, TestSecurityToken, TestRegionID) | |
62 | 64 | testLocationClient.SetDebug(true) |
63 | 65 | } |
64 | 66 |
25 | 25 | DiskCategoryEphemeralSSD = DiskCategory("ephemeral_ssd") |
26 | 26 | DiskCategoryCloudEfficiency = DiskCategory("cloud_efficiency") |
27 | 27 | DiskCategoryCloudSSD = DiskCategory("cloud_ssd") |
28 | DiskCategoryCloudESSD = DiskCategory("cloud_essd") | |
29 | ) | |
30 | ||
31 | // Performance Level of disks | |
32 | type DiskPerformanceLevel string | |
33 | ||
34 | const ( | |
35 | DiskPL0 = DiskCategory("PL0") | |
36 | DiskPL1 = DiskCategory("PL1") | |
37 | DiskPL2 = DiskCategory("PL2") | |
38 | DiskPL3 = DiskCategory("PL3") | |
28 | 39 | ) |
29 | 40 | |
30 | 41 | // Status of disks |
95 | 106 | AttachedTime util.ISO6801Time |
96 | 107 | DetachedTime util.ISO6801Time |
97 | 108 | DiskChargeType DiskChargeType |
109 | StorageSetId string | |
110 | PerformanceLevel DiskPerformanceLevel | |
98 | 111 | } |
99 | 112 | |
100 | 113 | type DescribeDisksResponse struct { |
138 | 151 | Encrypted bool |
139 | 152 | DiskCategory DiskCategory |
140 | 153 | Size int |
154 | Tag map[string]string | |
141 | 155 | SnapshotId string |
142 | 156 | ClientToken string |
157 | KMSKeyID string | |
158 | StorageSetId string | |
159 | ||
160 | PerformanceLevel DiskPerformanceLevel | |
143 | 161 | } |
144 | 162 | |
145 | 163 | type CreateDisksResponse struct { |
346 | 364 | if err != nil { |
347 | 365 | return err |
348 | 366 | } |
349 | if disks == nil || len(disks) == 0 { | |
367 | if len(disks) == 0 { | |
350 | 368 | return common.GetClientErrorFromString("Not found") |
351 | 369 | } |
352 | 370 | if disks[0].Status == status { |
4 | 4 | "time" |
5 | 5 | |
6 | 6 | "github.com/denverdino/aliyungo/common" |
7 | "github.com/denverdino/aliyungo/util" | |
7 | 8 | ) |
8 | 9 | |
9 | 10 | type CreateNetworkInterfaceArgs struct { |
10 | RegionId common.Region | |
11 | VSwitchId string | |
12 | PrimaryIpAddress string // optional | |
13 | SecurityGroupId string | |
14 | NetworkInterfaceName string // optional | |
15 | Description string // optional | |
16 | ClientToken string // optional | |
11 | RegionId common.Region | |
12 | VSwitchId string | |
13 | PrimaryIpAddress string // optional | |
14 | SecurityGroupId string | |
15 | NetworkInterfaceName string // optional | |
16 | Description string // optional | |
17 | ClientToken string // optional | |
18 | Tag map[string]string // optional | |
19 | ResourceGroupId string // optional | |
20 | SecurityGroupIds []string `query:"list"` // optional | |
21 | PrivateIpAddress []string `query:"list"` // optional | |
22 | SecondaryPrivateIpAddressCount int | |
17 | 23 | } |
18 | 24 | |
19 | 25 | type CreateNetworkInterfaceResponse struct { |
32 | 38 | type DescribeNetworkInterfacesArgs struct { |
33 | 39 | RegionId common.Region |
34 | 40 | VSwitchId string |
41 | VpcID string | |
35 | 42 | PrimaryIpAddress string |
43 | PrivateIpAddress []string `query:"list"` | |
36 | 44 | SecurityGroupId string |
37 | 45 | NetworkInterfaceName string |
38 | 46 | Type string |
45 | 53 | NetworkInterfaceId string |
46 | 54 | NetworkInterfaceName string |
47 | 55 | PrimaryIpAddress string |
48 | MacAddress string | |
49 | Status string | |
50 | PrivateIpAddress string | |
56 | PrivateIpSets struct { | |
57 | PrivateIpSet []PrivateIpType | |
58 | } | |
59 | MacAddress string | |
60 | Status string | |
61 | Type string | |
62 | VpcId string | |
63 | VSwitchId string | |
64 | ZoneId string | |
65 | AssociatedPublicIp AssociatedPublicIp | |
66 | SecurityGroupIds struct { | |
67 | SecurityGroupId []string | |
68 | } | |
69 | Description string | |
70 | InstanceId string | |
71 | CreationTime util.ISO6801Time | |
72 | PrivateIpAddress string | |
73 | } | |
74 | ||
75 | type PrivateIpType struct { | |
76 | PrivateIpAddress string | |
77 | Primary bool | |
78 | AssociatedPublicIp AssociatedPublicIp | |
79 | } | |
80 | ||
81 | type AssociatedPublicIp struct { | |
82 | PublicIpAddress string | |
83 | AllocationId string | |
51 | 84 | } |
52 | 85 | |
53 | 86 | type DescribeNetworkInterfacesResponse struct { |
74 | 107 | type ModifyNetworkInterfaceAttributeArgs struct { |
75 | 108 | RegionId common.Region |
76 | 109 | NetworkInterfaceId string |
77 | SecurityGroupId []string | |
110 | SecurityGroupId []string `query:"list"` | |
78 | 111 | NetworkInterfaceName string |
79 | 112 | Description string |
80 | 113 | } |
81 | 114 | type ModifyNetworkInterfaceAttributeResponse common.Response |
115 | ||
116 | type UnassignPrivateIpAddressesArgs struct { | |
117 | RegionId common.Region | |
118 | NetworkInterfaceId string | |
119 | PrivateIpAddress []string `query:"list"` | |
120 | } | |
121 | ||
122 | type UnassignPrivateIpAddressesResponse common.Response | |
123 | ||
124 | type AssignPrivateIpAddressesArgs struct { | |
125 | RegionId common.Region | |
126 | NetworkInterfaceId string | |
127 | PrivateIpAddress []string `query:"list"` // optional | |
128 | SecondaryPrivateIpAddressCount int // optional | |
129 | } | |
130 | ||
131 | type AssignPrivateIpAddressesResponse struct { | |
132 | common.Response | |
133 | ||
134 | AssignedPrivateIpAddressesSet struct { | |
135 | NetworkInterfaceId string | |
136 | PrivateIpSet struct { | |
137 | PrivateIpAddress []string | |
138 | } | |
139 | } | |
140 | } | |
82 | 141 | |
83 | 142 | func (client *Client) CreateNetworkInterface(args *CreateNetworkInterfaceArgs) (resp *CreateNetworkInterfaceResponse, err error) { |
84 | 143 | resp = &CreateNetworkInterfaceResponse{} |
116 | 175 | return resp, err |
117 | 176 | } |
118 | 177 | |
178 | func (client *Client) UnassignPrivateIpAddresses(args *UnassignPrivateIpAddressesArgs) (resp *UnassignPrivateIpAddressesResponse, err error) { | |
179 | resp = &UnassignPrivateIpAddressesResponse{} | |
180 | err = client.Invoke("UnassignPrivateIpAddresses", args, resp) | |
181 | return resp, err | |
182 | } | |
183 | ||
184 | func (client *Client) AssignPrivateIpAddresses(args *AssignPrivateIpAddressesArgs) (resp *AssignPrivateIpAddressesResponse, err error) { | |
185 | resp = &AssignPrivateIpAddressesResponse{} | |
186 | err = client.Invoke("AssignPrivateIpAddresses", args, resp) | |
187 | return resp, err | |
188 | } | |
189 | ||
119 | 190 | // Default timeout value for WaitForInstance method |
120 | 191 | const NetworkInterfacesDefaultTimeout = 120 |
121 | 192 |
0 | package ecs | |
1 | ||
2 | import ( | |
3 | "github.com/denverdino/aliyungo/common" | |
4 | "testing" | |
5 | "time" | |
6 | ) | |
7 | ||
8 | func TestAssignPrivateIPAddresses(t *testing.T) { | |
9 | req := AssignPrivateIpAddressesArgs{ | |
10 | RegionId: common.Beijing, | |
11 | NetworkInterfaceId: "eni-testeni", | |
12 | PrivateIpAddress: []string{"192.168.1.200", "192.168.1.201"}, | |
13 | } | |
14 | client := NewTestClient() | |
15 | assignPrivateIpAddressesResponse, err := client.AssignPrivateIpAddresses(&req) | |
16 | if err != nil { | |
17 | t.Errorf("Failed to AssignPrivateIpAddresses: %v", err) | |
18 | } | |
19 | ||
20 | if assignPrivateIpAddressesResponse.AssignedPrivateIpAddressesSet.NetworkInterfaceId != "eni-testeni" { | |
21 | t.Errorf("assert network id mismatch.%s\n", assignPrivateIpAddressesResponse.AssignedPrivateIpAddressesSet.NetworkInterfaceId) | |
22 | } | |
23 | ||
24 | time.Sleep(5 * time.Second) | |
25 | ||
26 | req = AssignPrivateIpAddressesArgs{ | |
27 | RegionId: common.Beijing, | |
28 | NetworkInterfaceId: "eni-testeni", | |
29 | SecondaryPrivateIpAddressCount: 1, | |
30 | } | |
31 | ||
32 | _, err = client.AssignPrivateIpAddresses(&req) | |
33 | if err != nil { | |
34 | t.Errorf("Failed to AssignPrivateIpAddresses: %v", err) | |
35 | } | |
36 | } | |
37 | ||
38 | func TestDescribeENI(t *testing.T) { | |
39 | req := DescribeNetworkInterfacesArgs{ | |
40 | RegionId: common.Beijing, | |
41 | NetworkInterfaceId: []string{"eni-testeni"}, | |
42 | } | |
43 | client := NewTestClient() | |
44 | resp, err := client.DescribeNetworkInterfaces(&req) | |
45 | if err != nil { | |
46 | t.Errorf("Failed to DescribeNetworkInterfaces: %v", err) | |
47 | } | |
48 | if len(resp.NetworkInterfaceSets.NetworkInterfaceSet[0].PrivateIpSets.PrivateIpSet) != 4 { | |
49 | t.Errorf("assert network private ip count be 4, %+v", resp.NetworkInterfaceSets.NetworkInterfaceSet[0].PrivateIpSets.PrivateIpSet) | |
50 | } | |
51 | t.Logf("%+v", resp.NetworkInterfaceSets.NetworkInterfaceSet[0]) | |
52 | } | |
53 | ||
54 | func TestFindENIByPrivateIP(t *testing.T) { | |
55 | req := DescribeNetworkInterfacesArgs{ | |
56 | RegionId: common.Shanghai, | |
57 | VpcID: "vpc-xxx", | |
58 | PrivateIpAddress: []string{"192.168.108.191"}, | |
59 | } | |
60 | client := NewTestClient() | |
61 | resp, err := client.DescribeNetworkInterfaces(&req) | |
62 | if err != nil { | |
63 | t.Errorf("Failed to DescribeNetworkInterfaces: %v", err) | |
64 | } | |
65 | t.Logf("%+v", resp.NetworkInterfaceSets.NetworkInterfaceSet) | |
66 | } | |
67 | ||
68 | func TestUnAssignPrivateIPAddresses(t *testing.T) { | |
69 | req := UnassignPrivateIpAddressesArgs{ | |
70 | RegionId: common.Beijing, | |
71 | NetworkInterfaceId: "eni-testeni", | |
72 | PrivateIpAddress: []string{"192.168.1.200", "192.168.1.201"}, | |
73 | } | |
74 | client := NewTestClient() | |
75 | _, err := client.UnassignPrivateIpAddresses(&req) | |
76 | if err != nil { | |
77 | t.Errorf("Failed to UnAssignPrivateIpAddresses: %v", err) | |
78 | } | |
79 | } | |
80 | ||
81 | func TestModifyNetworkInterfaceAttribute(t *testing.T) { | |
82 | args := &ModifyNetworkInterfaceAttributeArgs{ | |
83 | RegionId: common.Shanghai, | |
84 | NetworkInterfaceId: "eni-testeni", | |
85 | SecurityGroupId: []string{"sg-xxx", "sg-yyy"}, | |
86 | } | |
87 | ||
88 | client := NewTestClient() | |
89 | _, err := client.ModifyNetworkInterfaceAttribute(args) | |
90 | if err != nil { | |
91 | t.Errorf("failed to ModifyNetworkInterfaceAttribute: %v", err) | |
92 | } | |
93 | } | |
94 | ||
95 | func TestCreateNetworkInterface(t *testing.T) { | |
96 | args := &CreateNetworkInterfaceArgs{ | |
97 | RegionId: common.Shanghai, | |
98 | VSwitchId: "vsw-xxx", | |
99 | SecurityGroupIds: []string{"sg-xxx", "sg-yyy"}, | |
100 | SecondaryPrivateIpAddressCount: 9, | |
101 | } | |
102 | client := NewTestClient() | |
103 | resp, err := client.CreateNetworkInterface(args) | |
104 | if err != nil { | |
105 | t.Errorf("failed to CreateNetworkInterface: %v", err) | |
106 | } | |
107 | t.Logf("new eni info: %+v", resp) | |
108 | } |
312 | 312 | if err != nil { |
313 | 313 | return err |
314 | 314 | } |
315 | if images == nil || len(images) == 0 { | |
315 | if len(images) == 0 { | |
316 | 316 | args.Status = ImageStatusAvailable |
317 | 317 | images, _, er := client.DescribeImages(&args) |
318 | 318 | if er == nil && len(images) == 1 { |
3 | 3 | |
4 | 4 | type DescribeInstanceTypesArgs struct { |
5 | 5 | InstanceTypeFamily string |
6 | InstanceTypes []string `query:"list"` | |
6 | 7 | } |
7 | 8 | |
8 | 9 | // |
9 | 10 | // You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&instancetypeitemtype |
10 | 11 | type InstanceTypeItemType struct { |
11 | InstanceTypeId string | |
12 | CpuCoreCount int | |
13 | MemorySize float64 | |
14 | InstanceTypeFamily string | |
15 | GPUAmount int | |
16 | GPUSpec string | |
17 | InitialCredit int | |
18 | BaselineCredit int | |
19 | EniQuantity int | |
20 | LocalStorageCapacity int | |
21 | LocalStorageAmount int | |
22 | LocalStorageCategory string | |
12 | InstanceTypeId string | |
13 | CpuCoreCount int | |
14 | MemorySize float64 | |
15 | InstanceTypeFamily string | |
16 | GPUAmount int | |
17 | GPUSpec string | |
18 | InitialCredit int | |
19 | BaselineCredit int | |
20 | EniQuantity int | |
21 | EniPrivateIpAddressQuantity int | |
22 | LocalStorageCapacity int | |
23 | LocalStorageAmount int | |
24 | LocalStorageCategory string | |
23 | 25 | } |
24 | 26 | |
25 | 27 | type DescribeInstanceTypesResponse struct { |
4 | 4 | ) |
5 | 5 | |
6 | 6 | func TestDescribeInstanceTypes(t *testing.T) { |
7 | ||
8 | 7 | client := NewTestClient() |
9 | 8 | instanceTypes, err := client.DescribeInstanceTypes() |
10 | 9 | if err != nil { |
13 | 12 | for _, instanceType := range instanceTypes { |
14 | 13 | t.Logf("InstanceType: %++v", instanceType) |
15 | 14 | } |
15 | ||
16 | instanceTypes, err = client.DescribeInstanceTypesNew(&DescribeInstanceTypesArgs{ | |
17 | InstanceTypes: []string{"ecs.ec5.24xlarge", "ecs.ddh6s.custom.c4m48"}, | |
18 | }) | |
19 | if err != nil { | |
20 | t.Fatalf("Failed to DescribeInstanceTypesNew: %v", err) | |
21 | } | |
22 | for _, instanceType := range instanceTypes { | |
23 | t.Logf("InstanceType: %++v", instanceType) | |
24 | } | |
16 | 25 | } |
229 | 229 | // |
230 | 230 | // You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&instanceattributestype |
231 | 231 | type InstanceAttributesType struct { |
232 | AutoReleaseTime string | |
232 | 233 | InstanceId string |
233 | 234 | InstanceName string |
234 | 235 | Description string |
235 | 236 | ImageId string |
236 | 237 | RegionId common.Region |
237 | 238 | ZoneId string |
238 | CPU int | |
239 | Cpu int | |
240 | CpuOptions CpuOptionsType | |
239 | 241 | Memory int |
240 | 242 | ClusterId string |
241 | 243 | InstanceType string |
247 | 249 | SecurityGroupIds struct { |
248 | 250 | SecurityGroupId []string |
249 | 251 | } |
250 | PublicIpAddress IpAddressSetType | |
251 | InnerIpAddress IpAddressSetType | |
252 | InstanceNetworkType string //enum Classic | Vpc | |
253 | InternetMaxBandwidthIn int | |
254 | InternetMaxBandwidthOut int | |
255 | InternetChargeType common.InternetChargeType | |
256 | CreationTime util.ISO6801Time //time.Time | |
257 | VpcAttributes VpcAttributesType | |
258 | EipAddress EipAddressAssociateType | |
259 | IoOptimized StringOrBool | |
260 | InstanceChargeType common.InstanceChargeType | |
261 | ExpiredTime util.ISO6801Time | |
262 | Tags struct { | |
252 | PublicIpAddress IpAddressSetType | |
253 | InnerIpAddress IpAddressSetType | |
254 | InstanceNetworkType string //enum Classic | Vpc | |
255 | InternetMaxBandwidthIn int | |
256 | InternetMaxBandwidthOut int | |
257 | InternetChargeType common.InternetChargeType | |
258 | CreationTime util.ISO6801Time //time.Time | |
259 | CreditSpecification string | |
260 | DedicatedHostAttribute DedicatedHostAttributeType | |
261 | DedicatedInstanceAttribute DedicatedInstanceAttributeType | |
262 | DeletionProtection bool | |
263 | DeploymentSetGroupNo int | |
264 | DeploymentSetId string | |
265 | DeviceAvailable bool | |
266 | EcsCapacityReservationAttr EcsCapacityReservationAttrType | |
267 | VpcAttributes VpcAttributesType | |
268 | EipAddress EipAddressAssociateType | |
269 | IoOptimized StringOrBool | |
270 | InstanceChargeType common.InstanceChargeType | |
271 | ExpiredTime util.ISO6801Time | |
272 | GPUAmount int | |
273 | GPUSpec string | |
274 | HibernationOptions HibernationOptionsType | |
275 | HpcClusterId string | |
276 | ISP string | |
277 | LocalStorageAmount int | |
278 | LocalStorageCapacity int | |
279 | MetadataOptions MetadataOptionsType | |
280 | NetworkInterfaces struct { | |
281 | NetworkInterface []InstanceNetworkInterfaceType | |
282 | } | |
283 | OSName string | |
284 | OSNameEn string | |
285 | OSType string | |
286 | RdmaIpAddress RdmaIpAddressType | |
287 | Recyclable bool | |
288 | ResourceGroupId string | |
289 | SaleCycle string | |
290 | SpotDuration int | |
291 | StartTime string | |
292 | StoppedMode string | |
293 | Tags struct { | |
263 | 294 | Tag []TagItemType |
264 | 295 | } |
296 | VlanId string | |
265 | 297 | SpotStrategy SpotStrategyType |
266 | 298 | SpotPriceLimit float64 |
267 | 299 | KeyPairName string |
300 | } | |
301 | ||
302 | type CpuOptionsType struct { | |
303 | CoreCount int | |
304 | Numa string | |
305 | ThreadsPerCore int | |
306 | } | |
307 | ||
308 | type DedicatedHostAttributeType struct { | |
309 | DedicatedHostClusterId string | |
310 | DedicatedHostId string | |
311 | DedicatedHostName string | |
312 | } | |
313 | ||
314 | type DedicatedInstanceAttributeType struct { | |
315 | Affinity string | |
316 | Tenancy string | |
317 | } | |
318 | ||
319 | type EcsCapacityReservationAttrType struct { | |
320 | CapacityReservationId string | |
321 | CapacityReservationPreference string | |
322 | } | |
323 | ||
324 | type HibernationOptionsType struct { | |
325 | Configured bool | |
326 | } | |
327 | ||
328 | type MetadataOptionsType struct { | |
329 | HttpEndpoint string | |
330 | HttpPutResponseHopLimit int | |
331 | HttpTokens string | |
332 | } | |
333 | ||
334 | type InstanceNetworkInterfaceType struct { | |
335 | Ipv6Sets struct { | |
336 | Ipv6Set []Ipv6SetType | |
337 | } | |
338 | MacAddress string | |
339 | NetworkInterfaceId string | |
340 | PrimaryIpAddress string | |
341 | Type string | |
342 | PrivateIpSets struct { | |
343 | PrivateIpSet []PrivateIpSetType | |
344 | } | |
345 | } | |
346 | ||
347 | type Ipv6SetType struct { | |
348 | Ipv6Address string | |
349 | } | |
350 | ||
351 | type PrivateIpSetType struct { | |
352 | Primary bool | |
353 | PrivateIpAddress string | |
354 | } | |
355 | ||
356 | type RdmaIpAddressType struct { | |
357 | RdmaIpAddress []string | |
268 | 358 | } |
269 | 359 | |
270 | 360 | type DescribeInstanceAttributeResponse struct { |
400 | 490 | PrivateIpAddresses string |
401 | 491 | InnerIpAddresses string |
402 | 492 | PublicIpAddresses string |
493 | EipAddresses string | |
494 | InstanceChargeType common.InstanceChargeType | |
495 | InternetChargeType common.InternetChargeType | |
496 | ImageId string | |
497 | LockReason string | |
403 | 498 | SecurityGroupId string |
404 | Tag map[string]string | |
405 | 499 | InstanceType string |
406 | 500 | SpotStrategy SpotStrategyType |
407 | 501 | common.Pagination |
502 | NextToken string | |
503 | MaxResults int | |
504 | Filter []Filter | |
505 | IoOptimized *bool | |
506 | InstanceTypeFamily string | |
507 | KeyPairName string | |
508 | ResourceGroupId string | |
509 | HpcClusterId string | |
510 | RdmaIpAddresses string | |
511 | DryRun bool | |
512 | HttpEndpoint string | |
513 | HttpTokens string | |
514 | Tag []TagType | |
408 | 515 | } |
409 | 516 | |
410 | 517 | type DescribeInstancesResponse struct { |
411 | 518 | common.Response |
412 | 519 | common.PaginationResult |
520 | NextToken string | |
413 | 521 | Instances struct { |
414 | 522 | Instance []InstanceAttributesType |
415 | 523 | } |
487 | 595 | Description string |
488 | 596 | Device string |
489 | 597 | DeleteWithInstance bool |
598 | PerformanceLevel string | |
599 | KMSKeyId string | |
600 | Encrypted bool | |
490 | 601 | } |
491 | 602 | |
492 | 603 | type SystemDiskType struct { |
493 | Size int | |
494 | Category DiskCategory //Enum cloud, ephemeral, ephemeral_ssd | |
495 | DiskName string | |
496 | Description string | |
604 | Size int | |
605 | Category DiskCategory //Enum cloud, ephemeral, ephemeral_ssd | |
606 | DiskName string | |
607 | Description string | |
608 | PerformanceLevel DiskPerformanceLevel | |
609 | AutoSnapshotPolicyId string | |
497 | 610 | } |
498 | 611 | |
499 | 612 | type IoOptimized string |
544 | 657 | RegionId common.Region |
545 | 658 | ZoneId string |
546 | 659 | ImageId string |
660 | ImageFamily string | |
547 | 661 | InstanceType string |
548 | 662 | SecurityGroupId string |
549 | 663 | InstanceName string |
553 | 667 | InternetMaxBandwidthOut int |
554 | 668 | HostName string |
555 | 669 | Password string |
670 | PasswordInherit bool | |
671 | DeploymentSetId string | |
672 | ClusterId string | |
673 | VlanId string | |
674 | InnerIpAddress string | |
556 | 675 | IoOptimized IoOptimized |
676 | UseAdditionalService *bool | |
557 | 677 | SystemDisk SystemDiskType |
558 | 678 | DataDisk []DataDiskType |
559 | 679 | VSwitchId string |
567 | 687 | AutoRenewPeriod int |
568 | 688 | SpotStrategy SpotStrategyType |
569 | 689 | SpotPriceLimit float64 |
690 | SpotDuration *int | |
691 | SpotInterruptionBehavior string | |
570 | 692 | KeyPairName string |
571 | 693 | RamRoleName string |
572 | 694 | SecurityEnhancementStrategy SecurityEnhancementStrategy |
695 | ResourceGroupId string | |
696 | HpcClusterId string | |
697 | DryRun bool | |
698 | DedicatedHostId string | |
699 | CreditSpecification string | |
700 | DeletionProtection bool | |
701 | Affinity string | |
702 | Tenancy string | |
703 | StorageSetId string | |
704 | StorageSetPartitionNumber int | |
705 | HttpEndpoint string | |
706 | HttpTokens string | |
707 | PrivatePoolOptions []PrivatePoolOptionsType | |
708 | Tag []TagType | |
709 | } | |
710 | ||
711 | type PrivatePoolOptionsType struct { | |
712 | MatchCriteria string | |
713 | Id string | |
714 | } | |
715 | ||
716 | type TagType struct { | |
717 | Key string | |
718 | Value string | |
573 | 719 | } |
574 | 720 | |
575 | 721 | type CreateInstanceResponse struct { |
3 | 3 | "encoding/json" |
4 | 4 | "fmt" |
5 | 5 | "testing" |
6 | "time" | |
6 | 7 | |
7 | 8 | "github.com/denverdino/aliyungo/common" |
8 | 9 | ) |
331 | 332 | RegionId: TestRegionID, |
332 | 333 | Pagination: common.Pagination{ |
333 | 334 | PageNumber: 1, |
334 | PageSize: 100, | |
335 | PageSize: 2, | |
335 | 336 | }, |
336 | 337 | //SecurityToken: TestSecurityToken, |
337 | 338 | } |
345 | 346 | } |
346 | 347 | } |
347 | 348 | } |
349 | ||
350 | func Test_CreateDescribeAndDeletiongInstances(t *testing.T) { | |
351 | if TestAccessKeyId == "" || TestAccessKeySecret == "" || TestVpcId == "" || TestVswitchID == "" { | |
352 | t.Skip("missing env") | |
353 | return | |
354 | } | |
355 | client := NewTestClientForDebug() | |
356 | ||
357 | //createInstance | |
358 | createInstanceArgs := &CreateInstanceArgs{ | |
359 | RegionId: TestRegionID, | |
360 | InstanceType: TestInstanceType, | |
361 | VSwitchId: TestVswitchID, | |
362 | ResourceGroupId: TestResourceGroupId, | |
363 | SecurityGroupId: TestSecurityGroupId, | |
364 | ImageId: TestImageId, | |
365 | InstanceChargeType: common.PostPaid, | |
366 | } | |
367 | ||
368 | instanceId, err := client.CreateInstance(createInstanceArgs) | |
369 | if err != nil { | |
370 | t.Fatalf("CreateInstance error %v", err) | |
371 | } | |
372 | ||
373 | //wait for stoppend | |
374 | err = client.WaitForInstance(instanceId, Stopped, 60) | |
375 | if err != nil { | |
376 | t.Fatalf("WaitForInstance Stopped error %v", err) | |
377 | } | |
378 | ||
379 | // start Instance | |
380 | err = client.StartInstance(instanceId) | |
381 | if err != nil { | |
382 | t.Fatalf("StartInstance %s error %v", instanceId, err) | |
383 | } | |
384 | ||
385 | //wait for running | |
386 | err = client.WaitForInstance(instanceId, Running, 0) | |
387 | if err != nil { | |
388 | t.Fatalf("WaitForInstance Running error %v", err) | |
389 | } | |
390 | ||
391 | time.Sleep(10 * time.Second) | |
392 | t.Logf("After 30s ,describe instance %s", instanceId) | |
393 | ||
394 | //describe Instances | |
395 | instanceB, _ := json.Marshal([]string{instanceId}) | |
396 | describeInstancesArgs := &DescribeInstancesArgs{ | |
397 | RegionId: TestRegionID, | |
398 | InstanceIds: string(instanceB), | |
399 | } | |
400 | ||
401 | instances, pageInfo, err := client.DescribeInstances(describeInstancesArgs) | |
402 | if err != nil { | |
403 | t.Fatalf("Error %v", err) | |
404 | } | |
405 | ||
406 | t.Logf("PageInfo = %#v", pageInfo) | |
407 | for _, instance := range instances { | |
408 | t.Logf("Instance = %#v", instance) | |
409 | } | |
410 | ||
411 | time.Sleep(30 * time.Second) | |
412 | t.Logf("After 30s ,delete instance %s", instanceId) | |
413 | ||
414 | //stop instance | |
415 | err = client.StopInstance(instanceId, true) | |
416 | if err != nil { | |
417 | t.Fatalf("StopInstance %s error %v", instanceId, err) | |
418 | } | |
419 | ||
420 | //wait for stoppend | |
421 | err = client.WaitForInstance(instanceId, Stopped, 60) | |
422 | if err != nil { | |
423 | t.Fatalf("WaitForInstance Stopped error %v", err) | |
424 | } | |
425 | t.Logf("Instance %s is stopped successfully.", instanceId) | |
426 | ||
427 | // delete instance | |
428 | err = client.DeleteInstance(instanceId) | |
429 | if err != nil { | |
430 | t.Fatalf("DeleteInstance %s error %v", instanceId, err) | |
431 | } | |
432 | t.Logf("Instance %s is deleted successfully.", instanceId) | |
433 | ||
434 | } |
1 | 1 | |
2 | 2 | import ( |
3 | 3 | "github.com/denverdino/aliyungo/common" |
4 | ) | |
5 | ||
6 | type NatType string | |
7 | ||
8 | const ( | |
9 | NgwNatTypeNormal = NatType("Normal") | |
10 | NgwNatTypeEnhanced = NatType("Enhanced") | |
4 | 11 | ) |
5 | 12 | |
6 | 13 | type BandwidthPackageType struct { |
12 | 19 | type CreateNatGatewayArgs struct { |
13 | 20 | RegionId common.Region |
14 | 21 | VpcId string |
22 | VSwitchId string | |
15 | 23 | Spec string |
16 | 24 | BandwidthPackage []BandwidthPackageType |
17 | 25 | Name string |
18 | 26 | Description string |
27 | NatType NatType | |
19 | 28 | ClientToken string |
20 | 29 | } |
21 | 30 | |
74 | 83 | Spec string |
75 | 84 | Status string |
76 | 85 | VpcId string |
86 | NatType NatType | |
77 | 87 | } |
78 | 88 | |
79 | 89 | type DescribeNatGatewayResponse struct { |
37 | 37 | } |
38 | 38 | } |
39 | 39 | } |
40 | ||
41 | func TestClient_CreateNatGateway(t *testing.T) { | |
42 | client := NewVpcTestClientForDebug() | |
43 | args := &CreateNatGatewayArgs{ | |
44 | RegionId: TestRegionID, | |
45 | VpcId: TestVpcId, | |
46 | VSwitchId: TestVswitchID, | |
47 | NatType: NgwNatTypeEnhanced, | |
48 | } | |
49 | ||
50 | resp, err := client.CreateNatGateway(args) | |
51 | if err != nil { | |
52 | t.Fatalf("Error %++v", err) | |
53 | } else { | |
54 | t.Logf("ngw id :%s", resp.NatGatewayId) | |
55 | } | |
56 | } |
85 | 85 | type EipInstanceType string |
86 | 86 | |
87 | 87 | const ( |
88 | EcsInstance = "EcsInstance" | |
89 | SlbInstance = "SlbInstance" | |
90 | Nat = "Nat" | |
91 | HaVip = "HaVip" | |
88 | EcsInstance = "EcsInstance" | |
89 | SlbInstance = "SlbInstance" | |
90 | Nat = "Nat" | |
91 | HaVip = "HaVip" | |
92 | NetworkInterface = "NetworkInterface" | |
93 | ) | |
94 | ||
95 | type AssociateEipAddressMode string | |
96 | ||
97 | const ( | |
98 | NAT = "NAT" | |
99 | MULTI_BINDED = "MULTI_BINDED" | |
100 | BINDED = "BINDED" | |
92 | 101 | ) |
93 | 102 | |
94 | 103 | type AssociateEipAddressArgs struct { |
95 | AllocationId string | |
96 | InstanceId string | |
97 | InstanceType EipInstanceType | |
104 | AllocationId string | |
105 | InstanceId string | |
106 | InstanceRegionId common.Region | |
107 | InstanceType EipInstanceType | |
108 | PrivateIpAddress string | |
109 | Mode AssociateEipAddressMode | |
98 | 110 | } |
99 | 111 | |
100 | 112 | type AssociateEipAddressResponse struct { |
101 | 113 | common.Response |
102 | 114 | } |
103 | 115 | |
104 | // AssociateEipAddress associates EIP address to VM instance | |
105 | // | |
106 | // You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/network&associateeipaddress | |
116 | // AssociateEipAddress associates EIP address to instance | |
117 | // | |
118 | // You can read doc at https://help.aliyun.com/api/vpc/AssociateEipAddress.html | |
107 | 119 | func (client *Client) AssociateEipAddress(allocationId string, instanceId string) error { |
108 | 120 | args := AssociateEipAddressArgs{ |
109 | 121 | AllocationId: allocationId, |
131 | 143 | type AssociatedInstanceType string |
132 | 144 | |
133 | 145 | const ( |
134 | AssociatedInstanceTypeEcsInstance = AssociatedInstanceType("EcsInstance") | |
135 | AssociatedInstanceTypeSlbInstance = AssociatedInstanceType("SlbInstance") | |
136 | AssociatedInstanceTypeNat = AssociatedInstanceType("Nat") | |
137 | AssociatedInstanceTypeHaVip = AssociatedInstanceType("HaVip") | |
146 | AssociatedInstanceTypeEcsInstance = AssociatedInstanceType("EcsInstance") | |
147 | AssociatedInstanceTypeSlbInstance = AssociatedInstanceType("SlbInstance") | |
148 | AssociatedInstanceTypeNat = AssociatedInstanceType("Nat") | |
149 | AssociatedInstanceTypeHaVip = AssociatedInstanceType("HaVip") | |
150 | AssociatedInstanceTypeNetworkInterface = AssociatedInstanceType("NetworkInterface") | |
138 | 151 | ) |
139 | 152 | |
140 | 153 | type DescribeEipAddressesArgs struct { |
142 | 155 | Status EipStatus //enum Associating | Unassociating | InUse | Available |
143 | 156 | EipAddress string |
144 | 157 | AllocationId string |
145 | AssociatedInstanceType AssociatedInstanceType //enum EcsInstance | SlbInstance | Nat | HaVip | |
158 | AssociatedInstanceType AssociatedInstanceType //enum EcsInstance | SlbInstance | Nat | HaVip | NetworkInterface | |
146 | 159 | AssociatedInstanceId string //绑定的资源的Id。 这是一个过滤器性质的参数,若不指定,则表示不适用该条件对结果进行过滤。 如果要使用该过滤器,必须同时使用AssociatedInstanceType。若InstanceType为EcsInstance,则此处填写ECS实例Id。若InstanceType为SlbInstance,则此处填写VPC类型的私网SLB 的实例ID。若InstanceType为Nat,则此处填写NAT 的实例ID。。若InstanceType为HaVip,则此处填写HaVipId。 |
147 | 160 | common.Pagination |
148 | 161 | } |
157 | 170 | InstanceId string |
158 | 171 | InstanceType string |
159 | 172 | Bandwidth string // Why string |
173 | PrivateIpAddress string | |
160 | 174 | InternetChargeType common.InternetChargeType |
161 | 175 | OperationLocks OperationLocksType |
162 | 176 | AllocationTime util.ISO6801Time |
217 | 231 | } |
218 | 232 | |
219 | 233 | type UnallocateEipAddressArgs struct { |
220 | AllocationId string | |
221 | InstanceId string | |
234 | AllocationId string | |
235 | InstanceId string | |
236 | InstanceType EipInstanceType | |
237 | PrivateIpAddress string | |
222 | 238 | } |
223 | 239 | |
224 | 240 | type UnallocateEipAddressResponse struct { |
235 | 251 | } |
236 | 252 | response := UnallocateEipAddressResponse{} |
237 | 253 | return client.Invoke("UnassociateEipAddress", &args, &response) |
254 | } | |
255 | ||
256 | func (client *Client) NewUnassociateEipAddress(args *UnallocateEipAddressArgs) error { | |
257 | response := UnallocateEipAddressResponse{} | |
258 | return client.Invoke("UnassociateEipAddress", args, &response) | |
238 | 259 | } |
239 | 260 | |
240 | 261 | type ReleaseEipAddressArgs struct { |
84 | 84 | |
85 | 85 | } |
86 | 86 | |
87 | func TestClient_AssociateEipAddress_ENIIP(t *testing.T) { | |
88 | client := NewVpcTestClientForDebug() | |
89 | eipID := "eip-xxx" | |
90 | eniID := "eni-yyy" | |
91 | eniSecIP := "192.168.0.100" | |
92 | region := common.Region("cn-hangzhou") | |
93 | ||
94 | err := client.NewAssociateEipAddress(&AssociateEipAddressArgs{ | |
95 | AllocationId: eipID, | |
96 | InstanceId: eniID, | |
97 | InstanceType: NetworkInterface, | |
98 | PrivateIpAddress: eniSecIP, | |
99 | }) | |
100 | if err != nil { | |
101 | t.Errorf("Failed to associate EIP address: %v", err) | |
102 | } | |
103 | err = client.WaitForEip(region, eipID, EipStatusInUse, DefaultTimeout) | |
104 | if err != nil { | |
105 | t.Errorf("Failed wait associate EIP address: %v", err) | |
106 | } | |
107 | err = client.NewUnassociateEipAddress(&UnallocateEipAddressArgs{ | |
108 | AllocationId: eipID, | |
109 | InstanceId: eniID, | |
110 | InstanceType: NetworkInterface, | |
111 | PrivateIpAddress: eniSecIP, | |
112 | }) | |
113 | if err != nil { | |
114 | t.Errorf("Failed unassociate EIP address: %v", err) | |
115 | } | |
116 | } | |
117 | ||
87 | 118 | func TestClient_DescribeEipAddresses(t *testing.T) { |
88 | 119 | client := NewVpcTestClientForDebug() |
89 | 120 | args := &DescribeEipAddressesArgs{ |
0 | package ecs | |
1 | ||
2 | import "github.com/denverdino/aliyungo/common" | |
3 | ||
4 | type DescribeRouteEntryListArgs struct { | |
5 | RegionId string | |
6 | RouteTableId string | |
7 | DestinationCidrBlock string | |
8 | IpVersion string | |
9 | MaxResult int | |
10 | NextHopId string | |
11 | NextHopType string | |
12 | NextToken string | |
13 | RouteEntryId string | |
14 | RouteEntryName string | |
15 | RouteEntryType string | |
16 | } | |
17 | ||
18 | type DescribeRouteEntryListResponse struct { | |
19 | common.Response | |
20 | NextToken string | |
21 | RouteEntrys struct { | |
22 | RouteEntry []RouteEntry | |
23 | } | |
24 | } | |
25 | ||
26 | type RouteEntry struct { | |
27 | DestinationCidrBlock string | |
28 | IpVersion string | |
29 | RouteEntryId string | |
30 | RouteEntryName string | |
31 | RouteTableId string | |
32 | Status string | |
33 | Type string | |
34 | NextHops struct { | |
35 | NextHop []NextHop | |
36 | } | |
37 | } | |
38 | ||
39 | type NextHop struct { | |
40 | Enabled int | |
41 | Weight int | |
42 | NextHopId string | |
43 | NextHopRegionId string | |
44 | NextHopType string | |
45 | NextHopRelatedInfo NextHopRelatedInfo | |
46 | } | |
47 | ||
48 | type NextHopRelatedInfo struct { | |
49 | RegionId string | |
50 | InstanceId string | |
51 | InstanceType string | |
52 | } | |
53 | ||
54 | // DescribeRouteEntryList describes route entries | |
55 | // | |
56 | func (client *Client) DescribeRouteEntryList(args *DescribeRouteEntryListArgs) (*DescribeRouteEntryListResponse, error) { | |
57 | response := &DescribeRouteEntryListResponse{} | |
58 | err := client.Invoke("DescribeRouteEntryList", args, &response) | |
59 | return response, err | |
60 | } |
0 | package ecs | |
1 | ||
2 | import ( | |
3 | "testing" | |
4 | ) | |
5 | ||
6 | func TestClient_DescribeRouteEntry(t *testing.T) { | |
7 | client := NewVpcTestClientForDebug() | |
8 | ||
9 | nextHopId := "i-xxxx" | |
10 | destinationCidrBlock := "172.xxx/x" | |
11 | args := &DescribeRouteEntryListArgs{ | |
12 | RegionId: "cn-hangzhou", | |
13 | RouteTableId: "vtb-xxxxx", | |
14 | DestinationCidrBlock: destinationCidrBlock, | |
15 | NextHopId: nextHopId, | |
16 | RouteEntryType: "Custom", | |
17 | } | |
18 | ||
19 | response, err := client.DescribeRouteEntryList(args) | |
20 | ||
21 | if err != nil { | |
22 | t.Fatalf("Error %++v", err) | |
23 | } else { | |
24 | t.Logf("Result %++v", response) | |
25 | } | |
26 | } |
99 | 99 | type NextHopType string |
100 | 100 | |
101 | 101 | const ( |
102 | NextHopIntance = NextHopType("Instance") //Default | |
103 | NextHopTunnel = NextHopType("Tunnel") | |
104 | NextHopTunnelRouterInterface = NextHopType("RouterInterface") | |
102 | NextHopInstance = NextHopType("Instance") //Default | |
103 | NextHopHaVip = NextHopType("HaVip") | |
104 | NextHopRouterInterface = NextHopType("RouterInterface") | |
105 | NextHopNetworkInterface = NextHopType("NetworkInterface") | |
106 | NextHopVpnGateway = NextHopType("VpnGateway") | |
107 | NextHopIPv6Gateway = NextHopType("IPv6Gateway") | |
108 | NextHopTunnel = NextHopType("Tunnel") | |
105 | 109 | ) |
106 | 110 | |
107 | 111 | type CreateRouteEntryArgs struct { |
10 | 10 | createArgs := CreateRouteEntryArgs{ |
11 | 11 | RouteTableId: routeTableId, |
12 | 12 | DestinationCidrBlock: cidrBlock, |
13 | NextHopType: NextHopIntance, | |
13 | NextHopType: NextHopInstance, | |
14 | 14 | NextHopId: instanceId, |
15 | 15 | ClientToken: client.GenerateClientToken(), |
16 | 16 | } |
237 | 237 | for { |
238 | 238 | interfaces, err := client.DescribeRouterInterfaces(&DescribeRouterInterfacesArgs{ |
239 | 239 | RegionId: regionId, |
240 | Filter: []Filter{Filter{Key: "RouterInterfaceId", Value: []string{interfaceId}}}, | |
240 | Filter: []Filter{{Key: "RouterInterfaceId", Value: []string{interfaceId}}}, | |
241 | 241 | }) |
242 | 242 | if err != nil { |
243 | 243 | return err |
6 | 6 | |
7 | 7 | type NicType string |
8 | 8 | type Direction string |
9 | type SecurityGroupType string | |
9 | 10 | |
10 | 11 | const ( |
11 | 12 | NicTypeInternet = NicType("internet") |
14 | 15 | DirectionIngress = Direction("ingress") |
15 | 16 | DirectionEgress = Direction("egress") |
16 | 17 | DirectionAll = Direction("all") |
18 | ||
19 | SecurityGroupTypeNormal = SecurityGroupType("normal") | |
20 | SecurityGroupTypeEnterprise = SecurityGroupType("enterprise") | |
17 | 21 | ) |
18 | 22 | |
19 | 23 | type IpProtocol string |
91 | 95 | } |
92 | 96 | |
93 | 97 | type DescribeSecurityGroupsArgs struct { |
94 | RegionId common.Region | |
95 | VpcId string | |
98 | RegionId common.Region | |
99 | VpcId string | |
100 | SecurityGroupIds []string | |
96 | 101 | common.Pagination |
97 | 102 | } |
98 | 103 | |
103 | 108 | SecurityGroupName string |
104 | 109 | Description string |
105 | 110 | VpcId string |
111 | SecurityGroupType SecurityGroupType // normal|enterprise | |
112 | ServiceManaged bool | |
106 | 113 | CreationTime util.ISO6801Time |
107 | 114 | } |
108 | 115 |
0 | 0 | package ecs |
1 | 1 | |
2 | 2 | import ( |
3 | "os" | |
4 | "strings" | |
3 | 5 | "testing" |
4 | 6 | |
5 | 7 | "github.com/denverdino/aliyungo/common" |
38 | 40 | t.Logf("SecurityGroup Attribute: %++v", sga) |
39 | 41 | |
40 | 42 | } |
43 | } | |
44 | } | |
45 | ||
46 | func TestSecurityGroups_BatchQuery(t *testing.T) { | |
47 | ||
48 | client := NewTestClient() | |
49 | arg := DescribeSecurityGroupsArgs{ | |
50 | RegionId: common.Region(os.Getenv("RegionId")), | |
51 | SecurityGroupIds: strings.Split(os.Getenv("SecurityGroupIDs"), ","), | |
52 | } | |
53 | ||
54 | sgs, _, err := client.DescribeSecurityGroups(&arg) | |
55 | if err != nil { | |
56 | t.Errorf("Failed to DescribeSecurityGroups, error:%++v", err) | |
57 | } | |
58 | for _, sg := range sgs { | |
59 | t.Logf("SecurityGroup: %++v", sg) | |
41 | 60 | } |
42 | 61 | } |
43 | 62 |
125 | 125 | if err != nil { |
126 | 126 | return err |
127 | 127 | } |
128 | if snapshots == nil || len(snapshots) == 0 { | |
128 | if len(snapshots) == 0 { | |
129 | 129 | return common.GetClientErrorFromString("Not found") |
130 | 130 | } |
131 | 131 | if snapshots[0].Progress == "100%" { |
0 | 0 | package ecs |
1 | 1 | |
2 | import "github.com/denverdino/aliyungo/common" | |
2 | import ( | |
3 | "time" | |
4 | ||
5 | "github.com/denverdino/aliyungo/common" | |
6 | ) | |
7 | ||
8 | type SnatEntryStatus string | |
9 | ||
10 | const ( | |
11 | SnatEntryStatusPending = SnatEntryStatus("Pending") | |
12 | SnatEntryStatusAvailable = SnatEntryStatus("Available") | |
13 | ) | |
3 | 14 | |
4 | 15 | type CreateSnatEntryArgs struct { |
5 | 16 | RegionId common.Region |
6 | 17 | SnatTableId string |
7 | 18 | SourceVSwitchId string |
8 | 19 | SnatIp string |
20 | SourceCIDR string | |
9 | 21 | } |
10 | 22 | |
11 | 23 | type CreateSnatEntryResponse struct { |
20 | 32 | SnatTableId string |
21 | 33 | SourceCIDR string |
22 | 34 | SourceVSwitchId string |
23 | Status string | |
35 | Status SnatEntryStatus | |
24 | 36 | } |
25 | 37 | |
26 | 38 | type DescribeSnatTableEntriesArgs struct { |
27 | RegionId common.Region | |
28 | SnatTableId string | |
39 | RegionId common.Region | |
40 | SnatTableId string | |
41 | SnatEntryId string | |
42 | SnatEntryName string | |
43 | SnatIp string | |
44 | SourceCIDR string | |
45 | SourceVSwitchId string | |
29 | 46 | common.Pagination |
30 | 47 | } |
31 | 48 | |
38 | 55 | } |
39 | 56 | |
40 | 57 | type ModifySnatEntryArgs struct { |
41 | RegionId common.Region | |
42 | SnatTableId string | |
43 | SnatEntryId string | |
44 | SnatIp string | |
58 | RegionId common.Region | |
59 | SnatTableId string | |
60 | SnatEntryId string | |
61 | SnatIp string | |
62 | SnatEntryName string | |
45 | 63 | } |
46 | 64 | |
47 | 65 | type ModifySnatEntryResponse struct { |
100 | 118 | err := client.Invoke("DeleteSnatEntry", args, &response) |
101 | 119 | return err |
102 | 120 | } |
121 | ||
122 | // WaitForSnatEntryAvailable waits for SnatEntry to available status | |
123 | func (client *Client) WaitForSnatEntryAvailable(regionId common.Region, snatTableId, snatEntryId string, timeout int) error { | |
124 | if timeout <= 0 { | |
125 | timeout = DefaultTimeout | |
126 | } | |
127 | ||
128 | args := &DescribeSnatTableEntriesArgs{ | |
129 | RegionId: regionId, | |
130 | SnatTableId: snatTableId, | |
131 | SnatEntryId: snatEntryId, | |
132 | } | |
133 | ||
134 | for { | |
135 | snatEntries, _, err := client.DescribeSnatTableEntries(args) | |
136 | if err != nil { | |
137 | return err | |
138 | } | |
139 | ||
140 | if len(snatEntries) == 0 { | |
141 | return common.GetClientErrorFromString("Not found") | |
142 | } | |
143 | if snatEntries[0].Status == SnatEntryStatusAvailable { | |
144 | break | |
145 | } | |
146 | ||
147 | timeout = timeout - DefaultWaitForInterval | |
148 | if timeout <= 0 { | |
149 | return common.GetClientErrorFromString("Timeout") | |
150 | } | |
151 | time.Sleep(DefaultWaitForInterval * time.Second) | |
152 | } | |
153 | return nil | |
154 | } |
13 | 13 | t.Fatalf("Failed to DescribeBandwidthPackages: %v", err) |
14 | 14 | } |
15 | 15 | } |
16 | ||
17 | func TestCreateSnatEntryWithSourceCIDR(t *testing.T) { | |
18 | client := NewTestClient() | |
19 | args := CreateSnatEntryArgs{ | |
20 | RegionId: "cn-beijing", | |
21 | SnatTableId: "stb-xxx", | |
22 | SnatIp: "47.XX.XX.98", | |
23 | SourceCIDR: "192.168.1.1/32", | |
24 | } | |
25 | ||
26 | _, err := client.CreateSnatEntry(&args) | |
27 | if err != nil { | |
28 | t.Errorf("failed to CreateSnatEntry with SourceCIDR: %v", err) | |
29 | } | |
30 | } |
75 | 75 | VSwitchIds struct { |
76 | 76 | VSwitchId []string |
77 | 77 | } |
78 | CidrBlock string | |
79 | VRouterId string | |
80 | Description string | |
81 | IsDefault bool | |
82 | CreationTime util.ISO6801Time | |
78 | CidrBlock string | |
79 | VRouterId string | |
80 | Description string | |
81 | IsDefault bool | |
82 | CreationTime util.ISO6801Time | |
83 | SecondaryCidrBlocks struct { | |
84 | SecondaryCidrBlock []string | |
85 | } | |
86 | RouterTableIds struct { | |
87 | RouterTableIds []string | |
88 | } | |
83 | 89 | } |
84 | 90 | |
85 | 91 | type DescribeVpcsResponse struct { |
163 | 163 | t.Logf("Instance %s is created successfully.", instanceId) |
164 | 164 | instance, err := client.DescribeInstanceAttribute(instanceId) |
165 | 165 | t.Logf("Instance: %++v %v", instance, err) |
166 | ||
166 | 167 | err = client.WaitForInstance(instanceId, Stopped, 0) |
168 | if err != nil { | |
169 | t.Errorf("Failed to wait instance to stopped %s: %v", instanceId, err) | |
170 | } | |
167 | 171 | |
168 | 172 | err = client.StartInstance(instanceId) |
169 | 173 | if err != nil { |
1 | 1 | |
2 | 2 | import ( |
3 | 3 | "encoding/base64" |
4 | ||
5 | 4 | "github.com/denverdino/aliyungo/common" |
6 | 5 | "github.com/denverdino/aliyungo/ecs" |
7 | 6 | ) |
89 | 88 | CreationTime string |
90 | 89 | InternetMaxBandwidthIn int |
91 | 90 | InternetMaxBandwidthOut int |
91 | SystemDiskSize int | |
92 | 92 | SystemDiskCategory string |
93 | 93 | DataDisks struct { |
94 | 94 | DataDisk []DataDiskItemType |
166 | 166 | } |
167 | 167 | return &response, nil |
168 | 168 | } |
169 | ||
170 | type ModifyScalingConfigurationRequest struct { | |
171 | ScalingConfigurationId string | |
172 | IoOptimized string | |
173 | DataDisk []DataDisk | |
174 | SpotStrategy string | |
175 | SpotPriceLimit []SpotPriceLimit | |
176 | ScalingConfigurationName string | |
177 | InstanceName string | |
178 | HostName string | |
179 | ImageId string | |
180 | ImageName string | |
181 | InstanceTypes []string | |
182 | Cpu int | |
183 | Memory int | |
184 | InternetChargeType string | |
185 | InternetMaxBandwidthOut int | |
186 | SystemDisk SystemDisk | |
187 | LoadBalancerWeight string | |
188 | UserData string | |
189 | KeyPairName string | |
190 | RamRoleName string | |
191 | PasswordInherit string | |
192 | Tags string | |
193 | DeploymentSetId string | |
194 | SecurityGroupId string | |
195 | Override bool | |
196 | ResourceGroupId string | |
197 | SecurityGroupIds []string | |
198 | HpcClusterId string | |
199 | ||
200 | InstanceDescription string | |
201 | Ipv6AddressCount int | |
202 | ||
203 | CreditSpecification string | |
204 | ImageFamily string | |
205 | DedicatedHostId string | |
206 | Affinity string | |
207 | Tenancy string | |
208 | } | |
209 | ||
210 | type DataDisk struct { | |
211 | Size int | |
212 | SnapshotId string | |
213 | Category string | |
214 | Device string | |
215 | DeleteWithInstance bool | |
216 | Encrypted bool | |
217 | KMSKeyId string | |
218 | DiskName string | |
219 | Description string | |
220 | AutoSnapshotPolicyId string | |
221 | } | |
222 | ||
223 | type SpotPriceLimit struct { | |
224 | InstanceType string | |
225 | PriceLimit float32 | |
226 | } | |
227 | ||
228 | type SystemDisk struct { | |
229 | Category string | |
230 | Size int | |
231 | DiskName string | |
232 | Description string | |
233 | AutoSnapshotPolicyId string | |
234 | } | |
235 | ||
236 | type ModifyScalingConfigurationResponse struct { | |
237 | common.Response | |
238 | } | |
239 | ||
240 | func (client *Client) ModifyScalingConfiguration(args *ModifyScalingConfigurationRequest) (resp *ModifyScalingConfigurationResponse, err error) { | |
241 | response := ModifyScalingConfigurationResponse{} | |
242 | err = client.InvokeByFlattenMethod("ModifyScalingConfiguration", args, &response) | |
243 | ||
244 | if err != nil { | |
245 | return nil, err | |
246 | } | |
247 | return &response, nil | |
248 | } |
14 | 14 | InService = LifecycleState("InService") |
15 | 15 | Pending = LifecycleState("Pending") |
16 | 16 | Removing = LifecycleState("Removing") |
17 | ) | |
18 | ||
19 | type MultiAZPolicy string | |
20 | ||
21 | const ( | |
22 | MultiAZPolicyPriority = MultiAZPolicy("PRIORITY") | |
23 | MultiAZPolicyCostOptimized = MultiAZPolicy("COST_OPTIMIZED") | |
24 | MultiAZPolicyBalance = MultiAZPolicy("BALANCE") | |
17 | 25 | ) |
18 | 26 | |
19 | 27 | type CreateScalingGroupArgs struct { |
26 | 34 | // NOTE: Set MinSize, MaxSize and DefaultCooldown type to int pointer to distinguish zero value from unset value. |
27 | 35 | MinSize *int |
28 | 36 | MaxSize *int |
37 | MultiAZPolicy MultiAZPolicy | |
29 | 38 | DefaultCooldown *int |
30 | 39 | RemovalPolicy common.FlattenArray |
31 | 40 | DBInstanceIds string |
337 | 346 | } |
338 | 347 | return nil |
339 | 348 | } |
349 | ||
350 | type DescribeScalingActivitiesRequest struct { | |
351 | ScalingActivityId []string | |
352 | ScalingGroupId string | |
353 | StatusCode string | |
354 | RegionId common.Region | |
355 | common.Pagination | |
356 | } | |
357 | ||
358 | type DescribeScalingActivitiesResponse struct { | |
359 | common.PaginationResult | |
360 | common.Response | |
361 | ScalingActivities struct { | |
362 | ScalingActivity []ScalingActivity | |
363 | } | |
364 | } | |
365 | ||
366 | type ScalingActivity struct { | |
367 | AttachedCapacity int | |
368 | AutoCreatedCapacity int | |
369 | Cause string | |
370 | Description string | |
371 | EndTime string | |
372 | Progress int | |
373 | ScalingActivityId string | |
374 | ScalingGroupId string | |
375 | ScalingInstanceNumber int | |
376 | StartTime string | |
377 | StatusCode string | |
378 | StatusMessage string | |
379 | TotalCapacity int | |
380 | } | |
381 | ||
382 | func (client *Client) DescribeScalingActivities(args *DescribeScalingActivitiesRequest) (resp *DescribeScalingActivitiesResponse, err error) { | |
383 | response := DescribeScalingActivitiesResponse{} | |
384 | err = client.InvokeByFlattenMethod("DescribeScalingActivities", args, &response) | |
385 | ||
386 | if err != nil { | |
387 | return nil, err | |
388 | } | |
389 | return &response, nil | |
390 | } |
0 | 0 | package ess |
1 | 1 | |
2 | 2 | import ( |
3 | "fmt" | |
3 | 4 | "testing" |
4 | 5 | |
5 | 6 | "github.com/denverdino/aliyungo/common" |
74 | 75 | } |
75 | 76 | t.Logf("Instance %s is deleted successfully.", instanceId) |
76 | 77 | } |
78 | ||
79 | func TestEssScalingActivity(t *testing.T) { | |
80 | ||
81 | client := NewTestClient(common.Region(RegionId)) | |
82 | id := "asg-uf68jfxw7gqlao0wlc94" | |
83 | result, err := client.DescribeScalingActivities( | |
84 | &DescribeScalingActivitiesRequest{ | |
85 | ScalingGroupId: id, | |
86 | RegionId: common.Shanghai, | |
87 | }, | |
88 | ) | |
89 | if err != nil { | |
90 | t.Errorf("get activity %s: %v", id, err) | |
91 | } | |
92 | fmt.Printf("%+v\n", result) | |
93 | t.Logf("get activity succeed by id %s.", id) | |
94 | } |
0 | module github.com/denverdino/aliyungo | |
1 | ||
2 | go 1.15 | |
3 | ||
4 | require ( | |
5 | github.com/golang/protobuf v1.5.2 // indirect | |
6 | github.com/magiconair/properties v1.8.6 // indirect | |
7 | github.com/opentracing/opentracing-go v1.2.0 // indirect | |
8 | github.com/pkg/errors v0.9.1 // indirect | |
9 | github.com/stretchr/testify v1.7.1 // indirect | |
10 | github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect | |
11 | github.com/uber/jaeger-lib v2.4.1+incompatible // indirect | |
12 | go.uber.org/atomic v1.9.0 // indirect | |
13 | golang.org/x/text v0.3.7 // indirect | |
14 | ) |
0 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= | |
1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | |
2 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | |
3 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | |
4 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= | |
5 | github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= | |
6 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= | |
7 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | |
8 | github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= | |
9 | github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= | |
10 | github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= | |
11 | github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= | |
12 | github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= | |
13 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= | |
14 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | |
15 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | |
16 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | |
17 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | |
18 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | |
19 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | |
20 | github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= | |
21 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | |
22 | github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= | |
23 | github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= | |
24 | github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= | |
25 | github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= | |
26 | go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= | |
27 | go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= | |
28 | golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= | |
29 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= | |
30 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | |
31 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |
32 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= | |
33 | google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= | |
34 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= | |
35 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | |
36 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= | |
37 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
5 | 5 | client := NewTestClientForDebug() |
6 | 6 | |
7 | 7 | args := &DescribeRegionsArgs{ |
8 | //RegionId: common.Beijing, | |
8 | //RegionId: common.Beijing, | |
9 | 9 | } |
10 | 10 | |
11 | 11 | regions, err := client.DescribeRegions(args) |
13 | 13 | "encoding/json" |
14 | 14 | "reflect" |
15 | 15 | |
16 | "os" | |
17 | ||
16 | 18 | "github.com/denverdino/aliyungo/util" |
17 | "os" | |
18 | 19 | ) |
19 | 20 | |
20 | 21 | const ( |
43 | 44 | VSWITCH_CIDR_BLOCK = "vswitch-cidr-block" |
44 | 45 | VSWITCH_ID = "vswitch-id" |
45 | 46 | ZONE = "zone-id" |
46 | RAM_SECURITY = "Ram/security-credentials" | |
47 | RAM_SECURITY = "ram/security-credentials" | |
47 | 48 | ) |
48 | 49 | |
49 | 50 | type IMetaDataRequest interface { |
350 | 351 | func (vpc *MetaDataRequest) Decode(data string, api interface{}) error { |
351 | 352 | if data == "" { |
352 | 353 | url, _ := vpc.Url() |
353 | return errors.New(fmt.Sprintf("metadata: alivpc decode data must not be nil. url=[%s]\n", url)) | |
354 | return fmt.Errorf("metadata: alivpc decode data must not be nil. url=[%s]\n", url) | |
354 | 355 | } |
355 | 356 | switch api.(type) { |
356 | 357 | case *ResultList: |
359 | 360 | case *RoleAuth: |
360 | 361 | return json.Unmarshal([]byte(data), api) |
361 | 362 | default: |
362 | return errors.New(fmt.Sprintf("metadata: unknow type to decode, type=%s\n", reflect.TypeOf(api))) | |
363 | return fmt.Errorf("metadata: unknow type to decode, type=%s\n", reflect.TypeOf(api)) | |
363 | 364 | } |
364 | 365 | } |
365 | 366 |
21 | 21 | client.debug = debug |
22 | 22 | } |
23 | 23 | |
24 | // SetTransport sets transport to the http client | |
25 | func (client *Client) SetTransport(transport http.RoundTripper) { | |
26 | if client.httpClient == nil { | |
27 | client.httpClient = &http.Client{} | |
28 | } | |
29 | client.httpClient.Transport = transport | |
30 | } | |
31 | ||
24 | 32 | func NewClient(accessKeyId, accessKeySecret, endpoint string) (client *Client) { |
25 | 33 | client = &Client{ |
26 | 34 | AccessKeyId: accessKeyId, |
43 | 43 | canonicalizedResource := req.path |
44 | 44 | var paramNames []string |
45 | 45 | if req.params != nil && len(req.params) > 0 { |
46 | for k, _ := range req.params { | |
46 | for k := range req.params { | |
47 | 47 | paramNames = append(paramNames, k) |
48 | 48 | } |
49 | 49 | sort.Strings(paramNames) |
61 | 61 | func canonicalizeHeader(headers map[string]string) string { |
62 | 62 | var canonicalizedHeaders []string |
63 | 63 | |
64 | for k, _ := range headers { | |
64 | for k := range headers { | |
65 | 65 | if lower := strings.ToLower(k); strings.HasPrefix(lower, HeaderMNSPrefix) { |
66 | 66 | canonicalizedHeaders = append(canonicalizedHeaders, lower) |
67 | 67 | } |
36 | 36 | Internal bool |
37 | 37 | Secure bool |
38 | 38 | ConnectTimeout time.Duration |
39 | Transport http.RoundTripper | |
39 | 40 | |
40 | 41 | endpoint string |
41 | 42 | debug bool |
56 | 57 | // Options struct |
57 | 58 | // |
58 | 59 | type Options struct { |
59 | ServerSideEncryption bool | |
60 | Meta map[string][]string | |
61 | ContentEncoding string | |
62 | CacheControl string | |
63 | ContentMD5 string | |
64 | ContentDisposition string | |
60 | ServerSideEncryption bool | |
61 | ServerSideEncryptionKeyID string | |
62 | ||
63 | Meta map[string][]string | |
64 | ContentEncoding string | |
65 | CacheControl string | |
66 | ContentMD5 string | |
67 | ContentDisposition string | |
65 | 68 | //Range string |
66 | 69 | //Expires int |
67 | 70 | } |
71 | 74 | CopySourceOptions string |
72 | 75 | MetadataDirective string |
73 | 76 | //ContentType string |
77 | ||
78 | ServerSideEncryption bool | |
79 | ServerSideEncryptionKeyID string | |
74 | 80 | } |
75 | 81 | |
76 | 82 | // CopyObjectResult is the output from a Copy request |
490 | 496 | |
491 | 497 | // addHeaders adds o's specified fields to headers |
492 | 498 | func (o Options) addHeaders(headers http.Header) { |
493 | if o.ServerSideEncryption { | |
499 | if len(o.ServerSideEncryptionKeyID) != 0 { | |
500 | headers.Set("x-oss-server-side-encryption", "KMS") | |
501 | headers.Set("x-oss-server-side-encryption-key-id", o.ServerSideEncryptionKeyID) | |
502 | } else if o.ServerSideEncryption { | |
494 | 503 | headers.Set("x-oss-server-side-encryption", "AES256") |
495 | 504 | } |
496 | 505 | if len(o.ContentEncoding) != 0 { |
515 | 524 | |
516 | 525 | // addHeaders adds o's specified fields to headers |
517 | 526 | func (o CopyOptions) addHeaders(headers http.Header) { |
527 | if len(o.ServerSideEncryptionKeyID) != 0 { | |
528 | headers.Set("x-oss-server-side-encryption", "KMS") | |
529 | headers.Set("x-oss-server-side-encryption-key-id", o.ServerSideEncryptionKeyID) | |
530 | } else if o.ServerSideEncryption { | |
531 | headers.Set("x-oss-server-side-encryption", "AES256") | |
532 | } | |
533 | ||
518 | 534 | if len(o.MetadataDirective) != 0 { |
519 | 535 | headers.Set("x-oss-metadata-directive", o.MetadataDirective) |
520 | 536 | } |
833 | 849 | // to retrieve the object at path. The signature is valid until expires. |
834 | 850 | func (b *Bucket) SignedURLWithArgs(path string, expires time.Time, params url.Values, headers http.Header) string { |
835 | 851 | return b.SignedURLWithMethod("GET", path, expires, params, headers) |
852 | } | |
853 | ||
854 | func (b *Bucket) SignedURLWithMethodForAssumeRole(method, path string, expires time.Time, params url.Values, headers http.Header) string { | |
855 | var uv = url.Values{} | |
856 | if params != nil { | |
857 | uv = params | |
858 | } | |
859 | if len(b.Client.SecurityToken) != 0 { | |
860 | uv.Set("security-token", b.Client.SecurityToken) | |
861 | } | |
862 | return b.SignedURLWithMethod(method, path, expires, params, headers) | |
836 | 863 | } |
837 | 864 | |
838 | 865 | // SignedURLWithMethod returns a signed URL that allows anyone holding the URL |
1023 | 1050 | func (client *Client) prepare(req *request) error { |
1024 | 1051 | // Copy so they can be mutated without affecting on retries. |
1025 | 1052 | headers := copyHeader(req.headers) |
1026 | if len(client.SecurityToken) != 0 { | |
1053 | // security-token should be in either Params or Header, cannot be in both | |
1054 | if len(req.params.Get("security-token")) == 0 && len(client.SecurityToken) != 0 { | |
1027 | 1055 | headers.Set("x-oss-security-token", client.SecurityToken) |
1028 | 1056 | } |
1029 | 1057 | |
1161 | 1189 | }, |
1162 | 1190 | Timeout: req.timeout, |
1163 | 1191 | } |
1192 | if client.Transport != nil { | |
1193 | c.Transport = client.Transport | |
1194 | } | |
1164 | 1195 | |
1165 | 1196 | return client.doHttpRequest(c, hreq, resp) |
1166 | 1197 | } |
5 | 5 | "io/ioutil" |
6 | 6 | "math/rand" |
7 | 7 | "net/http" |
8 | "os" | |
8 | "net/url" | |
9 | 9 | "strconv" |
10 | 10 | "sync" |
11 | ||
11 | 12 | //"net/http" |
12 | 13 | "testing" |
13 | 14 | "time" |
22 | 23 | ) |
23 | 24 | |
24 | 25 | func init() { |
25 | AccessKeyId := os.Getenv("AccessKeyId") | |
26 | AccessKeySecret := os.Getenv("AccessKeySecret") | |
27 | if len(AccessKeyId) != 0 && len(AccessKeySecret) != 0 { | |
28 | client = oss.NewOSSClient(TestRegion, false, AccessKeyId, AccessKeySecret, false) | |
29 | } else { | |
30 | client = oss.NewOSSClient(TestRegion, false, TestAccessKeyId, TestAccessKeySecret, false) | |
31 | } | |
32 | ||
33 | assumeRoleClient = oss.NewOSSClientForAssumeRole(TestRegion, false, TestAccessKeyId, TestAccessKeySecret, TestSecurityToken, false) | |
26 | client = oss.NewOSSClient(TestRegion, false, TestAccessKeyID, TestAccessKeySecret, false) | |
27 | assumeRoleClient = oss.NewOSSClientForAssumeRole(TestRegion, false, TestAccessKeyID, TestAccessKeySecret, TestSecurityToken, false) | |
34 | 28 | assumeRoleClient.SetDebug(true) |
35 | 29 | } |
36 | 30 | |
97 | 91 | } |
98 | 92 | } |
99 | 93 | |
100 | func aTestGetNotFound(t *testing.T) { | |
94 | func TestGetNotFound(t *testing.T) { | |
101 | 95 | |
102 | 96 | b := client.Bucket("non-existent-bucket") |
103 | 97 | _, err := b.Get("non-existent") |
123 | 117 | } |
124 | 118 | } |
125 | 119 | |
120 | func TestPutObjectWithSSE(t *testing.T) { | |
121 | const DISPOSITION = "attachment; filename=\"0x1a2b3c.jpg\"" | |
122 | ||
123 | b := client.Bucket(TestBucket) | |
124 | err := b.Put("name-sse", []byte("content"), "content-type", oss.Private, oss.Options{ | |
125 | ContentDisposition: DISPOSITION, | |
126 | ServerSideEncryptionKeyID: TestServerSideEncryptionKeyID, | |
127 | }) | |
128 | if err != nil { | |
129 | t.Errorf("Failed for Put: %v", err) | |
130 | } | |
131 | } | |
132 | ||
133 | func TestPutCopyWithSSE(t *testing.T) { | |
134 | b := client.Bucket(TestBucket) | |
135 | t.Log("Source: ", b.Path("name-sse")) | |
136 | res, err := b.PutCopy("newname-sse", oss.Private, oss.CopyOptions{ | |
137 | ServerSideEncryptionKeyID: TestServerSideEncryptionKeyID, | |
138 | }, | |
139 | b.Path("name")) | |
140 | if err == nil { | |
141 | t.Logf("Copy result: %v", res) | |
142 | } else { | |
143 | t.Errorf("Failed for PutCopy: %v", err) | |
144 | } | |
145 | } | |
146 | ||
126 | 147 | func TestList(t *testing.T) { |
127 | 148 | |
128 | 149 | b := client.Bucket(TestBucket) |
129 | 150 | |
130 | 151 | data, err := b.List("n", "", "", 0) |
131 | if err != nil || len(data.Contents) != 2 { | |
152 | if err != nil || len(data.Contents) != 4 { | |
132 | 153 | t.Errorf("Failed for List: %v", err) |
133 | 154 | } else { |
134 | 155 | t.Logf("Contents = %++v", data) |
240 | 261 | resp.Body.Close() |
241 | 262 | } |
242 | 263 | |
264 | func TestSignedURLWithArgsWithTrafficLimits(t *testing.T) { | |
265 | b := client.Bucket(TestBucket) | |
266 | expires := time.Now().Add(20 * time.Minute) | |
267 | url := b.SignedURLWithArgs("largefile", expires, url.Values{ | |
268 | "x-oss-traffic-limit": []string{strconv.FormatInt(5*8<<20, 10)}}, | |
269 | nil) | |
270 | resp, err := http.Get(url) | |
271 | t.Logf("Large file response headers: %++v", resp.Header) | |
272 | ||
273 | if err != nil { | |
274 | t.Fatalf("Failed for GetResponseWithHeaders: %v", err) | |
275 | } | |
276 | data, err := ioutil.ReadAll(resp.Body) | |
277 | ||
278 | if err != nil { | |
279 | t.Errorf("Failed for Read file: %v", err) | |
280 | } | |
281 | ||
282 | if len(data) != int(_fileSize) { | |
283 | t.Errorf("Incorrect length for Read with offset: %v", len(data)) | |
284 | } | |
285 | resp.Body.Close() | |
286 | } | |
287 | ||
243 | 288 | func TestCopyLargeFile(t *testing.T) { |
244 | 289 | b := client.Bucket(TestBucket) |
245 | 290 | err := b.CopyLargeFile("largefile", "largefile2", "application/octet-stream", oss.Private, oss.Options{}) |
271 | 316 | t.Fatalf("Failed for Get file: %v", err) |
272 | 317 | } |
273 | 318 | |
274 | if bytes.Compare(bytes1, bytes2) != 0 { | |
319 | if !bytes.Equal(bytes1, bytes2) { | |
275 | 320 | t.Fatal("The result should be equal") |
276 | 321 | } |
277 | 322 | } |
307 | 352 | t.Fatalf("Failed for Get file: %v", err) |
308 | 353 | } |
309 | 354 | |
310 | if bytes.Compare(bytes1, bytes2) != 0 { | |
355 | if !bytes.Equal(bytes1, bytes2) { | |
311 | 356 | t.Fatal("The result should be equal") |
312 | 357 | } |
313 | 358 | } |
370 | 415 | func TestDelMultiObjects(t *testing.T) { |
371 | 416 | |
372 | 417 | b := client.Bucket(TestBucket) |
373 | objects := []oss.Object{oss.Object{Key: "newname"}} | |
418 | objects := []oss.Object{ | |
419 | {Key: "newname"}, | |
420 | {Key: "name-sse"}, | |
421 | {Key: "newname-sse"}, | |
422 | } | |
374 | 423 | err := b.DelMulti(oss.Delete{ |
375 | 424 | Quiet: false, |
376 | 425 | Objects: objects, |
15 | 15 | // |
16 | 16 | |
17 | 17 | var ( |
18 | TestAccessKeyId = os.Getenv("AccessKeyId") | |
18 | TestAccessKeyID = os.Getenv("AccessKeyId") | |
19 | 19 | TestAccessKeySecret = os.Getenv("AccessKeySecret") |
20 | 20 | TestSecurityToken = os.Getenv("SecurityToken") |
21 | 21 | TestRegion = oss.Region(os.Getenv("RegionId")) |
22 | ||
23 | TestServerSideEncryptionKeyID = os.Getenv("ServerSideEncryptionKeyId") | |
22 | 24 | ) |
26 | 26 | MEEast1 = Region("oss-me-east-1") |
27 | 27 | |
28 | 28 | EUCentral1 = Region("oss-eu-central-1") |
29 | EUWest1 = Region("oss-eu-west-1") | |
29 | 30 | |
30 | 31 | DefaultRegion = Hangzhou |
31 | 32 | ) |
12 | 12 | |
13 | 13 | var ossParamsToSign = map[string]bool{ |
14 | 14 | "acl": true, |
15 | "append": true, | |
16 | "bucketInfo": true, | |
17 | "cname": true, | |
18 | "comp": true, | |
19 | "cors": true, | |
15 | 20 | "delete": true, |
21 | "endTime": true, | |
22 | "img": true, | |
23 | "lifecycle": true, | |
24 | "live": true, | |
16 | 25 | "location": true, |
17 | 26 | "logging": true, |
18 | "notification": true, | |
27 | "objectMeta": true, | |
19 | 28 | "partNumber": true, |
20 | "policy": true, | |
21 | "requestPayment": true, | |
22 | "torrent": true, | |
23 | "uploadId": true, | |
24 | "uploads": true, | |
25 | "versionId": true, | |
26 | "versioning": true, | |
27 | "versions": true, | |
28 | "response-content-type": true, | |
29 | "response-content-language": true, | |
30 | "response-expires": true, | |
29 | "position": true, | |
30 | "qos": true, | |
31 | "referer": true, | |
32 | "replication": true, | |
33 | "replicationLocation": true, | |
34 | "replicationProgress": true, | |
31 | 35 | "response-cache-control": true, |
32 | 36 | "response-content-disposition": true, |
33 | 37 | "response-content-encoding": true, |
34 | "bucketInfo": true, | |
38 | "response-content-language": true, | |
39 | "response-content-type": true, | |
40 | "response-expires": true, | |
41 | "security-token": true, | |
42 | "startTime": true, | |
43 | "status": true, | |
44 | "style": true, | |
45 | "styleName": true, | |
46 | "symlink": true, | |
47 | "tagging": true, | |
48 | "uploadId": true, | |
49 | "uploads": true, | |
50 | "vod": true, | |
51 | "website": true, | |
52 | "x-oss-process": true, | |
53 | "x-oss-traffic-limit": true, | |
35 | 54 | } |
36 | 55 | |
37 | 56 | func (client *Client) signRequest(request *request) { |
61 | 80 | } |
62 | 81 | |
63 | 82 | if len(params) > 0 { |
64 | resource = resource + "?" + util.Encode(params) | |
83 | resource = resource + "?" + util.EncodeWithoutEscape(params) | |
65 | 84 | } |
66 | 85 | |
67 | 86 | canonicalizedResource := resource |
73 | 92 | //log.Println("stringToSign: ", stringToSign) |
74 | 93 | signature := util.CreateSignature(stringToSign, client.AccessKeySecret) |
75 | 94 | |
76 | if query.Get("OSSAccessKeyId") != "" { | |
95 | if urlSignature { | |
77 | 96 | query.Set("Signature", signature) |
78 | 97 | } else { |
79 | 98 | headers.Set("Authorization", "OSS "+client.AccessKeyId+":"+signature) |
59 | 59 | return NewPVTZClientWithEndpointAndSecurityToken(endpoint, accessKeyId, accessKeySecret, securityToken, regionID) |
60 | 60 | } |
61 | 61 | |
62 | //Onlyfor hangzhou | |
63 | func NewPVTZClientWithSecurityToken4RegionalDomain(accessKeyId string, accessKeySecret string, securityToken string, regionID common.Region) *Client { | |
64 | endpoint := os.Getenv("PVTZ_ENDPOINT") | |
65 | if endpoint == "" { | |
66 | endpoint = PVTZDefaultEndpoint | |
67 | } | |
68 | ||
69 | return NewPVTZClientWithEndpointAndSecurityToken4RegionalDomain(endpoint, accessKeyId, accessKeySecret, securityToken, regionID) | |
70 | } | |
71 | ||
62 | 72 | func NewPVTZClientWithEndpoint(endpoint string, accessKeyId string, accessKeySecret string, regionID common.Region) *Client { |
63 | 73 | return NewPVTZClientWithEndpointAndSecurityToken(endpoint, accessKeyId, accessKeySecret, "", regionID) |
64 | 74 | } |
75 | 85 | InitClient() |
76 | 86 | return client |
77 | 87 | } |
88 | ||
89 | //only for hangzhou | |
90 | func NewPVTZClientWithEndpointAndSecurityToken4RegionalDomain(endpoint string, accessKeyId string, accessKeySecret string, securityToken string, regionID common.Region) *Client { | |
91 | client := &Client{} | |
92 | client.WithEndpoint(endpoint). | |
93 | WithVersion(PVTZAPIVersion). | |
94 | WithAccessKeyId(accessKeyId). | |
95 | WithAccessKeySecret(accessKeySecret). | |
96 | WithSecurityToken(securityToken). | |
97 | WithServiceCode(PVTZServiceCode). | |
98 | WithRegionID(regionID). | |
99 | InitClient4RegionalDomain() | |
100 | return client | |
101 | } |
42 | 42 | err = client.BindZoneVpc(&BindZoneVpcArgs{ |
43 | 43 | ZoneId: zoneId, |
44 | 44 | Vpcs: []VPCType{ |
45 | VPCType{ | |
45 | { | |
46 | 46 | RegionId: common.Beijing, |
47 | 47 | VpcId: TestVPCId, |
48 | 48 | }, |
114 | 114 | } |
115 | 115 | |
116 | 116 | func TestDescribeChangeLogs(t *testing.T) { |
117 | client := NewTestClient() | |
117 | client := NewTestLocationClientForDebug() | |
118 | 118 | |
119 | 119 | changeLogs, err := client.DescribeChangeLogs(&DescribeChangeLogsArgs{}) |
120 | 120 |
0 | 0 | package pvtz |
1 | 1 | |
2 | 2 | import ( |
3 | "github.com/denverdino/aliyungo/common" | |
3 | 4 | "os" |
4 | 5 | ) |
5 | 6 | |
9 | 10 | TestAccessKeyId = os.Getenv("AccessKeyId") |
10 | 11 | TestAccessKeySecret = os.Getenv("AccessKeySecret") |
11 | 12 | TestVPCId = os.Getenv("VPCId") |
13 | TestSecurityToken = os.Getenv("SecurityToken") | |
14 | TestRegionID = common.Region(os.Getenv("RegionId")) | |
12 | 15 | ) |
13 | 16 | |
14 | 17 | var testClient *Client |
29 | 32 | } |
30 | 33 | return testDebugClient |
31 | 34 | } |
35 | ||
36 | var testDebugLocationClient *Client | |
37 | ||
38 | func NewTestLocationClientForDebug() *Client { | |
39 | if testDebugLocationClient == nil { | |
40 | testDebugLocationClient = NewPVTZClientWithSecurityToken4RegionalDomain(TestAccessKeyId, TestAccessKeySecret, TestSecurityToken, TestRegionID) | |
41 | testDebugLocationClient.SetDebug(true) | |
42 | } | |
43 | return testDebugLocationClient | |
44 | } |
151 | 151 | // UpdateZoneRecord update zone record |
152 | 152 | // |
153 | 153 | // You can read doc at https://help.aliyun.com/document_detail/66250.html |
154 | func (client *Client) UpdateZoneRecord(args *AddZoneRecordArgs) (err error) { | |
154 | func (client *Client) UpdateZoneRecord(args *UpdateZoneRecordArgs) (err error) { | |
155 | 155 | response := &UpdateZoneRecordResponse{} |
156 | 156 | |
157 | 157 | err = client.Invoke("UpdateZoneRecord", args, &response) |
80 | 80 | ClearAccountAlias() (RamCommonResponse, error) |
81 | 81 | SetPasswordPolicy(passwordPolicy PasswordPolicyRequest) (PasswordPolicyResponse, error) |
82 | 82 | GetPasswordPolicy() (PasswordPolicyResponse, error) |
83 | ||
84 | // Common Client Methods | |
85 | SetUserAgent(userAgent string) | |
83 | 86 | } |
23 | 23 | |
24 | 24 | type PolicyResponse struct { |
25 | 25 | RamCommonResponse |
26 | Policy Policy | |
26 | Policy Policy | |
27 | DefaultPolicyVersion PolicyVersion | |
27 | 28 | } |
28 | 29 | |
29 | 30 | type PolicyQueryRequest struct { |
11 | 11 | policy_name string |
12 | 12 | policy_document = PolicyDocument{ |
13 | 13 | Statement: []PolicyItem{ |
14 | PolicyItem{ | |
14 | { | |
15 | 15 | Action: "*", |
16 | 16 | Effect: "Allow", |
17 | 17 | Resource: "*", |
202 | 202 | t.Logf("pass ListPoliciesForGroup %++v", resp) |
203 | 203 | } |
204 | 204 | |
205 | func TEstListEntitiesForPolicy(t *testing.T) { | |
205 | func TestListEntitiesForPolicy(t *testing.T) { | |
206 | 206 | client := NewTestClient() |
207 | 207 | policyReq := PolicyRequest{ |
208 | 208 | PolicyType: "Custom", |
19 | 19 | |
20 | 20 | policyDocument = AssumeRolePolicyDocument{ |
21 | 21 | Statement: []AssumeRolePolicyItem{ |
22 | AssumeRolePolicyItem{Action: "sts:AssumeRole", Effect: "Allow", Principal: princpal}, | |
22 | {Action: "sts:AssumeRole", Effect: "Allow", Principal: princpal}, | |
23 | 23 | }, |
24 | 24 | Version: "1"} |
25 | 25 | |
26 | 26 | newPolicyDocument = AssumeRolePolicyDocument{ |
27 | 27 | Statement: []AssumeRolePolicyItem{ |
28 | AssumeRolePolicyItem{Action: "sts:AssumeRole", Effect: "Deny", Principal: princpal}, | |
28 | {Action: "sts:AssumeRole", Effect: "Deny", Principal: princpal}, | |
29 | 29 | }, |
30 | 30 | Version: "1"} |
31 | 31 |
204 | 204 | } |
205 | 205 | |
206 | 206 | // CreateOrder create db instance order |
207 | // you can read doc at http://docs.alibaba-inc.com/pages/viewpage.action?pageId=259349053 | |
208 | 207 | func (client *Client) CreateOrder(args *CreateOrderArgs) (resp CreateOrderResponse, err error) { |
209 | 208 | response := CreateOrderResponse{} |
210 | 209 | err = client.Invoke("CreateOrder", args, &response) |
253 | 253 | args := AllocateInstancePublicConnectionArgs{ |
254 | 254 | DBInstanceId: DBInstanceId, |
255 | 255 | ConnectionStringPrefix: DBInstanceId + "o", |
256 | Port: "3306", | |
256 | Port: "3306", | |
257 | 257 | } |
258 | 258 | |
259 | 259 | _, err := client.AllocateInstancePublicConnection(&args) |
85 | 85 | client.SecurityToken = securityToken |
86 | 86 | } |
87 | 87 | |
88 | // SetTransport sets transport to the http client | |
89 | func (client *Client) SetTransport(transport http.RoundTripper) { | |
90 | if client.httpClient == nil { | |
91 | client.httpClient = &http.Client{} | |
92 | } | |
93 | client.httpClient.Transport = transport | |
94 | } | |
95 | ||
88 | 96 | type Request struct { |
89 | 97 | Method string |
90 | 98 | URL string |
143 | 151 | httpReq.Header.Set("Date", util.GetGMTime()) |
144 | 152 | httpReq.Header.Set("Accept", "application/json") |
145 | 153 | //httpReq.Header.Set("x-acs-version", client.Version) |
154 | httpReq.Header["x-acs-version"] = []string{client.Version} | |
146 | 155 | |
147 | 156 | httpReq.Header["x-acs-signature-version"] = []string{"1.0"} |
148 | 157 | httpReq.Header["x-acs-signature-nonce"] = []string{util.CreateRandomString()} |
179 | 188 | |
180 | 189 | if client.debug { |
181 | 190 | var prettyJSON bytes.Buffer |
182 | err = json.Indent(&prettyJSON, body, "", " ") | |
183 | log.Println(string(prettyJSON.Bytes())) | |
191 | _ = json.Indent(&prettyJSON, body, "", " ") | |
192 | log.Println(prettyJSON.String()) | |
184 | 193 | } |
185 | 194 | |
186 | 195 | if statusCode >= 400 && statusCode <= 599 { |
187 | 196 | errorResponse := common.ErrorResponse{} |
188 | err = json.Unmarshal(body, &errorResponse) | |
197 | _ = json.Unmarshal(body, &errorResponse) | |
189 | 198 | cErr := &common.Error{ |
190 | 199 | ErrorResponse: errorResponse, |
191 | 200 | StatusCode: statusCode, |
13 | 13 | TestSecurityToken = os.Getenv("SecurityToken") |
14 | 14 | TestRegionID = common.Region(os.Getenv("RegionId")) |
15 | 15 | |
16 | clientForTestCase = NewTestClient() | |
17 | debugClientForTestCase = NewTestClientForDebug() | |
16 | debugClientForTestCase = NewTestClientForDebug() | |
17 | debugRpcClientForTestCase = NewTestRpcClientForDebug() | |
18 | 18 | ) |
19 | 19 | |
20 | 20 | var testClient *Client |
28 | 28 | } |
29 | 29 | |
30 | 30 | var testDebugClient *Client |
31 | var testDebugRpcClient *RpcClient | |
31 | 32 | |
32 | 33 | func NewTestClientForDebug() *Client { |
33 | 34 | if testDebugClient == nil { |
37 | 38 | testDebugClient.SetSecurityToken(TestSecurityToken) |
38 | 39 | return testDebugClient |
39 | 40 | } |
41 | ||
42 | func NewTestRpcClientForDebug() *RpcClient { | |
43 | if testDebugRpcClient == nil { | |
44 | testDebugRpcClient = NewRpcClient(TestAccessKeyId, TestAccessKeySecret) | |
45 | testDebugRpcClient.SetDebug(true) | |
46 | } | |
47 | testDebugRpcClient.SetSecurityToken(TestSecurityToken) | |
48 | return testDebugRpcClient | |
49 | } |
17 | 17 | } |
18 | 18 | |
19 | 19 | type Event struct { |
20 | Status string | |
20 | 21 | ResourceStatus string |
21 | 22 | ResourceName string |
22 | 23 | StatusReason string |
32 | 32 | func (client *Client) DescribeResource(stackId, stackName, resourceName string) (*Resource, error) { |
33 | 33 | response := &Resource{} |
34 | 34 | err := client.Invoke("", http.MethodGet, fmt.Sprintf("/stacks/%s/%s/resources/%s", stackName, stackId, resourceName), nil, nil, &response) |
35 | if err != nil { | |
36 | return nil, err | |
37 | } | |
38 | ||
39 | return response, nil | |
40 | } | |
41 | ||
42 | //https://help.aliyun.com/document_detail/28917.html?spm=5176.doc28916.6.589.BUPJqx | |
43 | func (client *Client) DescribeResourceByRegion(regionId common.Region, stackId, stackName, resourceName string) (*Resource, error) { | |
44 | response := &Resource{} | |
45 | err := client.Invoke(regionId, http.MethodGet, fmt.Sprintf("/stacks/%s/%s/resources/%s", stackName, stackId, resourceName), nil, nil, &response) | |
35 | 46 | if err != nil { |
36 | 47 | return nil, err |
37 | 48 | } |
0 | package ros | |
1 | ||
2 | import ( | |
3 | "github.com/denverdino/aliyungo/common" | |
4 | "os" | |
5 | ) | |
6 | ||
7 | const ( | |
8 | ROS_RPC_APIVersion = "2019-09-10" | |
9 | ROSServiceCode = "ros" | |
10 | ) | |
11 | ||
12 | type RpcClient struct { | |
13 | common.Client | |
14 | } | |
15 | ||
16 | func NewRpcClient(accessKeyId, accessKeySecret string) *RpcClient { | |
17 | endpoint := os.Getenv("ROS_ENDPOINT") | |
18 | if endpoint == "" { | |
19 | endpoint = ROSDefaultEndpoint | |
20 | } | |
21 | return NewRpcClientWithEndpoint(endpoint, accessKeyId, accessKeySecret) | |
22 | } | |
23 | ||
24 | func NewRpcClientWithEndpoint(endpoint string, accessKeyId string, accessKeySecret string) *RpcClient { | |
25 | client := &RpcClient{} | |
26 | client.Init(endpoint, ROS_RPC_APIVersion, accessKeyId, accessKeySecret) | |
27 | return client | |
28 | } | |
29 | ||
30 | func NewRosRpcClientWithSecurityToken(accessKeyId string, accessKeySecret string, securityToken string, regionID common.Region) *RpcClient { | |
31 | endpoint := os.Getenv("ROS_ENDPOINT") | |
32 | if endpoint == "" { | |
33 | endpoint = ROSDefaultEndpoint | |
34 | } | |
35 | ||
36 | return NewRosRpcClientWithEndpointAndSecurityToken(endpoint, accessKeyId, accessKeySecret, securityToken, regionID) | |
37 | } | |
38 | ||
39 | func NewRosRpcClientWithEndpointAndSecurityToken(endpoint string, accessKeyId string, accessKeySecret string, securityToken string, regionID common.Region) *RpcClient { | |
40 | client := &RpcClient{} | |
41 | client.WithEndpoint(endpoint). | |
42 | WithVersion(ROS_RPC_APIVersion). | |
43 | WithAccessKeyId(accessKeyId). | |
44 | WithAccessKeySecret(accessKeySecret). | |
45 | WithSecurityToken(securityToken). | |
46 | WithServiceCode(ROSServiceCode). | |
47 | WithRegionID(regionID). | |
48 | InitClient() | |
49 | return client | |
50 | } |
21 | 21 | _, canonicalizedHeader := canonicalizeHeader(headers) |
22 | 22 | |
23 | 23 | stringToSign := request.Method + "\n" + accept + "\n" + contentMd5 + "\n" + contentType + "\n" + date + "\n" + canonicalizedHeader + canonicalizedResource |
24 | ||
25 | log.Println("stringToSign: ", stringToSign) | |
24 | if client.debug { | |
25 | log.Println("stringToSign: ", stringToSign) | |
26 | } | |
26 | 27 | signature := util.CreateSignature(stringToSign, client.AccessKeySecret) |
27 | 28 | headers.Set("Authorization", "acs "+client.AccessKeyId+":"+signature) |
28 | 29 | } |
8 | 8 | "github.com/denverdino/aliyungo/util" |
9 | 9 | ) |
10 | 10 | |
11 | type DeletionProtection string | |
12 | ||
13 | const ( | |
14 | DeletionProtectionEnabled = DeletionProtection("Enabled") | |
15 | DeletionProtectionDisabled = DeletionProtection("Disabled") | |
16 | ) | |
17 | ||
11 | 18 | //https://help.aliyun.com/document_detail/28910.html?spm=5176.doc50083.6.580.b5wkQr |
12 | 19 | type CreateStackRequest struct { |
13 | Name string | |
14 | Template string | |
15 | Parameters interface{} | |
16 | DisableRollback bool | |
17 | TimeoutMins int | |
20 | Name string | |
21 | Template string | |
22 | Parameters interface{} | |
23 | DisableRollback bool | |
24 | DeletionProtection DeletionProtection | |
25 | TimeoutMins int | |
18 | 26 | } |
19 | 27 | |
20 | 28 | type CreateStackResponse struct { |
35 | 43 | //https://help.aliyun.com/document_detail/28911.html?spm=5176.doc28910.6.581.etoi2Z |
36 | 44 | type DeleteStackRequest struct { |
37 | 45 | RegionId common.Region |
46 | } | |
47 | ||
48 | type DeleteStackRpcRequest struct { | |
49 | RegionId common.Region | |
50 | StackId string | |
51 | RetainResources common.FlattenArray | |
52 | RetainAllResources bool | |
53 | } | |
54 | ||
55 | type SetDeletionProtectionRequest struct { | |
56 | RegionId common.Region | |
57 | StackId string | |
58 | DeletionProtection DeletionProtection | |
38 | 59 | } |
39 | 60 | |
40 | 61 | type DeleteStackResponse struct { |
202 | 223 | |
203 | 224 | //https://help.aliyun.com/document_detail/49066.html?spm=5176.doc28910.6.586.MJjWQh |
204 | 225 | type UpdateStackRequest struct { |
205 | Template string | |
206 | Parameters interface{} | |
207 | DisableRollback bool | |
208 | TimeoutMins int | |
226 | Template string | |
227 | Parameters interface{} | |
228 | DisableRollback bool | |
229 | TimeoutMins int | |
230 | StackPolicy interface{} | |
231 | UpdateAllowPolicy interface{} | |
232 | Existing bool | |
209 | 233 | } |
210 | 234 | |
211 | 235 | type UpdateStackResponse struct { |
223 | 247 | |
224 | 248 | return stack, nil |
225 | 249 | } |
250 | ||
251 | // rpc api: https://help.aliyun.com/document_detail/132113.html?spm=a2c4g.11174283.6.880.1b1d143eCzdE0b | |
252 | func (client *RpcClient) DeleteStack(args *DeleteStackRpcRequest) (*DeleteStackResponse, error) { | |
253 | response := &DeleteStackResponse{} | |
254 | err := client.InvokeByFlattenMethod("DeleteStack", args, response) | |
255 | if err != nil { | |
256 | return nil, err | |
257 | } | |
258 | return response, nil | |
259 | } | |
260 | ||
261 | // rpc api: https://help.aliyun.com/document_detail/161560.html?spm=a2c4g.11186623.6.991.18f62842yOfz9G | |
262 | func (client *RpcClient) SetDeletionProtection(args *SetDeletionProtectionRequest) (*common.Response, error) { | |
263 | response := &common.Response{} | |
264 | err := client.Invoke("SetDeletionProtection", args, response) | |
265 | if err != nil { | |
266 | return nil, err | |
267 | } | |
268 | return response, nil | |
269 | } |
0 | 0 | package ros |
1 | 1 | |
2 | 2 | import ( |
3 | "strings" | |
3 | 4 | "testing" |
4 | 5 | |
5 | 6 | "fmt" |
90 | 91 | } |
91 | 92 | } |
92 | 93 | |
94 | func TestClient_CreateStack_DeletionProtection(t *testing.T) { | |
95 | args := &CreateStackRequest{ | |
96 | Name: fmt.Sprintf("my-k8s-test-stack-%d", time.Now().Unix()), | |
97 | Template: myTestTemplate, | |
98 | Parameters: map[string]interface{}{}, | |
99 | DisableRollback: false, | |
100 | DeletionProtection: DeletionProtectionEnabled, | |
101 | TimeoutMins: 30, | |
102 | } | |
103 | ||
104 | response, err := debugClientForTestCase.CreateStack(TestRegionID, args) | |
105 | if err != nil { | |
106 | t.Fatalf("Failed to CreateStack %++v", err) | |
107 | } else { | |
108 | t.Logf("Success %++v", response) | |
109 | } | |
110 | } | |
111 | ||
93 | 112 | func TestClient_DeleteStack(t *testing.T) { |
94 | 113 | stackName := os.Getenv("StackName") |
95 | 114 | stackId := os.Getenv("StackId") |
158 | 177 | t.Logf("Success %++v", response) |
159 | 178 | } |
160 | 179 | } |
180 | ||
181 | func TestClient_DeleteStackWithParams(t *testing.T) { | |
182 | stackId := os.Getenv("StackId") | |
183 | resourceIds := os.Getenv("RetainResources") | |
184 | ||
185 | args := &DeleteStackRpcRequest{ | |
186 | RegionId: TestRegionID, | |
187 | StackId: stackId, | |
188 | RetainResources: strings.Split(resourceIds, ","), | |
189 | } | |
190 | ||
191 | response, err := debugRpcClientForTestCase.DeleteStack(args) | |
192 | if err != nil { | |
193 | t.Fatalf("Failed to DeleteStack %++v", err) | |
194 | } else { | |
195 | t.Logf("Success %++v", response) | |
196 | } | |
197 | } | |
198 | ||
199 | func TestClient_DeleteStack_DisabledProtection(t *testing.T) { | |
200 | stackId := os.Getenv("StackId") | |
201 | ||
202 | args := &SetDeletionProtectionRequest{ | |
203 | RegionId: TestRegionID, | |
204 | StackId: stackId, | |
205 | DeletionProtection: DeletionProtectionDisabled, | |
206 | } | |
207 | ||
208 | response, err := debugRpcClientForTestCase.SetDeletionProtection(args) | |
209 | if err != nil { | |
210 | t.Fatalf("Failed to SetDeletionProtection %++v", err) | |
211 | } else { | |
212 | t.Logf("Success %++v", response) | |
213 | } | |
214 | ||
215 | deleteArgs := &DeleteStackRpcRequest{ | |
216 | RegionId: TestRegionID, | |
217 | StackId: stackId, | |
218 | } | |
219 | ||
220 | resp, err := debugRpcClientForTestCase.DeleteStack(deleteArgs) | |
221 | if err != nil { | |
222 | t.Fatalf("Failed to DeleteStack %++v", err) | |
223 | } else { | |
224 | t.Logf("Success %++v", resp) | |
225 | } | |
226 | } |
0 | package standard | |
1 | ||
2 | import ( | |
3 | "github.com/denverdino/aliyungo/common" | |
4 | ||
5 | "os" | |
6 | ) | |
7 | ||
8 | type Client struct { | |
9 | common.Client | |
10 | } | |
11 | ||
12 | const ( | |
13 | // ROSDefaultEndpoint is the default API endpoint of ESS services | |
14 | ROSDefaultEndpoint = "https://ros.aliyuncs.com" | |
15 | ROSAPIVersion = "2019-09-10" | |
16 | ROSServiceCode = "ros" | |
17 | ) | |
18 | ||
19 | // NewClient creates a new instance of RDS client | |
20 | func NewClient(accessKeyId, accessKeySecret string) *Client { | |
21 | endpoint := os.Getenv("ROS_ENDPOINT") | |
22 | if endpoint == "" { | |
23 | endpoint = ROSDefaultEndpoint | |
24 | } | |
25 | return NewClientWithEndpoint(endpoint, accessKeyId, accessKeySecret) | |
26 | } | |
27 | ||
28 | func NewClientWithEndpoint(endpoint string, accessKeyId, accessKeySecret string) *Client { | |
29 | client := &Client{} | |
30 | client.Init(endpoint, ROSAPIVersion, accessKeyId, accessKeySecret) | |
31 | return client | |
32 | } | |
33 | ||
34 | func NewROSClient(accessKeyId, accessKeySecret string, regionID common.Region) *Client { | |
35 | endpoint := os.Getenv("ROS_ENDPOINT") | |
36 | if endpoint == "" { | |
37 | endpoint = ROSDefaultEndpoint | |
38 | } | |
39 | ||
40 | return NewClientWithRegion(endpoint, accessKeyId, accessKeySecret, regionID) | |
41 | } | |
42 | ||
43 | func NewClientWithRegion(endpoint string, accessKeyId, accessKeySecret string, regionID common.Region) *Client { | |
44 | client := &Client{} | |
45 | client.NewInit(endpoint, ROSAPIVersion, accessKeyId, accessKeySecret, ROSServiceCode, regionID) | |
46 | return client | |
47 | } |
0 | package standard | |
1 | ||
2 | import ( | |
3 | "fmt" | |
4 | "github.com/denverdino/aliyungo/common" | |
5 | "testing" | |
6 | ) | |
7 | ||
8 | const ( | |
9 | TestAccessKeyId = "" | |
10 | TestAccessKeySecret = "" | |
11 | Region = common.Shanghai | |
12 | StackID = "c7f1fed9-0104-4596-aae6-aa5215f5a793" | |
13 | ) | |
14 | ||
15 | func NewTestClient() *Client { | |
16 | return NewROSClient(TestAccessKeyId, TestAccessKeySecret, Region) | |
17 | } | |
18 | ||
19 | func TestGetStack(t *testing.T) { | |
20 | ||
21 | client := NewTestClient() | |
22 | req := GetStackRequest{ | |
23 | RegionId: Region, | |
24 | StackId: StackID, | |
25 | } | |
26 | res, err := client.GetStack(&req) | |
27 | if err != nil { | |
28 | t.Fail() | |
29 | } | |
30 | fmt.Printf("Response: %+v\n", res) | |
31 | } | |
32 | ||
33 | func TestListStack(t *testing.T) { | |
34 | client := NewTestClient() | |
35 | req := &ListStacksRequest{} | |
36 | res, err := client.ListStacks(req) | |
37 | if err != nil { | |
38 | t.Fail() | |
39 | } | |
40 | fmt.Printf("ListResponse: %+v\n", res) | |
41 | } | |
42 | ||
43 | func TestListStackEvent(t *testing.T) { | |
44 | client := NewTestClient() | |
45 | req := &ListStackEventsRequest{ | |
46 | StackId: StackID, | |
47 | } | |
48 | res, err := client.ListStackEvents(req) | |
49 | if err != nil { | |
50 | t.Fail() | |
51 | } | |
52 | fmt.Printf("ListEventResponse: %+v\n", res) | |
53 | } | |
54 | ||
55 | func TestCreateStack(t *testing.T) { | |
56 | client := NewTestClient() | |
57 | req := &CreateStackRequest{ | |
58 | StackName: "TDDDDDDD", | |
59 | TemplateBody: tpl, | |
60 | DisableRollback: true, | |
61 | TimeoutInMinutes: 60, | |
62 | Parameters: []Parameter{ | |
63 | {ParameterKey: "SystemDisk", ParameterValue: ""}, | |
64 | }, | |
65 | } | |
66 | res, err := client.CreateStack(req) | |
67 | if err != nil { | |
68 | t.Logf("create stack: %s", err.Error()) | |
69 | t.Fail() | |
70 | } | |
71 | fmt.Printf("ListEventResponse: %+v\n", res) | |
72 | } | |
73 | ||
74 | var tpl = ` | |
75 | ||
76 | ` |
0 | package standard | |
1 | ||
2 | import ( | |
3 | "github.com/denverdino/aliyungo/common" | |
4 | ) | |
5 | ||
6 | type DeletionProtection string | |
7 | ||
8 | const ( | |
9 | DeletionProtectionEnabled = DeletionProtection("Enabled") | |
10 | DeletionProtectionDisabled = DeletionProtection("Disabled") | |
11 | ) | |
12 | ||
13 | //https://help.aliyun.com/document_detail/28910.html?spm=5176.doc50083.6.580.b5wkQr | |
14 | type CreateStackRequest struct { | |
15 | RegionId common.Region | |
16 | StackName string | |
17 | DisableRollback bool | |
18 | TemplateBody string | |
19 | TemplateURL string | |
20 | Parameters []Parameter | |
21 | StackPolicyURL string | |
22 | TimeoutInMinutes int | |
23 | StackPolicyBody string | |
24 | ClientToken string | |
25 | NotificationURLs []string | |
26 | DeletionProtection DeletionProtection | |
27 | RamRoleName string | |
28 | } | |
29 | ||
30 | type CreateStackResponse struct { | |
31 | StackId string | |
32 | common.Response | |
33 | } | |
34 | ||
35 | type ListStackEventsRequest struct { | |
36 | common.Pagination | |
37 | RegionId common.Region | |
38 | StackId string | |
39 | Status []string | |
40 | ResourceType []string | |
41 | LogicalResourceId []string | |
42 | } | |
43 | ||
44 | type ListStackEventsResponse struct { | |
45 | common.Response | |
46 | common.PaginationResult | |
47 | RegionId common.Region | |
48 | Events []Event | |
49 | } | |
50 | ||
51 | type Event struct { | |
52 | StackId string | |
53 | Status string | |
54 | StackName string | |
55 | StatusReason string | |
56 | EventId string | |
57 | LogicalResourceId string | |
58 | ResourceType string | |
59 | PhysicalResourceId string | |
60 | CreateTime string | |
61 | } | |
62 | ||
63 | func (client *Client) ListStackEvents(args *ListStackEventsRequest) (*ListStackEventsResponse, error) { | |
64 | response := &ListStackEventsResponse{} | |
65 | err := client.Invoke("ListStackEvents", args, response) | |
66 | if err != nil { | |
67 | return nil, err | |
68 | } | |
69 | ||
70 | return response, nil | |
71 | } | |
72 | ||
73 | func (client *Client) CreateStack(args *CreateStackRequest) (*CreateStackResponse, error) { | |
74 | stack := &CreateStackResponse{} | |
75 | err := client.Invoke("CreateStack", args, stack) | |
76 | if err != nil { | |
77 | return nil, err | |
78 | } | |
79 | ||
80 | return stack, nil | |
81 | } | |
82 | ||
83 | //https://help.aliyun.com/document_detail/28911.html?spm=5176.doc28910.6.581.etoi2Z | |
84 | type DeleteStackRequest struct { | |
85 | RegionId common.Region | |
86 | StackId string | |
87 | RetainAllResources bool | |
88 | RetainResources []string | |
89 | RamRoleName string | |
90 | } | |
91 | ||
92 | type DeleteStackResponse struct { | |
93 | common.Response | |
94 | } | |
95 | ||
96 | func (client *Client) DeleteStack(req *DeleteStackRequest) (*DeleteStackResponse, error) { | |
97 | response := &DeleteStackResponse{} | |
98 | err := client.Invoke("DeleteStack", req, response) | |
99 | if err != nil { | |
100 | return nil, err | |
101 | } | |
102 | ||
103 | return response, nil | |
104 | } | |
105 | ||
106 | type GetStackRequest struct { | |
107 | RegionId common.Region | |
108 | StackId string | |
109 | ClientToken string | |
110 | } | |
111 | ||
112 | type GetStackResponse struct { | |
113 | CreateTime string | |
114 | Description string | |
115 | DisableRollback bool | |
116 | NotificationURLs []string | |
117 | Outputs []Output | |
118 | ParentStackId string | |
119 | RegionId common.Region | |
120 | Status string | |
121 | StackId string | |
122 | StackName string | |
123 | Parameters []Parameter | |
124 | UpdateTime string | |
125 | StatusReason string | |
126 | TemplateDescription string | |
127 | TimeoutInMinutes int | |
128 | ||
129 | RequestId string | |
130 | DeletionProtection DeletionProtection | |
131 | DriftDetectionTime string | |
132 | RamRoleName string | |
133 | RootStackId string | |
134 | StackDriftStatus string | |
135 | StackType string | |
136 | } | |
137 | ||
138 | type Parameter struct { | |
139 | ParameterKey string | |
140 | ParameterValue string | |
141 | } | |
142 | ||
143 | type Output struct { | |
144 | Description string | |
145 | OutputKey string | |
146 | OutputValue interface{} | |
147 | } | |
148 | ||
149 | func (client *Client) GetStack(req *GetStackRequest) (*GetStackResponse, error) { | |
150 | response := &GetStackResponse{} | |
151 | err := client.Invoke("GetStack", req, response) | |
152 | if err != nil { | |
153 | return nil, err | |
154 | } | |
155 | ||
156 | return response, nil | |
157 | } | |
158 | ||
159 | type ListStacksRequest struct { | |
160 | RegionId common.Region | |
161 | StackId string | |
162 | Status []string | |
163 | ParentStackId string | |
164 | StackName []string | |
165 | ShowNestedStack bool | |
166 | Tag []Tag | |
167 | common.Pagination | |
168 | } | |
169 | ||
170 | type ListStacksResponse struct { | |
171 | common.PaginationResult | |
172 | common.Response | |
173 | Stacks []Stack | |
174 | } | |
175 | ||
176 | type Stack struct { | |
177 | CreateTime string | |
178 | ||
179 | DisableRollback bool | |
180 | DriftDetectionTime string | |
181 | ParentStackId string | |
182 | RegionId common.Region | |
183 | StackDriftStatus string | |
184 | StackId string | |
185 | StackName string | |
186 | Status string | |
187 | StatusReason string | |
188 | ||
189 | TimeoutInMinutes int | |
190 | UpdateTime string | |
191 | } | |
192 | ||
193 | type Tag struct { | |
194 | Key string | |
195 | Value string | |
196 | } | |
197 | ||
198 | func (client *Client) ListStacks(req *ListStacksRequest) (*ListStacksResponse, error) { | |
199 | response := &ListStacksResponse{} | |
200 | err := client.Invoke("ListStacks", req, response) | |
201 | if err != nil { | |
202 | return nil, err | |
203 | } | |
204 | ||
205 | return response, nil | |
206 | } | |
207 | ||
208 | type UpdateStackRequest struct { | |
209 | Parameters []Parameter | |
210 | RegionId string | |
211 | StackId string | |
212 | ClientToken string | |
213 | StackPolicyDuringUpdateBody string | |
214 | TimeoutInMinutes int | |
215 | TemplateBody string | |
216 | StackPolicyURL string | |
217 | StackPolicyDuringUpdateURL string | |
218 | StackPolicyBody string | |
219 | UsePreviousParameters bool | |
220 | DisableRollback bool | |
221 | TemplateURL string | |
222 | RamRoleName string | |
223 | ReplacementOption string | |
224 | } | |
225 | ||
226 | type UpdateStackResponse struct { | |
227 | StackId string | |
228 | common.Response | |
229 | } | |
230 | ||
231 | func (client *Client) UpdateStack(req *UpdateStackRequest) (*UpdateStackResponse, error) { | |
232 | response := &UpdateStackResponse{} | |
233 | err := client.Invoke("UpdateStack", req, response) | |
234 | if err != nil { | |
235 | return nil, err | |
236 | } | |
237 | ||
238 | return response, nil | |
239 | } | |
240 | ||
241 | type GetStackResourceRequest struct { | |
242 | StackId string | |
243 | LogicalResourceId string | |
244 | ClientToken string | |
245 | ShowResourceAttributes bool | |
246 | RegionId common.Region | |
247 | } | |
248 | ||
249 | type GetStackResourceResponse struct { | |
250 | Status string | |
251 | Description string | |
252 | LogicalResourceId string | |
253 | StackId string | |
254 | ||
255 | StackName string | |
256 | StatusReason string | |
257 | PhysicalResourceId string | |
258 | ResourceType string | |
259 | CreateTime string | |
260 | Metadata map[string]string | |
261 | UpdateTime string | |
262 | ResourceAttributes []ResourceAttribute | |
263 | RequestId string | |
264 | DriftDetectionTime string | |
265 | ResourceDriftStatus string | |
266 | } | |
267 | type ResourceAttribute struct { | |
268 | ResourceAttributeValue string | |
269 | ResourceAttributeKey string | |
270 | } | |
271 | ||
272 | func (client *Client) GetStackResource(req *GetStackResourceRequest) (*GetStackResourceResponse, error) { | |
273 | response := &GetStackResourceResponse{} | |
274 | err := client.Invoke("GetStackResource", req, response) | |
275 | if err != nil { | |
276 | return nil, err | |
277 | } | |
278 | ||
279 | return response, nil | |
280 | } | |
281 | ||
282 | type ListStackResourcesRequest struct { | |
283 | RegionId common.Region | |
284 | StackId string | |
285 | } | |
286 | ||
287 | type ListStackResourcesResponse struct { | |
288 | common.Response | |
289 | Resources []Resource | |
290 | } | |
291 | ||
292 | type Resource struct { | |
293 | CreateTime string | |
294 | DriftDetectionTime string | |
295 | LogicalResourceId string | |
296 | PhysicalResourceId string | |
297 | ||
298 | ResourceDriftStatus string | |
299 | ResourceType string | |
300 | StackId string | |
301 | StackName string | |
302 | Status string | |
303 | StatusReason string | |
304 | UpdateTime string | |
305 | } | |
306 | ||
307 | func (client *Client) ListStackResources(req *ListStackResourcesRequest) (*ListStackResourcesResponse, error) { | |
308 | response := &ListStackResourcesResponse{} | |
309 | err := client.Invoke("ListStackResources", req, response) | |
310 | if err != nil { | |
311 | return nil, err | |
312 | } | |
313 | ||
314 | return response, nil | |
315 | } |
56 | 56 | return NewSLBClientWithEndpointAndSecurityToken(endpoint, accessKeyId, accessKeySecret, securityToken, regionID) |
57 | 57 | } |
58 | 58 | |
59 | //Only for hangzhou | |
60 | func NewSLBClientWithSecurityToken4RegionalDomain(accessKeyId string, accessKeySecret string, securityToken string, regionID common.Region) *Client { | |
61 | endpoint := os.Getenv("SLB_ENDPOINT") | |
62 | if endpoint == "" { | |
63 | endpoint = SLBDefaultEndpoint | |
64 | } | |
65 | ||
66 | return NewSLBClientWithEndpointAndSecurityToken4RegionalDomain(endpoint, accessKeyId, accessKeySecret, securityToken, regionID) | |
67 | } | |
68 | ||
59 | 69 | func NewSLBClientWithEndpointAndSecurityToken(endpoint string, accessKeyId string, accessKeySecret string, securityToken string, regionID common.Region) *Client { |
60 | 70 | client := &Client{} |
61 | 71 | client.WithEndpoint(endpoint). |
68 | 78 | InitClient() |
69 | 79 | return client |
70 | 80 | } |
81 | ||
82 | //only for hangzhou | |
83 | func NewSLBClientWithEndpointAndSecurityToken4RegionalDomain(endpoint string, accessKeyId string, accessKeySecret string, securityToken string, regionID common.Region) *Client { | |
84 | client := &Client{} | |
85 | client.WithEndpoint(endpoint). | |
86 | WithVersion(SLBAPIVersion). | |
87 | WithAccessKeyId(accessKeyId). | |
88 | WithAccessKeySecret(accessKeySecret). | |
89 | WithSecurityToken(securityToken). | |
90 | WithServiceCode(SLBServiceCode). | |
91 | WithRegionID(regionID). | |
92 | InitClient4RegionalDomain() | |
93 | return client | |
94 | } |
15 | 15 | TestVServerGroupID = "MY_VSERVER_GROUPID" |
16 | 16 | TestListenerPort = 9000 |
17 | 17 | TestInstanceId = "MY_INSTANCE_ID" |
18 | TestENIId = "MY_ENI_ID" | |
18 | 19 | TestRegionID = common.Region(os.Getenv("RegionId")) |
19 | 20 | TestIAmRich = false |
20 | 21 | TestQuick = false |
43 | 44 | |
44 | 45 | func NewTestNewSLBClientForDebug() *Client { |
45 | 46 | if testDebugNewSLBClient == nil { |
46 | testDebugNewSLBClient = NewSLBClientWithSecurityToken(TestAccessKeyId, TestAccessKeySecret, TestSecurityToken, TestRegionID) | |
47 | testDebugNewSLBClient = NewSLBClientWithSecurityToken4RegionalDomain(TestAccessKeyId, TestAccessKeySecret, TestSecurityToken, TestRegionID) | |
47 | 48 | testDebugNewSLBClient.SetDebug(true) |
48 | 49 | } |
49 | 50 | return testDebugNewSLBClient |
98 | 98 | UnhealthyThreshold int |
99 | 99 | HealthCheckTimeout int |
100 | 100 | HealthCheckInterval int |
101 | ForwardPort int | |
102 | ListenerForward FlagType | |
101 | 103 | HealthCheckHttpCode HealthCheckHttpCodeType |
102 | 104 | VServerGroup FlagType |
103 | 105 | VServerGroupId string |
105 | 107 | XForwardedFor_SLBID FlagType |
106 | 108 | XForwardedFor_SLBIP FlagType |
107 | 109 | XForwardedFor_proto FlagType |
110 | Description string | |
111 | AclId string | |
112 | AclStatus string | |
113 | AclType string | |
108 | 114 | } |
109 | 115 | type CreateLoadBalancerHTTPListenerArgs HTTPListenerType |
110 | 116 | |
146 | 152 | BackendServerPort int |
147 | 153 | Bandwidth int |
148 | 154 | Scheduler SchedulerType |
149 | PersistenceTimeout int | |
155 | PersistenceTimeout *int | |
150 | 156 | HealthCheck FlagType |
151 | 157 | HealthCheckType HealthCheckType |
152 | 158 | HealthCheckDomain string |
159 | 165 | HealthCheckHttpCode HealthCheckHttpCodeType |
160 | 166 | VServerGroup FlagType |
161 | 167 | VServerGroupId string |
168 | Description string | |
169 | AclId string | |
170 | AclStatus string | |
171 | AclType string | |
162 | 172 | } |
163 | 173 | |
164 | 174 | type CreateLoadBalancerTCPListenerArgs TCPListenerType |
178 | 188 | BackendServerPort int |
179 | 189 | Bandwidth int |
180 | 190 | Scheduler SchedulerType |
181 | PersistenceTimeout int | |
191 | PersistenceTimeout *int | |
182 | 192 | HealthCheck FlagType |
183 | 193 | HealthCheckConnectPort int |
184 | 194 | HealthyThreshold int |
187 | 197 | HealthCheckInterval int |
188 | 198 | VServerGroup FlagType |
189 | 199 | VServerGroupId string |
200 | Description string | |
201 | ||
202 | AclId string | |
203 | AclStatus string | |
204 | AclType string | |
190 | 205 | } |
191 | 206 | type CreateLoadBalancerUDPListenerArgs UDPListenerType |
192 | 207 |
0 | 0 | package slb |
1 | 1 | |
2 | import "testing" | |
2 | import ( | |
3 | "bytes" | |
4 | "encoding/json" | |
5 | "fmt" | |
6 | "testing" | |
7 | ) | |
3 | 8 | |
4 | 9 | func testListeners(t *testing.T, client *Client, loadBalancerId string) { |
5 | 10 | |
40 | 45 | } |
41 | 46 | t.Logf("Listener: %++v", *response) |
42 | 47 | } |
48 | ||
49 | func TestDescribeListener(t *testing.T) { | |
50 | ||
51 | response, err := client.DescribeLoadBalancerTCPListenerAttribute(loadBalancerId, 22) | |
52 | if err != nil { | |
53 | t.Error(err) | |
54 | } else { | |
55 | fmt.Println(PrettyJson(response)) | |
56 | } | |
57 | } | |
58 | ||
59 | func TestDescribeSLB(t *testing.T) { | |
60 | ||
61 | response, err := client.DescribeLoadBalancerAttribute(loadBalancerId) | |
62 | if err != nil { | |
63 | t.Error(err) | |
64 | } else { | |
65 | fmt.Println(PrettyJson(response)) | |
66 | } | |
67 | } | |
68 | ||
69 | func PrettyJson(obj interface{}) string { | |
70 | pretty := bytes.Buffer{} | |
71 | data, err := json.Marshal(obj) | |
72 | if err != nil { | |
73 | return err.Error() | |
74 | } | |
75 | err = json.Indent(&pretty, data, "", " ") | |
76 | ||
77 | if err != nil { | |
78 | return err.Error() | |
79 | } | |
80 | ||
81 | return pretty.String() | |
82 | } |
19 | 19 | const ( |
20 | 20 | PayByBandwidth = InternetChargeType("paybybandwidth") |
21 | 21 | PayByTraffic = InternetChargeType("paybytraffic") |
22 | ) | |
23 | ||
24 | type AddressIPVersionType string | |
25 | ||
26 | const ( | |
27 | IPv4 = AddressIPVersionType("ipv4") | |
28 | IPv6 = AddressIPVersionType("ipv6") | |
22 | 29 | ) |
23 | 30 | |
24 | 31 | type LoadBalancerSpecType string |
32 | 39 | S3Large = "slb.s3.large" |
33 | 40 | ) |
34 | 41 | |
42 | type ModificationProtectionType string | |
43 | ||
44 | const ( | |
45 | NonProtection = ModificationProtectionType("NonProtection") | |
46 | ConsoleProtection = ModificationProtectionType("ConsoleProtection") | |
47 | ) | |
48 | ||
35 | 49 | type CreateLoadBalancerArgs struct { |
36 | RegionId common.Region | |
37 | LoadBalancerName string | |
38 | AddressType AddressType | |
39 | VSwitchId string | |
40 | InternetChargeType InternetChargeType | |
41 | Bandwidth int | |
42 | ClientToken string | |
43 | MasterZoneId string | |
44 | SlaveZoneId string | |
45 | LoadBalancerSpec LoadBalancerSpecType | |
50 | RegionId common.Region | |
51 | LoadBalancerName string | |
52 | AddressType AddressType | |
53 | VSwitchId string | |
54 | InternetChargeType InternetChargeType | |
55 | Bandwidth int | |
56 | ClientToken string | |
57 | MasterZoneId string | |
58 | SlaveZoneId string | |
59 | LoadBalancerSpec LoadBalancerSpecType | |
60 | AddressIPVersion AddressIPVersionType | |
61 | DeleteProtection FlagType | |
62 | ModificationProtectionStatus ModificationProtectionType | |
63 | ModificationProtectionReason string | |
64 | ResourceGroupId string | |
46 | 65 | } |
47 | 66 | |
48 | 67 | type CreateLoadBalancerResponse struct { |
53 | 72 | VpcId string |
54 | 73 | VSwitchId string |
55 | 74 | LoadBalancerName string |
75 | MasterZoneId string | |
76 | SlaveZoneId string | |
77 | AddressIPVersion AddressIPVersionType | |
56 | 78 | } |
57 | 79 | |
58 | 80 | // CreateLoadBalancer create loadbalancer |
192 | 214 | type ListenerPortAndProtocolType struct { |
193 | 215 | ListenerPort int |
194 | 216 | ListenerProtocol string |
217 | Description string | |
195 | 218 | } |
196 | 219 | |
197 | 220 | type BackendServerType struct { |
200 | 223 | Type string |
201 | 224 | } |
202 | 225 | |
226 | type ServiceManagedModeType string | |
227 | ||
228 | const ( | |
229 | Managed = ServiceManagedModeType("Managed") | |
230 | Unmanaged = ServiceManagedModeType("Unmanaged") | |
231 | DependencyManaged = ServiceManagedModeType("DependencyManaged") | |
232 | ) | |
233 | ||
203 | 234 | type LoadBalancerType struct { |
204 | LoadBalancerId string | |
205 | LoadBalancerName string | |
206 | LoadBalancerStatus string | |
207 | Address string | |
208 | RegionId common.Region | |
209 | RegionIdAlias string | |
210 | AddressType AddressType | |
211 | VSwitchId string | |
212 | VpcId string | |
213 | NetworkType string | |
214 | Bandwidth int | |
215 | InternetChargeType InternetChargeType | |
216 | CreateTime string //Why not ISO 6801 | |
217 | CreateTimeStamp util.ISO6801Time | |
218 | ListenerPorts struct { | |
235 | LoadBalancerId string | |
236 | ResourceGroupId string | |
237 | LoadBalancerName string | |
238 | LoadBalancerStatus string | |
239 | Address string | |
240 | RegionId common.Region | |
241 | RegionIdAlias string | |
242 | AddressType AddressType | |
243 | VSwitchId string | |
244 | VpcId string | |
245 | NetworkType string | |
246 | Bandwidth int | |
247 | InternetChargeType InternetChargeType | |
248 | CreateTime string //Why not ISO 6801 | |
249 | CreateTimeStamp util.ISO6801Time | |
250 | DeleteProtection FlagType | |
251 | ModificationProtectionStatus ModificationProtectionType | |
252 | ModificationProtectionReason string | |
253 | ListenerPorts struct { | |
219 | 254 | ListenerPort []int |
220 | 255 | } |
221 | 256 | ListenerPortsAndProtocol struct { |
224 | 259 | BackendServers struct { |
225 | 260 | BackendServer []BackendServerType |
226 | 261 | } |
227 | LoadBalancerSpec LoadBalancerSpecType | |
262 | LoadBalancerSpec LoadBalancerSpecType | |
263 | MasterZoneId string | |
264 | SlaveZoneId string | |
265 | AddressIPVersion AddressIPVersionType | |
266 | ServiceManagedMode ServiceManagedModeType | |
228 | 267 | } |
229 | 268 | |
230 | 269 | type DescribeLoadBalancersResponse struct { |
320 | 359 | } |
321 | 360 | return nil |
322 | 361 | } |
362 | ||
363 | type SetLoadBalancerDeleteProtectionArgs struct { | |
364 | LoadBalancerId string | |
365 | DeleteProtection FlagType | |
366 | RegionId common.Region | |
367 | } | |
368 | ||
369 | type SetLoadBalancerDeleteProtectionResponse struct { | |
370 | common.Response | |
371 | } | |
372 | ||
373 | // SetLoadBalancerDeleteProtection loadbalancer delete protection | |
374 | // | |
375 | // You can read doc at https://help.aliyun.com/document_detail/122674.html?spm=a2c4g.11186623.6.720.694f4265hwOdXQ | |
376 | func (client *Client) SetLoadBalancerDeleteProtection(args *SetLoadBalancerDeleteProtectionArgs) (err error) { | |
377 | response := &SetLoadBalancerDeleteProtectionResponse{} | |
378 | err = client.Invoke("SetLoadBalancerDeleteProtection", args, response) | |
379 | return err | |
380 | } | |
381 | ||
382 | type SetLoadBalancerModificationProtectionArgs struct { | |
383 | RegionId common.Region | |
384 | LoadBalancerId string | |
385 | ModificationProtectionStatus ModificationProtectionType | |
386 | ModificationProtectionReason string | |
387 | } | |
388 | ||
389 | type SetLoadBalancerModificationProtectionResponse struct { | |
390 | common.Response | |
391 | } | |
392 | ||
393 | func (client *Client) SetLoadBalancerModificationProtection(args *SetLoadBalancerModificationProtectionArgs) (err error) { | |
394 | response := &SetLoadBalancerModificationProtectionResponse{} | |
395 | err = client.Invoke("SetLoadBalancerModificationProtection", args, response) | |
396 | return err | |
397 | } | |
398 | ||
399 | type ManagedResourceType string | |
400 | ||
401 | const ( | |
402 | ManagedLoadBalancer = ManagedResourceType("LoadBalancer") | |
403 | ManagedTls = ManagedResourceType("Tls") | |
404 | ManagedVServerGroup = ManagedResourceType("VServerGroup") | |
405 | ManagedMasterSlaveServerGroup = ManagedResourceType("MasterSlaveServerGroup") | |
406 | ManagedAcl = ManagedResourceType("Acl") | |
407 | ManagedListener = ManagedResourceType("Listener") | |
408 | ManagedRule = ManagedResourceType("Rule") | |
409 | ManagedAppRule = ManagedResourceType("AppRule") | |
410 | ManagedDomainExtension = ManagedResourceType("DomainExtension") | |
411 | ) | |
412 | ||
413 | type ManagedResourceModel struct { | |
414 | ResourceId string | |
415 | Port int | |
416 | Protocol string | |
417 | } | |
418 | ||
419 | type ServiceManagedControlArgs struct { | |
420 | RegionId common.Region | |
421 | ServiceManagedMode ServiceManagedModeType | |
422 | ResourceUid string | |
423 | ResourceBid string | |
424 | ResourceType ManagedResourceType | |
425 | Resources []ManagedResourceModel | |
426 | } | |
427 | ||
428 | type ServiceManagedControlResponse struct { | |
429 | common.Response | |
430 | } | |
431 | ||
432 | //api: https://yuque.antfin-inc.com/docs/share/63b5a2d3-6fb3-4bd7-a50e-c4b385b866fd?# | |
433 | func (client *Client) ServiceManagedControl(args *ServiceManagedControlArgs) (err error) { | |
434 | response := &ServiceManagedControlResponse{} | |
435 | err = client.Invoke("ServiceManagedControl", args, response) | |
436 | return err | |
437 | } |
5 | 5 | "github.com/denverdino/aliyungo/common" |
6 | 6 | ) |
7 | 7 | |
8 | func TestLoadBlancer(t *testing.T) { | |
8 | func TestLoadBalancer(t *testing.T) { | |
9 | 9 | |
10 | 10 | client := NewTestClientForDebug() |
11 | 11 | |
12 | 12 | creationArgs := CreateLoadBalancerArgs{ |
13 | 13 | RegionId: common.Beijing, |
14 | 14 | LoadBalancerName: "test-slb", |
15 | LoadBalancerSpec: S2Medium, // eni not support slb.s0.share slb(default slb.s0.share) | |
15 | 16 | AddressType: InternetAddressType, |
16 | 17 | ClientToken: client.GenerateClientToken(), |
17 | 18 | } |
29 | 30 | |
30 | 31 | describeLoadBalancersArgs := DescribeLoadBalancersArgs{ |
31 | 32 | RegionId: common.Beijing, |
33 | } | |
34 | ||
35 | loadBalancers, err := client.DescribeLoadBalancers(&describeLoadBalancersArgs) | |
36 | ||
37 | if err != nil { | |
38 | t.Fatalf("Failed to DescribeLoadBalancers: %v", err) | |
39 | } | |
40 | t.Logf("DescribeLoadBalancers result: %++v", loadBalancers) | |
41 | ||
42 | err = client.SetLoadBalancerStatus(lbId, InactiveStatus) | |
43 | if err != nil { | |
44 | t.Fatalf("Failed to SetLoadBalancerStatus: %v", err) | |
45 | } | |
46 | err = client.SetLoadBalancerName(lbId, "test-slb2") | |
47 | if err != nil { | |
48 | t.Fatalf("Failed to SetLoadBalancerName: %v", err) | |
49 | } | |
50 | loadBalancer, err := client.DescribeLoadBalancerAttribute(lbId) | |
51 | ||
52 | if err != nil { | |
53 | t.Fatalf("Failed to DescribeLoadBalancerAttribute: %v", err) | |
54 | } | |
55 | t.Logf("DescribeLoadBalancerAttribute result: %++v", loadBalancer) | |
56 | ||
57 | err = client.DeleteLoadBalancer(lbId) | |
58 | if err != nil { | |
59 | t.Errorf("Failed to DeleteLoadBalancer: %v", err) | |
60 | } | |
61 | ||
62 | t.Logf("DeleteLoadBalancer successfully: %s", lbId) | |
63 | ||
64 | } | |
65 | ||
66 | func TestLoadBalancerIPv6(t *testing.T) { | |
67 | ||
68 | client := NewTestClientForDebug() | |
69 | ||
70 | creationArgs := CreateLoadBalancerArgs{ | |
71 | RegionId: common.Hangzhou, | |
72 | LoadBalancerName: "test-slb-ipv6", | |
73 | AddressType: InternetAddressType, | |
74 | MasterZoneId: "cn-hangzhou-e", | |
75 | SlaveZoneId: "cn-hangzhou-f", | |
76 | ClientToken: client.GenerateClientToken(), | |
77 | AddressIPVersion: IPv6, | |
78 | } | |
79 | ||
80 | response, err := client.CreateLoadBalancer(&creationArgs) | |
81 | if err != nil { | |
82 | t.Fatalf("Failed to CreateLoadBalancer: %v", err) | |
83 | } | |
84 | ||
85 | t.Logf("CreateLoadBalancer result: %v", *response) | |
86 | lbId := response.LoadBalancerId | |
87 | ||
88 | describeLoadBalancersArgs := DescribeLoadBalancersArgs{ | |
89 | RegionId: common.Hangzhou, | |
32 | 90 | } |
33 | 91 | |
34 | 92 | loadBalancers, err := client.DescribeLoadBalancers(&describeLoadBalancersArgs) |
78 | 136 | t.Logf("Result = %++v", slbs) |
79 | 137 | } |
80 | 138 | } |
139 | ||
140 | func TestClient_SetLoadBalancerDeleteProtection(t *testing.T) { | |
141 | client := NewTestNewSLBClientForDebug() | |
142 | ||
143 | creationArgs := CreateLoadBalancerArgs{ | |
144 | RegionId: common.Beijing, | |
145 | LoadBalancerName: "test-slb", | |
146 | LoadBalancerSpec: S2Medium, | |
147 | AddressType: InternetAddressType, | |
148 | ClientToken: client.GenerateClientToken(), | |
149 | } | |
150 | ||
151 | response, err := client.CreateLoadBalancer(&creationArgs) | |
152 | if err != nil { | |
153 | t.Fatalf("Failed to CreateLoadBalancer: %v", err) | |
154 | } | |
155 | ||
156 | t.Logf("CreateLoadBalancer result: %v", *response) | |
157 | lbId := response.LoadBalancerId | |
158 | ||
159 | args := &SetLoadBalancerDeleteProtectionArgs{ | |
160 | LoadBalancerId: lbId, | |
161 | DeleteProtection: OnFlag, | |
162 | RegionId: common.Beijing, | |
163 | } | |
164 | ||
165 | err = client.SetLoadBalancerDeleteProtection(args) | |
166 | if err != nil { | |
167 | t.Fatalf("Failed %++v", err) | |
168 | } | |
169 | t.Logf("SetLoadBalancerDeleteProtection result: %v", *response) | |
170 | ||
171 | err = client.DeleteLoadBalancer(lbId) | |
172 | if err != nil { | |
173 | t.Logf("DeleteLoadBalancer result: %++v", err) | |
174 | } else { | |
175 | t.Fatalf("Failed to set LoadBalancer delete protection.") | |
176 | } | |
177 | } | |
178 | ||
179 | func TestClient_SetLoadBalancerModificationProtection(t *testing.T) { | |
180 | client := NewTestNewSLBClientForDebug() | |
181 | ||
182 | creationArgs := CreateLoadBalancerArgs{ | |
183 | RegionId: common.Beijing, | |
184 | LoadBalancerName: "test-slb-modification-protection", | |
185 | LoadBalancerSpec: S1Small, | |
186 | AddressType: InternetAddressType, | |
187 | ModificationProtectionStatus: ConsoleProtection, | |
188 | ModificationProtectionReason: "kubernetes.do.not.delete", | |
189 | ClientToken: client.GenerateClientToken(), | |
190 | } | |
191 | response, err := client.CreateLoadBalancer(&creationArgs) | |
192 | if err != nil { | |
193 | t.Fatalf("Failed to CreateLoadBalancer: %v", err) | |
194 | } | |
195 | ||
196 | t.Logf("CreateLoadBalancer result: %v", *response) | |
197 | lbId := response.LoadBalancerId | |
198 | ||
199 | lb, err := client.DescribeLoadBalancerAttribute(lbId) | |
200 | if err != nil { | |
201 | t.Fatalf("Failed to DescribeLoadBalancerAttribute: %v", err) | |
202 | } | |
203 | ||
204 | if lb.ModificationProtectionStatus != ConsoleProtection { | |
205 | t.Fatalf("Failed to SetLoadBalancerModificationProtection, slb %s, expected %s got %s", | |
206 | lbId, ConsoleProtection, lb.ModificationProtectionStatus) | |
207 | } | |
208 | ||
209 | args := SetLoadBalancerModificationProtectionArgs{ | |
210 | RegionId: common.Beijing, | |
211 | LoadBalancerId: lbId, | |
212 | ModificationProtectionStatus: NonProtection, | |
213 | } | |
214 | ||
215 | err = client.SetLoadBalancerModificationProtection(&args) | |
216 | if err != nil { | |
217 | t.Fatalf("Failed to SetLoadBalancerModificationProtection: %v", err) | |
218 | } | |
219 | ||
220 | lb, err = client.DescribeLoadBalancerAttribute(lbId) | |
221 | if err != nil { | |
222 | t.Fatalf("Failed to DescribeLoadBalancerAttribute: %v", err) | |
223 | } | |
224 | ||
225 | if lb.ModificationProtectionStatus != NonProtection { | |
226 | t.Fatalf("Failed to SetLoadBalancerModificationProtection, slb %s, expected %s got %s", | |
227 | lbId, ConsoleProtection, lb.ModificationProtectionStatus) | |
228 | } | |
229 | ||
230 | // Delete Slb | |
231 | err = client.DeleteLoadBalancer(lbId) | |
232 | if err != nil { | |
233 | t.Fatalf("Failed to DeleteLoadBalancer: %v", err) | |
234 | } | |
235 | ||
236 | } | |
237 | ||
238 | func TestClient_ServiceManagedControl(t *testing.T) { | |
239 | client := NewTestNewSLBClientForDebug() | |
240 | ||
241 | creationArgs := CreateLoadBalancerArgs{ | |
242 | RegionId: common.Beijing, | |
243 | LoadBalancerName: "test-slb-modification-protection", | |
244 | LoadBalancerSpec: S1Small, | |
245 | AddressType: InternetAddressType, | |
246 | ModificationProtectionStatus: ConsoleProtection, | |
247 | ModificationProtectionReason: "kubernetes.do.not.delete", | |
248 | ClientToken: client.GenerateClientToken(), | |
249 | } | |
250 | response, err := client.CreateLoadBalancer(&creationArgs) | |
251 | if err != nil { | |
252 | t.Fatalf("Failed to CreateLoadBalancer: %v", err) | |
253 | } | |
254 | ||
255 | t.Logf("CreateLoadBalancer result: %v", *response) | |
256 | lbId := response.LoadBalancerId | |
257 | ||
258 | lb, err := client.DescribeLoadBalancerAttribute(lbId) | |
259 | if err != nil { | |
260 | t.Fatalf("Failed to DescribeLoadBalancerAttribute: %v", err) | |
261 | } | |
262 | ||
263 | resource := make([]ManagedResourceModel, 0) | |
264 | resource = append(resource, ManagedResourceModel{ResourceId: lb.LoadBalancerId}) | |
265 | args := ServiceManagedControlArgs{ | |
266 | RegionId: common.Beijing, | |
267 | ServiceManagedMode: Managed, | |
268 | ResourceType: ManagedLoadBalancer, | |
269 | Resources: resource, | |
270 | } | |
271 | ||
272 | err = client.ServiceManagedControl(&args) | |
273 | if err != nil { | |
274 | t.Fatalf("Failed to modify resource managed status: %v", err) | |
275 | } | |
276 | ||
277 | lb, err = client.DescribeLoadBalancerAttribute(lbId) | |
278 | if err != nil { | |
279 | t.Fatalf("Failed to DescribeLoadBalancerAttribute: %v", err) | |
280 | } | |
281 | ||
282 | if lb.ServiceManagedMode != Managed { | |
283 | t.Fatalf("Failed to modify resource managed status, slb %s, expected %s got %s", | |
284 | lbId, Managed, lb.ServiceManagedMode) | |
285 | } | |
286 | ||
287 | // Delete Slb | |
288 | err = client.DeleteLoadBalancer(lbId) | |
289 | if err != nil { | |
290 | t.Fatalf("Failed to DeleteLoadBalancer: %v", err) | |
291 | } | |
292 | ||
293 | } |
10 | 10 | client := NewTestClientForDebug() |
11 | 11 | |
12 | 12 | rulesArr := []Rule{ |
13 | Rule{RuleName: "rule-001", Domain: "datapaking.com", Url: "/rule0001", VServerGroupId: TestVServerGroupID}, | |
14 | Rule{RuleName: "rule-002", Domain: "datapaking.com", Url: "/rule0002", VServerGroupId: TestVServerGroupID}, | |
13 | {RuleName: "rule-001", Domain: "datapaking.com", Url: "/rule0001", VServerGroupId: TestVServerGroupID}, | |
14 | {RuleName: "rule-002", Domain: "datapaking.com", Url: "/rule0002", VServerGroupId: TestVServerGroupID}, | |
15 | 15 | } |
16 | 16 | ruleStr, _ := json.Marshal(rulesArr) |
17 | 17 |
1 | 1 | |
2 | 2 | import ( |
3 | 3 | "encoding/json" |
4 | ||
5 | 4 | "github.com/denverdino/aliyungo/common" |
6 | 5 | ) |
7 | 6 | |
62 | 61 | |
63 | 62 | type RemoveBackendServersArgs struct { |
64 | 63 | LoadBalancerId string |
65 | BackendServers []string | |
64 | BackendServers string | |
66 | 65 | } |
67 | 66 | |
68 | 67 | type RemoveBackendServersResponse struct { |
76 | 75 | // RemoveBackendServers Remove backend servers |
77 | 76 | // |
78 | 77 | // You can read doc at http://docs.aliyun.com/#/pub/slb/api-reference/api-related-backendserver&RemoveBackendServers |
79 | func (client *Client) RemoveBackendServers(loadBalancerId string, backendServers []string) (result []BackendServerType, err error) { | |
78 | func (client *Client) RemoveBackendServers(loadBalancerId string, backendServers []BackendServerType) (result []BackendServerType, err error) { | |
79 | bytes, _ := json.Marshal(backendServers) | |
80 | ||
80 | 81 | args := &RemoveBackendServersArgs{ |
81 | 82 | LoadBalancerId: loadBalancerId, |
82 | BackendServers: backendServers, | |
83 | BackendServers: string(bytes), | |
83 | 84 | } |
84 | 85 | response := &RemoveBackendServersResponse{} |
86 | ||
85 | 87 | err = client.Invoke("RemoveBackendServers", args, response) |
86 | 88 | if err != nil { |
87 | 89 | return nil, err |
4 | 4 | func testBackendServers(t *testing.T, client *Client, loadBalancerId string) { |
5 | 5 | |
6 | 6 | backendServers := []BackendServerType{ |
7 | BackendServerType{ | |
7 | { | |
8 | 8 | ServerId: TestInstanceId, |
9 | 9 | Weight: 100, |
10 | Type: "ecs", | |
10 | 11 | }, |
12 | //BackendServerType{ | |
13 | // ServerId: TestENIId, | |
14 | // Weight: 100, | |
15 | // Type: "eni", | |
16 | //}, | |
11 | 17 | } |
12 | 18 | |
13 | 19 | servers, err := client.AddBackendServers(loadBalancerId, backendServers) |
28 | 34 | |
29 | 35 | t.Logf("Backend servers: %++v", servers) |
30 | 36 | |
31 | servers, err = client.RemoveBackendServers(loadBalancerId, []string{TestInstanceId}) | |
37 | servers, err = client.RemoveBackendServers(loadBalancerId, backendServers) | |
32 | 38 | if err != nil { |
33 | 39 | t.Errorf("Failed to RemoveBackendServers: %v", err) |
34 | 40 | } |
10 | 10 | client := NewTestClientForDebug() |
11 | 11 | |
12 | 12 | tagItemArr := []TagItem{ |
13 | TagItem{TagKey: "username", TagValue: "test"}, | |
14 | TagItem{TagKey: "birdthday", TagValue: "20170101"}, | |
13 | {TagKey: "username", TagValue: "test"}, | |
14 | {TagKey: "birdthday", TagValue: "20170101"}, | |
15 | 15 | } |
16 | 16 | tagItems, _ := json.Marshal(tagItemArr) |
17 | 17 | |
33 | 33 | client := NewTestClientForDebug() |
34 | 34 | |
35 | 35 | tagItemArr := []TagItem{ |
36 | TagItem{TagKey: "username", TagValue: "test"}, | |
37 | TagItem{TagKey: "birdthday", TagValue: "20170101"}, | |
36 | {TagKey: "username", TagValue: "test"}, | |
37 | {TagKey: "birdthday", TagValue: "20170101"}, | |
38 | 38 | } |
39 | 39 | tagItems, _ := json.Marshal(tagItemArr) |
40 | 40 |
4 | 4 | ) |
5 | 5 | |
6 | 6 | type VBackendServerType struct { |
7 | ServerId string | |
8 | Weight int | |
9 | Port int | |
10 | Type string | |
7 | ServerId string | |
8 | Weight int | |
9 | Port int | |
10 | Type string | |
11 | ServerIp string | |
12 | Description string | |
11 | 13 | } |
12 | 14 | |
13 | 15 | type VServerGroup struct { |
16 | RegionId common.Region | |
14 | 17 | VServerGroupName string |
15 | 18 | VServerGroupId string |
16 | 19 | } |
50 | 53 | } |
51 | 54 | |
52 | 55 | type DescribeVServerGroupsArgs struct { |
53 | LoadBalancerId string | |
54 | RegionId common.Region | |
56 | LoadBalancerId string | |
57 | RegionId common.Region | |
58 | IncludeRule bool | |
59 | IncludeListener bool | |
55 | 60 | } |
56 | 61 | |
57 | 62 | type DescribeVServerGroupAttributeArgs struct { |
82 | 87 | VServerGroups struct { |
83 | 88 | VServerGroup []VServerGroup |
84 | 89 | } |
90 | AssociatedObjects struct { | |
91 | Listeners string | |
92 | Rules string | |
93 | } | |
85 | 94 | } |
86 | type DescribeVServerGroupAttributeResponse CreateVServerGroupResponse | |
95 | type DescribeVServerGroupAttributeResponse struct { | |
96 | common.Response | |
97 | VServerGroupId string | |
98 | VServerGroupName string | |
99 | LoadBalancerId string | |
100 | BackendServers VBackendServers | |
101 | } | |
87 | 102 | |
88 | 103 | func (client *Client) CreateVServerGroup(args *CreateVServerGroupArgs) (response *CreateVServerGroupResponse, err error) { |
89 | 104 | response = &CreateVServerGroupResponse{} |
2 | 2 | import ( |
3 | 3 | "encoding/json" |
4 | 4 | "testing" |
5 | ||
6 | "fmt" | |
5 | 7 | |
6 | 8 | "github.com/denverdino/aliyungo/common" |
7 | 9 | ) |
56 | 58 | |
57 | 59 | func TestDescribeVServerGroups(t *testing.T) { |
58 | 60 | arg := &DescribeVServerGroupsArgs{ |
59 | LoadBalancerId: loadBalancerId, | |
60 | RegionId: region, | |
61 | LoadBalancerId: loadBalancerId, | |
62 | RegionId: region, | |
63 | IncludeListener: true, | |
64 | IncludeRule: true, | |
61 | 65 | } |
62 | 66 | response, err := client.DescribeVServerGroups(arg) |
63 | 67 | if err != nil { |
64 | 68 | t.Error(err) |
65 | 69 | } else { |
66 | t.Log(response) | |
67 | for _, vserverGroup := range response.VServerGroups.VServerGroup { | |
68 | deleteVServerGroupIdList = append(deleteVServerGroupIdList, vserverGroup.VServerGroupId) | |
69 | } | |
70 | fmt.Println(PrettyJson(response)) | |
70 | 71 | } |
71 | 72 | } |
72 | 73 |
0 | package slb | |
1 | ||
2 | import ( | |
3 | "github.com/denverdino/aliyungo/common" | |
4 | ) | |
5 | ||
6 | type DescribeZonesArgs struct { | |
7 | RegionId common.Region | |
8 | } | |
9 | ||
10 | // | |
11 | // You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&zonetype | |
12 | type ZoneType struct { | |
13 | ZoneId string | |
14 | LocalName string | |
15 | SlaveZones struct { | |
16 | SlaveZone []ZoneType | |
17 | } | |
18 | } | |
19 | ||
20 | type DescribeZonesResponse struct { | |
21 | common.Response | |
22 | Zones struct { | |
23 | Zone []ZoneType | |
24 | } | |
25 | } | |
26 | ||
27 | // DescribeZones describes zones | |
28 | func (client *Client) DescribeZones(regionId common.Region) (zones []ZoneType, err error) { | |
29 | response, err := client.DescribeZonesWithRaw(regionId) | |
30 | if err == nil { | |
31 | return response.Zones.Zone, nil | |
32 | } | |
33 | ||
34 | return []ZoneType{}, err | |
35 | } | |
36 | ||
37 | func (client *Client) DescribeZonesWithRaw(regionId common.Region) (response *DescribeZonesResponse, err error) { | |
38 | args := DescribeZonesArgs{ | |
39 | RegionId: regionId, | |
40 | } | |
41 | response = &DescribeZonesResponse{} | |
42 | ||
43 | err = client.Invoke("DescribeZones", &args, response) | |
44 | ||
45 | if err == nil { | |
46 | return response, nil | |
47 | } | |
48 | ||
49 | return nil, err | |
50 | } |
0 | package slb | |
1 | ||
2 | import ( | |
3 | "github.com/denverdino/aliyungo/common" | |
4 | "testing" | |
5 | ) | |
6 | ||
7 | func TestDescribeZones(t *testing.T) { | |
8 | ||
9 | client := NewTestNewSLBClientForDebug() | |
10 | ||
11 | zones, err := client.DescribeZones(common.Hangzhou) | |
12 | ||
13 | if err == nil { | |
14 | t.Logf("regions: %v", zones) | |
15 | } else { | |
16 | t.Errorf("Failed to DescribeZones: %v", err) | |
17 | } | |
18 | ||
19 | } |
25 | 25 | |
26 | 26 | func (client *Client) SetDebug(debug bool) { |
27 | 27 | client.debug = debug |
28 | } | |
29 | ||
30 | // SetTransport sets transport to the http client | |
31 | func (client *Client) SetTransport(transport http.RoundTripper) { | |
32 | if client.httpClient == nil { | |
33 | client.httpClient = &http.Client{} | |
34 | } | |
35 | client.httpClient.Transport = transport | |
28 | 36 | } |
29 | 37 | |
30 | 38 | type Project struct { |
0 | 0 | package sls |
1 | 1 | |
2 | import "encoding/json" | |
2 | import ( | |
3 | "encoding/json" | |
4 | ) | |
3 | 5 | |
4 | 6 | type IndexLineConfig struct { |
5 | 7 | TokenList []string `json:"token,omitempty"` |
6 | 8 | CaseSensitive bool `json:"caseSensitive"` |
7 | 9 | IncludeKeys []string `json:"include_keys,omitempty"` |
8 | Exclude_keys []string `json:"exclude_keys,omitempty"` | |
10 | ExcludeKeys []string `json:"exclude_keys,omitempty"` | |
9 | 11 | } |
10 | 12 | |
11 | 13 | type IndexKeyConfig struct { |
14 | Type string `json:"type,omitempty"` | |
15 | Alias string `json:"alias,omitempty"` | |
16 | Chn bool `json:"chn"` | |
12 | 17 | TokenList []string `json:"token,omitempty"` |
13 | CaseSensitive bool `json:"caseSensitive,omitempty"` | |
18 | CaseSensitive bool `json:"caseSensitive"` | |
19 | DocValue bool `json:"doc_value"` | |
14 | 20 | } |
15 | 21 | |
16 | 22 | type IndexConfig struct { |
17 | 23 | TTL int `json:"ttl,omitempty"` |
18 | LineConfig IndexLineConfig `json:"line,omitempty"` | |
24 | LineConfig *IndexLineConfig `json:"line,omitempty"` | |
19 | 25 | KeyConfigList map[string]IndexKeyConfig `json:"keys,omitempty"` |
20 | 26 | } |
21 | 27 |
9 | 9 | p := DefaultProject(t) |
10 | 10 | config := &IndexConfig{ |
11 | 11 | TTL: 7, |
12 | LineConfig: IndexLineConfig{ | |
12 | LineConfig: &IndexLineConfig{ | |
13 | 13 | TokenList: []string{",", "\t", "\n", " ", ";"}, |
14 | 14 | CaseSensitive: false, |
15 | 15 | }, |
1 | 1 | |
2 | 2 | import ( |
3 | 3 | "encoding/json" |
4 | "errors" | |
5 | 4 | "fmt" |
6 | 5 | "strconv" |
7 | 6 | ) |
153 | 152 | return v, nil |
154 | 153 | } |
155 | 154 | |
156 | return nil, errors.New(fmt.Sprintf("%v is not a string array", configs["config"])) | |
155 | return nil, fmt.Errorf("%v is not a string array", configs["config"]) | |
157 | 156 | } |
7 | 7 | "io/ioutil" |
8 | 8 | "log" |
9 | 9 | "net/http" |
10 | "net/http/httputil" | |
10 | 11 | "net/url" |
11 | 12 | "strconv" |
12 | 13 | "time" |
90 | 91 | if err != nil { |
91 | 92 | return nil, err |
92 | 93 | } |
94 | if client.debug { | |
95 | reqDump, _ := httputil.DumpRequest(hreq, true) | |
96 | log.Printf("---------------REQUEST---------------\n%s\n\n", string(reqDump)) | |
97 | } | |
93 | 98 | t0 := time.Now() |
94 | 99 | resp, err := client.httpClient.Do(hreq) |
95 | 100 | t1 := time.Now() |
96 | 101 | if err != nil { |
97 | 102 | return nil, err |
98 | 103 | } |
99 | ||
100 | 104 | if client.debug { |
105 | resDump, _ := httputil.DumpResponse(resp, true) | |
106 | log.Printf("---------------RESPONSE---------------\n%s\n\n", string(resDump)) | |
101 | 107 | log.Printf("Invoke %s %s %d (%v)", req.method, req.url(), resp.StatusCode, t1.Sub(t0)) |
102 | 108 | } |
103 | 109 |
50 | 50 | canonicalizedResource := req.path |
51 | 51 | var paramNames []string |
52 | 52 | if req.params != nil && len(req.params) > 0 { |
53 | for k, _ := range req.params { | |
53 | for k := range req.params { | |
54 | 54 | paramNames = append(paramNames, k) |
55 | 55 | } |
56 | 56 | sort.Strings(paramNames) |
68 | 68 | func canonicalizeHeader(headers map[string]string) string { |
69 | 69 | var canonicalizedHeaders []string |
70 | 70 | |
71 | for k, _ := range headers { | |
71 | for k := range headers { | |
72 | 72 | if lower := strings.ToLower(k); strings.HasPrefix(lower, HeaderSLSPrefix1) || strings.HasPrefix(lower, HeaderSLSPrefix2) { |
73 | 73 | canonicalizedHeaders = append(canonicalizedHeaders, lower) |
74 | 74 | } |
25 | 25 | |
26 | 26 | princpalPolicyDocument = ram.AssumeRolePolicyDocument{ |
27 | 27 | Statement: []ram.AssumeRolePolicyItem{ |
28 | ram.AssumeRolePolicyItem{Action: "sts:AssumeRole", Effect: "Allow", Principal: princpal}, | |
28 | {Action: "sts:AssumeRole", Effect: "Allow", Principal: princpal}, | |
29 | 29 | }, |
30 | 30 | Version: "1"} |
31 | 31 | |
38 | 38 | |
39 | 39 | var policyDocument = ram.PolicyDocument{ |
40 | 40 | Statement: []ram.PolicyItem{ |
41 | ram.PolicyItem{ | |
41 | { | |
42 | 42 | Action: "oss:GetObject", |
43 | 43 | Effect: "Allow", |
44 | 44 | Resource: "acs:oss:*:*:*/anyprefix", |
65 | 65 | func createPolicyDocument() *ram.PolicyDocument { |
66 | 66 | return &ram.PolicyDocument{ |
67 | 67 | Statement: []ram.PolicyItem{ |
68 | ram.PolicyItem{ | |
68 | { | |
69 | 69 | Action: "oss:GetObject", |
70 | 70 | Effect: "Allow", |
71 | 71 | Resource: "acs:oss:*:*:*/*", |
13 | 13 | got := make([]time.Duration, 0, len(want)) // avoid allocation when testing timing |
14 | 14 | t0 := time.Now() |
15 | 15 | for a := testAttempt.Start(); a.Next(); { |
16 | got = append(got, time.Now().Sub(t0)) | |
16 | got = append(got, time.Since(t0)) | |
17 | 17 | } |
18 | got = append(got, time.Now().Sub(t0)) | |
18 | got = append(got, time.Since(t0)) | |
19 | 19 | if len(got) != len(want) { |
20 | 20 | t.Fatalf("Failed!") |
21 | 21 | } |
46 | 46 | // add to support url.Values |
47 | 47 | mapValues, ok := i.(url.Values) |
48 | 48 | if ok { |
49 | for k, _ := range mapValues { | |
49 | for k := range mapValues { | |
50 | 50 | values.Set(k, mapValues.Get(k)) |
51 | 51 | } |
52 | 52 | return |
190 | 190 | // add to support url.Values |
191 | 191 | mapValues, ok := i.(url.Values) |
192 | 192 | if ok { |
193 | for k, _ := range mapValues { | |
193 | for k := range mapValues { | |
194 | 194 | values.Set(k, mapValues.Get(k)) |
195 | 195 | } |
196 | 196 | return |
64 | 64 | StringArray: []string{"abc", "xyz"}, |
65 | 65 | StringArray2: []string{"abc", "xyz"}, |
66 | 66 | StructArray: []SubStruct{ |
67 | SubStruct{A: "a", B: 1}, | |
68 | SubStruct{A: "x", B: 2}, | |
67 | {A: "a", B: 1}, | |
68 | {A: "x", B: 2}, | |
69 | 69 | }, |
70 | 70 | SubStruct: SubStruct{A: "M", B: 0}, |
71 | 71 | test: TestString("test"), |
3 | 3 | "bytes" |
4 | 4 | srand "crypto/rand" |
5 | 5 | "encoding/binary" |
6 | "encoding/json" | |
7 | "fmt" | |
6 | 8 | "math/rand" |
7 | 9 | "net/http" |
8 | 10 | "net/url" |
57 | 59 | if v != "" { |
58 | 60 | buf.WriteString("=") |
59 | 61 | buf.WriteString(url.QueryEscape(v)) |
62 | } | |
63 | } | |
64 | } | |
65 | return buf.String() | |
66 | } | |
67 | ||
68 | // Like Encode, but key and value are not escaped | |
69 | func EncodeWithoutEscape(v url.Values) string { | |
70 | if v == nil { | |
71 | return "" | |
72 | } | |
73 | var buf bytes.Buffer | |
74 | keys := make([]string, 0, len(v)) | |
75 | for k := range v { | |
76 | keys = append(keys, k) | |
77 | } | |
78 | sort.Strings(keys) | |
79 | for _, k := range keys { | |
80 | vs := v[k] | |
81 | prefix := k | |
82 | for _, v := range vs { | |
83 | if buf.Len() > 0 { | |
84 | buf.WriteByte('&') | |
85 | } | |
86 | buf.WriteString(prefix) | |
87 | if v != "" { | |
88 | buf.WriteString("=") | |
89 | buf.WriteString(v) | |
60 | 90 | } |
61 | 91 | } |
62 | 92 | } |
144 | 174 | return string(s) |
145 | 175 | |
146 | 176 | } |
177 | ||
178 | func PrettyJson(object interface{}) string { | |
179 | b, err := json.MarshalIndent(object, "", " ") | |
180 | if err != nil { | |
181 | fmt.Printf("ERROR: PrettyJson, %v\n %s\n", err, b) | |
182 | } | |
183 | return string(b) | |
184 | } |