mirror of
https://github.com/vxcontrol/external-dns.git
synced 2026-07-19 18:23:33 -04:00
use trash to add aliyun sdk
This commit is contained in:
@@ -0,0 +1 @@
|
||||
.idea
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.7.4
|
||||
|
||||
# let us have speedy Docker-based Travis workers
|
||||
sudo: false
|
||||
|
||||
script:
|
||||
- go get ./...
|
||||
- go vet ./...
|
||||
- go build ./...
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
https://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Copyright 2015-2015 Li Yi (denverdino@gmail.com).
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
+178
@@ -0,0 +1,178 @@
|
||||
# AliyunGo: Go SDK for Aliyun Services
|
||||
|
||||
[](https://travis-ci.org/denverdino/aliyungo) [](https://circleci.com/gh/denverdino/aliyungo) [](https://goreportcard.com/report/github.com/denverdino/aliyungo)
|
||||
|
||||
This is an unofficial Go SDK for Aliyun Services. You are welcome for contribution.
|
||||
|
||||
|
||||
## Package Structure
|
||||
|
||||
* ecs: [Elastic Compute Service](https://help.aliyun.com/document_detail/ecs/open-api/summary.html)
|
||||
* oss: [Open Storage Service](https://help.aliyun.com/document_detail/oss/api-reference/abstract.html)
|
||||
* slb: [Server Load Balancer](https://help.aliyun.com/document_detail/slb/api-reference/brief-introduction.html)
|
||||
* dns: [DNS](https://help.aliyun.com/document_detail/dns/api-reference/summary.html)
|
||||
* sls: [Logging Service](https://help.aliyun.com/document_detail/sls/api/overview.html)
|
||||
* ram: [Resource Access Management](https://help.aliyun.com/document_detail/ram/ram-api-reference/intro/intro.html)
|
||||
* rds: [Relational Database Service](https://help.aliyun.com/document_detail/26226.html)
|
||||
* cms: [Cloud Monitor Service](https://help.aliyun.com/document_detail/28615.html)
|
||||
* cs: [Container Service](https://help.aliyun.com/product/25972.html)
|
||||
* sts: [Security Token Service](https://help.aliyun.com/document_detail/28756.html)
|
||||
* dm: [Direct Mail](https://help.aliyun.com/document_detail/29414.html)
|
||||
* sms: [Short Message Service](https://help.aliyun.com/product/44282.html)
|
||||
* push: [Cloud Mobile Push](https://help.aliyun.com/document_detail/30049.html)
|
||||
* opensearch: [OpenSearch](https://help.aliyun.com/document_detail/29118.html)
|
||||
* mq: [Message Queue](https://help.aliyun.com/document_detail/29532.html)
|
||||
* nas: [Network Attached Storage](https://help.aliyun.com/document_detail/27518.html)
|
||||
* common: Common libary of Aliyun Go SDK
|
||||
* util: Utility helpers
|
||||
|
||||
|
||||
|
||||
## Quick Start
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/denverdino/aliyungo/ecs"
|
||||
)
|
||||
|
||||
const ACCESS_KEY_ID = "<YOUR_ID>"
|
||||
const ACCESS_KEY_SECRET = "<****>"
|
||||
|
||||
func main() {
|
||||
client := ecs.NewClient(ACCESS_KEY_ID, ACCESS_KEY_SECRET)
|
||||
fmt.Print(client.DescribeRegions())
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
* ECS: [https://godoc.org/github.com/denverdino/aliyungo/ecs](https://godoc.org/github.com/denverdino/aliyungo/ecs) [](https://godoc.org/github.com/denverdino/aliyungo/ecs)
|
||||
* OSS: [https://godoc.org/github.com/denverdino/aliyungo/oss](https://godoc.org/github.com/denverdino/aliyungo/oss) [](https://godoc.org/github.com/denverdino/aliyungo/oss)
|
||||
* SLB: [https://godoc.org/github.com/denverdino/aliyungo/slb](https://godoc.org/github.com/denverdino/aliyungo/slb) [](https://godoc.org/github.com/denverdino/aliyungo/slb)
|
||||
* DNS: [https://godoc.org/github.com/denverdino/aliyungo/dns](https://godoc.org/github.com/denverdino/aliyungo/dns) [](https://godoc.org/github.com/denverdino/aliyungo/dns)
|
||||
* SLS: [https://godoc.org/github.com/denverdino/aliyungo/sls](https://godoc.org/github.com/denverdino/aliyungo/sls) [](https://godoc.org/github.com/denverdino/aliyungo/sls)
|
||||
* RAM: [https://godoc.org/github.com/denverdino/aliyungo/ram](https://godoc.org/github.com/denverdino/aliyungo/ram) [](https://godoc.org/github.com/denverdino/aliyungo/ram)
|
||||
* RDS: [https://godoc.org/github.com/denverdino/aliyungo/rds](https://godoc.org/github.com/denverdino/aliyungo/rds) [](https://godoc.org/github.com/denverdino/aliyungo/rds)
|
||||
* CMS: [https://godoc.org/github.com/denverdino/aliyungo/cms](https://godoc.org/github.com/denverdino/aliyungo/cms) [](https://godoc.org/github.com/denverdino/aliyungo/cms)
|
||||
* CS: [https://godoc.org/github.com/denverdino/aliyungo/cs](https://godoc.org/github.com/denverdino/aliyungo/cs) [](https://godoc.org/github.com/denverdino/aliyungo/cs)
|
||||
* STS: [https://godoc.org/github.com/denverdino/aliyungo/sts](https://godoc.org/github.com/denverdino/aliyungo/sts) [](https://godoc.org/github.com/denverdino/aliyungo/sts)
|
||||
* DM: [https://godoc.org/github.com/denverdino/aliyungo/dm](https://godoc.org/github.com/denverdino/aliyungo/dm) [](https://godoc.org/github.com/denverdino/aliyungo/dm)
|
||||
* SMS: [https://godoc.org/github.com/denverdino/aliyungo/sms](https://godoc.org/github.com/denverdino/aliyungo/sms) [](https://godoc.org/github.com/denverdino/aliyungo/sms)
|
||||
* MQ: [https://godoc.org/github.com/denverdino/aliyungo/mq](https://godoc.org/github.com/denverdino/aliyungo/mq) [](https://godoc.org/github.com/denverdino/aliyungo/mq)
|
||||
* NAS: [https://godoc.org/github.com/denverdino/aliyungo/nas](https://godoc.org/github.com/denverdino/aliyungo/nas) [](https://godoc.org/github.com/denverdino/aliyungo/nas)
|
||||
* OPENSEARCH: [https://godoc.org/github.com/denverdino/aliyungo/opensearch](https://godoc.org/github.com/denverdino/aliyungo/opensearch) [](https://godoc.org/github.com/denverdino/aliyungo/opensearch)
|
||||
* PUSH: [https://godoc.org/github.com/denverdino/aliyungo/push](https://godoc.org/github.com/denverdino/aliyungo/push) [](https://godoc.org/github.com/denverdino/aliyungo/push)
|
||||
|
||||
## Build and Install
|
||||
|
||||
go get:
|
||||
|
||||
```sh
|
||||
go get github.com/denverdino/aliyungo
|
||||
```
|
||||
|
||||
|
||||
## Test ECS
|
||||
|
||||
Modify "ecs/config_test.go"
|
||||
|
||||
```sh
|
||||
TestAccessKeyId = "MY_ACCESS_KEY_ID"
|
||||
TestAccessKeySecret = "MY_ACCESS_KEY_ID"
|
||||
TestInstanceId = "MY_INSTANCE_ID"
|
||||
TestIAmRich = false
|
||||
```
|
||||
|
||||
* TestAccessKeyId: the Access Key Id
|
||||
* TestAccessKeySecret: the Access Key Secret.
|
||||
* TestInstanceId: the existing instance id for testing. It will be stopped and restarted during testing.
|
||||
* TestIAmRich(Optional): If it is set to true, it will perform tests to create virtual machines and disks under your account. And you will pay the bill. :-)
|
||||
|
||||
Under "ecs" and run
|
||||
|
||||
```sh
|
||||
go test
|
||||
```
|
||||
|
||||
## Test OSS
|
||||
|
||||
Modify "oss/config_test.go"
|
||||
|
||||
```sh
|
||||
TestAccessKeyId = "MY_ACCESS_KEY_ID"
|
||||
TestAccessKeySecret = "MY_ACCESS_KEY_ID"
|
||||
TestRegion = oss.Beijing
|
||||
TestBucket = "denverdino"
|
||||
```
|
||||
|
||||
* TestAccessKeyId: the Access Key Id
|
||||
* TestAccessKeySecret: the Access Key Secret.
|
||||
* TestRegion: the region of OSS for testing
|
||||
* TestBucket: the bucket name for testing
|
||||
|
||||
|
||||
Under "oss" and run
|
||||
|
||||
```sh
|
||||
go test
|
||||
```
|
||||
|
||||
## Contributors
|
||||
|
||||
* Li Yi (denverdino@gmail.com)
|
||||
* Boshi Lian (farmer1992@gmail.com)
|
||||
* Yu Zhou (oscarrr110@gmail.com)
|
||||
* Yufei Zhang
|
||||
* linuxlikerqq
|
||||
* Changhai Yan
|
||||
* Jizhong Jiang (jiangjizhong@gmail.com)
|
||||
* Kent Wang (pragkent@gmail.com)
|
||||
* ringtail
|
||||
* aiden0z (aiden0xz@gmail.com)
|
||||
* jimmycmh
|
||||
* menglingwei
|
||||
* mingang.he (dustgle@gmail.com)
|
||||
* Young Chen (chainone@gmail.com)
|
||||
* johnzeng
|
||||
* spacexnice (445436286@qq.com)
|
||||
* xiaoheihero
|
||||
* hmgle (dustgle@gmail.com)
|
||||
* jzwlqx (jiangjizhong@gmail.com)
|
||||
* Linhua Tan (toolchainX@gmail.com)
|
||||
* Plutonist (p@vecsight.com)
|
||||
* Bin Liu
|
||||
* wangyue
|
||||
* demonwy
|
||||
* yarous224
|
||||
* yufeizyf (xazyf9111@sina.cn)
|
||||
* keontang (ikeontang@gmail.com)
|
||||
* Cholerae Hu (me@cholerae.com)
|
||||
* Zach Bergh (berghzach@gmail.com)
|
||||
* Bingshen Wang
|
||||
* xiaozhu36
|
||||
* Russell (yufeiwu@gmail.com)
|
||||
* zhuzhih2017
|
||||
* cheyang
|
||||
* Hobo Chen
|
||||
* Shuwei Yin
|
||||
|
||||
|
||||
## License
|
||||
This project is licensed under the Apache License, Version 2.0. See [LICENSE](https://github.com/denverdino/aliyungo/blob/master/LICENSE.txt) for the full license text.
|
||||
|
||||
|
||||
## Related projects
|
||||
|
||||
* Aliyun ECS driver for Docker Machine: [Pull request](https://github.com/docker/machine/pull/1182)
|
||||
|
||||
* Aliyun OSS driver for Docker Registry V2: [Pull request](https://github.com/docker/distribution/pull/514)
|
||||
|
||||
|
||||
## References
|
||||
|
||||
The GO API design of OSS refer the implementation from [https://github.com/AdRoll/goamz](https://github.com/AdRoll)
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
machine:
|
||||
environment:
|
||||
GODIST: "go1.7.5.linux-amd64.tar.gz"
|
||||
services:
|
||||
- docker
|
||||
|
||||
dependencies:
|
||||
override:
|
||||
- go get -t -d -v ./...
|
||||
|
||||
test:
|
||||
override:
|
||||
- go vet ./...
|
||||
+357
@@ -0,0 +1,357 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/denverdino/aliyungo/util"
|
||||
)
|
||||
|
||||
// RemovalPolicy.N add index to array item
|
||||
// RemovalPolicy=["a", "b"] => RemovalPolicy.1="a" RemovalPolicy.2="b"
|
||||
type FlattenArray []string
|
||||
|
||||
// string contains underline which will be replaced with dot
|
||||
// SystemDisk_Category => SystemDisk.Category
|
||||
type UnderlineString string
|
||||
|
||||
// A Client represents a client of ECS services
|
||||
type Client struct {
|
||||
AccessKeyId string //Access Key Id
|
||||
AccessKeySecret string //Access Key Secret
|
||||
debug bool
|
||||
httpClient *http.Client
|
||||
endpoint string
|
||||
version string
|
||||
serviceCode string
|
||||
regionID Region
|
||||
businessInfo string
|
||||
userAgent string
|
||||
}
|
||||
|
||||
// NewClient creates a new instance of ECS client
|
||||
func (client *Client) Init(endpoint, version, accessKeyId, accessKeySecret string) {
|
||||
client.AccessKeyId = accessKeyId
|
||||
client.AccessKeySecret = accessKeySecret + "&"
|
||||
client.debug = false
|
||||
client.httpClient = &http.Client{}
|
||||
client.endpoint = endpoint
|
||||
client.version = version
|
||||
}
|
||||
|
||||
func (client *Client) NewInit(endpoint, version, accessKeyId, accessKeySecret, serviceCode string, regionID Region) {
|
||||
client.Init(endpoint, version, accessKeyId, accessKeySecret)
|
||||
client.serviceCode = serviceCode
|
||||
client.regionID = regionID
|
||||
client.setEndpointByLocation(regionID, serviceCode, accessKeyId, accessKeySecret)
|
||||
}
|
||||
|
||||
//NewClient using location service
|
||||
func (client *Client) setEndpointByLocation(region Region, serviceCode, accessKeyId, accessKeySecret string) {
|
||||
locationClient := NewLocationClient(accessKeyId, accessKeySecret)
|
||||
ep := locationClient.DescribeOpenAPIEndpoint(region, serviceCode)
|
||||
if ep == "" {
|
||||
ep = loadEndpointFromFile(region, serviceCode)
|
||||
}
|
||||
|
||||
if ep != "" {
|
||||
client.endpoint = ep
|
||||
}
|
||||
}
|
||||
|
||||
// SetEndpoint sets custom endpoint
|
||||
func (client *Client) SetEndpoint(endpoint string) {
|
||||
client.endpoint = endpoint
|
||||
}
|
||||
|
||||
// SetEndpoint sets custom version
|
||||
func (client *Client) SetVersion(version string) {
|
||||
client.version = version
|
||||
}
|
||||
|
||||
func (client *Client) SetRegionID(regionID Region) {
|
||||
client.regionID = regionID
|
||||
}
|
||||
|
||||
//SetServiceCode sets serviceCode
|
||||
func (client *Client) SetServiceCode(serviceCode string) {
|
||||
client.serviceCode = serviceCode
|
||||
}
|
||||
|
||||
// SetAccessKeyId sets new AccessKeyId
|
||||
func (client *Client) SetAccessKeyId(id string) {
|
||||
client.AccessKeyId = id
|
||||
}
|
||||
|
||||
// SetAccessKeySecret sets new AccessKeySecret
|
||||
func (client *Client) SetAccessKeySecret(secret string) {
|
||||
client.AccessKeySecret = secret + "&"
|
||||
}
|
||||
|
||||
// SetDebug sets debug mode to log the request/response message
|
||||
func (client *Client) SetDebug(debug bool) {
|
||||
client.debug = debug
|
||||
}
|
||||
|
||||
// SetBusinessInfo sets business info to log the request/response message
|
||||
func (client *Client) SetBusinessInfo(businessInfo string) {
|
||||
if strings.HasPrefix(businessInfo, "/") {
|
||||
client.businessInfo = businessInfo
|
||||
} else if businessInfo != "" {
|
||||
client.businessInfo = "/" + businessInfo
|
||||
}
|
||||
}
|
||||
|
||||
// SetUserAgent sets user agent to the request/response message
|
||||
func (client *Client) SetUserAgent(userAgent string) {
|
||||
client.userAgent = userAgent
|
||||
}
|
||||
|
||||
// Invoke sends the raw HTTP request for ECS services
|
||||
func (client *Client) Invoke(action string, args interface{}, response interface{}) error {
|
||||
|
||||
request := Request{}
|
||||
request.init(client.version, action, client.AccessKeyId)
|
||||
|
||||
query := util.ConvertToQueryValues(request)
|
||||
util.SetQueryValues(args, &query)
|
||||
|
||||
// Sign request
|
||||
signature := util.CreateSignatureForRequest(ECSRequestMethod, &query, client.AccessKeySecret)
|
||||
|
||||
// Generate the request URL
|
||||
requestURL := client.endpoint + "?" + query.Encode() + "&Signature=" + url.QueryEscape(signature)
|
||||
|
||||
httpReq, err := http.NewRequest(ECSRequestMethod, requestURL, nil)
|
||||
|
||||
if err != nil {
|
||||
return GetClientError(err)
|
||||
}
|
||||
|
||||
// TODO move to util and add build val flag
|
||||
httpReq.Header.Set("X-SDK-Client", `AliyunGO/`+Version+client.businessInfo)
|
||||
|
||||
httpReq.Header.Set("User-Agent", httpReq.UserAgent()+ " " +client.userAgent)
|
||||
|
||||
t0 := time.Now()
|
||||
httpResp, err := client.httpClient.Do(httpReq)
|
||||
t1 := time.Now()
|
||||
if err != nil {
|
||||
return GetClientError(err)
|
||||
}
|
||||
statusCode := httpResp.StatusCode
|
||||
|
||||
if client.debug {
|
||||
log.Printf("Invoke %s %s %d (%v)", ECSRequestMethod, requestURL, statusCode, t1.Sub(t0))
|
||||
}
|
||||
|
||||
defer httpResp.Body.Close()
|
||||
body, err := ioutil.ReadAll(httpResp.Body)
|
||||
|
||||
if err != nil {
|
||||
return GetClientError(err)
|
||||
}
|
||||
|
||||
if client.debug {
|
||||
var prettyJSON bytes.Buffer
|
||||
err = json.Indent(&prettyJSON, body, "", " ")
|
||||
log.Println(string(prettyJSON.Bytes()))
|
||||
}
|
||||
|
||||
if statusCode >= 400 && statusCode <= 599 {
|
||||
errorResponse := ErrorResponse{}
|
||||
err = json.Unmarshal(body, &errorResponse)
|
||||
ecsError := &Error{
|
||||
ErrorResponse: errorResponse,
|
||||
StatusCode: statusCode,
|
||||
}
|
||||
return ecsError
|
||||
}
|
||||
|
||||
err = json.Unmarshal(body, response)
|
||||
//log.Printf("%++v", response)
|
||||
if err != nil {
|
||||
return GetClientError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Invoke sends the raw HTTP request for ECS services
|
||||
func (client *Client) InvokeByFlattenMethod(action string, args interface{}, response interface{}) error {
|
||||
|
||||
request := Request{}
|
||||
request.init(client.version, action, client.AccessKeyId)
|
||||
|
||||
query := util.ConvertToQueryValues(request)
|
||||
|
||||
util.SetQueryValueByFlattenMethod(args, &query)
|
||||
|
||||
// Sign request
|
||||
signature := util.CreateSignatureForRequest(ECSRequestMethod, &query, client.AccessKeySecret)
|
||||
|
||||
// Generate the request URL
|
||||
requestURL := client.endpoint + "?" + query.Encode() + "&Signature=" + url.QueryEscape(signature)
|
||||
|
||||
httpReq, err := http.NewRequest(ECSRequestMethod, requestURL, nil)
|
||||
|
||||
if err != nil {
|
||||
return GetClientError(err)
|
||||
}
|
||||
|
||||
// TODO move to util and add build val flag
|
||||
httpReq.Header.Set("X-SDK-Client", `AliyunGO/`+Version+client.businessInfo)
|
||||
|
||||
httpReq.Header.Set("User-Agent", httpReq.UserAgent()+ " " +client.userAgent)
|
||||
|
||||
t0 := time.Now()
|
||||
httpResp, err := client.httpClient.Do(httpReq)
|
||||
t1 := time.Now()
|
||||
if err != nil {
|
||||
return GetClientError(err)
|
||||
}
|
||||
statusCode := httpResp.StatusCode
|
||||
|
||||
if client.debug {
|
||||
log.Printf("Invoke %s %s %d (%v)", ECSRequestMethod, requestURL, statusCode, t1.Sub(t0))
|
||||
}
|
||||
|
||||
defer httpResp.Body.Close()
|
||||
body, err := ioutil.ReadAll(httpResp.Body)
|
||||
|
||||
if err != nil {
|
||||
return GetClientError(err)
|
||||
}
|
||||
|
||||
if client.debug {
|
||||
var prettyJSON bytes.Buffer
|
||||
err = json.Indent(&prettyJSON, body, "", " ")
|
||||
log.Println(string(prettyJSON.Bytes()))
|
||||
}
|
||||
|
||||
if statusCode >= 400 && statusCode <= 599 {
|
||||
errorResponse := ErrorResponse{}
|
||||
err = json.Unmarshal(body, &errorResponse)
|
||||
ecsError := &Error{
|
||||
ErrorResponse: errorResponse,
|
||||
StatusCode: statusCode,
|
||||
}
|
||||
return ecsError
|
||||
}
|
||||
|
||||
err = json.Unmarshal(body, response)
|
||||
//log.Printf("%++v", response)
|
||||
if err != nil {
|
||||
return GetClientError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Invoke sends the raw HTTP request for ECS services
|
||||
//改进了一下上面那个方法,可以使用各种Http方法
|
||||
//2017.1.30 增加了一个path参数,用来拓展访问的地址
|
||||
func (client *Client) InvokeByAnyMethod(method, action, path string, args interface{}, response interface{}) error {
|
||||
|
||||
request := Request{}
|
||||
request.init(client.version, action, client.AccessKeyId)
|
||||
|
||||
data := util.ConvertToQueryValues(request)
|
||||
util.SetQueryValues(args, &data)
|
||||
|
||||
// Sign request
|
||||
signature := util.CreateSignatureForRequest(method, &data, client.AccessKeySecret)
|
||||
|
||||
data.Add("Signature", signature)
|
||||
// Generate the request URL
|
||||
var (
|
||||
httpReq *http.Request
|
||||
err error
|
||||
)
|
||||
if method == http.MethodGet {
|
||||
requestURL := client.endpoint + path + "?" + data.Encode()
|
||||
//fmt.Println(requestURL)
|
||||
httpReq, err = http.NewRequest(method, requestURL, nil)
|
||||
} else {
|
||||
//fmt.Println(client.endpoint + path)
|
||||
httpReq, err = http.NewRequest(method, client.endpoint+path, strings.NewReader(data.Encode()))
|
||||
httpReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return GetClientError(err)
|
||||
}
|
||||
|
||||
// TODO move to util and add build val flag
|
||||
httpReq.Header.Set("X-SDK-Client", `AliyunGO/`+Version+client.businessInfo)
|
||||
|
||||
httpReq.Header.Set("User-Agent", httpReq.Header.Get("User-Agent")+ " " +client.userAgent)
|
||||
|
||||
t0 := time.Now()
|
||||
httpResp, err := client.httpClient.Do(httpReq)
|
||||
t1 := time.Now()
|
||||
if err != nil {
|
||||
return GetClientError(err)
|
||||
}
|
||||
statusCode := httpResp.StatusCode
|
||||
|
||||
if client.debug {
|
||||
log.Printf("Invoke %s %s %d (%v) %v", ECSRequestMethod, client.endpoint, statusCode, t1.Sub(t0), data.Encode())
|
||||
}
|
||||
|
||||
defer httpResp.Body.Close()
|
||||
body, err := ioutil.ReadAll(httpResp.Body)
|
||||
|
||||
if err != nil {
|
||||
return GetClientError(err)
|
||||
}
|
||||
|
||||
if client.debug {
|
||||
var prettyJSON bytes.Buffer
|
||||
err = json.Indent(&prettyJSON, body, "", " ")
|
||||
log.Println(string(prettyJSON.Bytes()))
|
||||
}
|
||||
|
||||
if statusCode >= 400 && statusCode <= 599 {
|
||||
errorResponse := ErrorResponse{}
|
||||
err = json.Unmarshal(body, &errorResponse)
|
||||
ecsError := &Error{
|
||||
ErrorResponse: errorResponse,
|
||||
StatusCode: statusCode,
|
||||
}
|
||||
return ecsError
|
||||
}
|
||||
|
||||
err = json.Unmarshal(body, response)
|
||||
//log.Printf("%++v", response)
|
||||
if err != nil {
|
||||
return GetClientError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GenerateClientToken generates the Client Token with random string
|
||||
func (client *Client) GenerateClientToken() string {
|
||||
return util.CreateRandomString()
|
||||
}
|
||||
|
||||
func GetClientErrorFromString(str string) error {
|
||||
return &Error{
|
||||
ErrorResponse: ErrorResponse{
|
||||
Code: "AliyunGoClientFailure",
|
||||
Message: str,
|
||||
},
|
||||
StatusCode: -1,
|
||||
}
|
||||
}
|
||||
|
||||
func GetClientError(err error) error {
|
||||
return GetClientErrorFromString(err.Error())
|
||||
}
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// LocationDefaultEndpoint is the default API endpoint of Location services
|
||||
locationDefaultEndpoint = "https://location.aliyuncs.com"
|
||||
locationAPIVersion = "2015-06-12"
|
||||
HTTP_PROTOCOL = "http"
|
||||
HTTPS_PROTOCOL = "https"
|
||||
)
|
||||
|
||||
var (
|
||||
endpoints = make(map[Region]map[string]string)
|
||||
)
|
||||
|
||||
//init endpoints from file
|
||||
func init() {
|
||||
|
||||
}
|
||||
|
||||
func NewLocationClient(accessKeyId, accessKeySecret string) *Client {
|
||||
endpoint := os.Getenv("LOCATION_ENDPOINT")
|
||||
if endpoint == "" {
|
||||
endpoint = locationDefaultEndpoint
|
||||
}
|
||||
|
||||
client := &Client{}
|
||||
client.Init(endpoint, locationAPIVersion, accessKeyId, accessKeySecret)
|
||||
return client
|
||||
}
|
||||
|
||||
func (client *Client) DescribeEndpoint(args *DescribeEndpointArgs) (*DescribeEndpointResponse, error) {
|
||||
response := &DescribeEndpointResponse{}
|
||||
err := client.Invoke("DescribeEndpoint", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
func getProductRegionEndpoint(region Region, serviceCode string) string {
|
||||
if sp, ok := endpoints[region]; ok {
|
||||
if endpoint, ok := sp[serviceCode]; ok {
|
||||
return endpoint
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func setProductRegionEndpoint(region Region, serviceCode string, endpoint string) {
|
||||
endpoints[region] = map[string]string{
|
||||
serviceCode: endpoint,
|
||||
}
|
||||
}
|
||||
|
||||
func (client *Client) DescribeOpenAPIEndpoint(region Region, serviceCode string) string {
|
||||
if endpoint := getProductRegionEndpoint(region, serviceCode); endpoint != "" {
|
||||
return endpoint
|
||||
}
|
||||
|
||||
defaultProtocols := HTTP_PROTOCOL
|
||||
|
||||
args := &DescribeEndpointArgs{
|
||||
Id: region,
|
||||
ServiceCode: serviceCode,
|
||||
Type: "openAPI",
|
||||
}
|
||||
|
||||
endpoint, err := client.DescribeEndpoint(args)
|
||||
if err != nil || endpoint.Endpoint == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
for _, protocol := range endpoint.Protocols.Protocols {
|
||||
if strings.ToLower(protocol) == HTTPS_PROTOCOL {
|
||||
defaultProtocols = HTTPS_PROTOCOL
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
ep := fmt.Sprintf("%s://%s", defaultProtocols, endpoint.Endpoint)
|
||||
|
||||
setProductRegionEndpoint(region, serviceCode, ep)
|
||||
return ep
|
||||
}
|
||||
|
||||
func loadEndpointFromFile(region Region, serviceCode string) string {
|
||||
data, err := ioutil.ReadFile("./endpoints.xml")
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
var endpoints Endpoints
|
||||
err = xml.Unmarshal(data, &endpoints)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
for _, endpoint := range endpoints.Endpoint {
|
||||
if endpoint.RegionIds.RegionId == string(region) {
|
||||
for _, product := range endpoint.Products.Product {
|
||||
if strings.ToLower(product.ProductName) == serviceCode {
|
||||
return fmt.Sprintf("%s://%s", HTTPS_PROTOCOL, product.DomainName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
+1349
File diff suppressed because it is too large
Load Diff
+34
@@ -0,0 +1,34 @@
|
||||
package common
|
||||
|
||||
// Region represents ECS region
|
||||
type Region string
|
||||
|
||||
// Constants of region definition
|
||||
const (
|
||||
Hangzhou = Region("cn-hangzhou")
|
||||
Qingdao = Region("cn-qingdao")
|
||||
Beijing = Region("cn-beijing")
|
||||
Hongkong = Region("cn-hongkong")
|
||||
Shenzhen = Region("cn-shenzhen")
|
||||
Shanghai = Region("cn-shanghai")
|
||||
Zhangjiakou = Region("cn-zhangjiakou")
|
||||
|
||||
APSouthEast1 = Region("ap-southeast-1")
|
||||
APNorthEast1 = Region("ap-northeast-1")
|
||||
APSouthEast2 = Region("ap-southeast-2")
|
||||
|
||||
USWest1 = Region("us-west-1")
|
||||
USEast1 = Region("us-east-1")
|
||||
|
||||
MEEast1 = Region("me-east-1")
|
||||
|
||||
EUCentral1 = Region("eu-central-1")
|
||||
)
|
||||
|
||||
var ValidRegions = []Region{
|
||||
Hangzhou, Qingdao, Beijing, Shenzhen, Hongkong, Shanghai, Zhangjiakou,
|
||||
USWest1, USEast1,
|
||||
APNorthEast1, APSouthEast1, APSouthEast2,
|
||||
MEEast1,
|
||||
EUCentral1,
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/denverdino/aliyungo/util"
|
||||
)
|
||||
|
||||
// Constants for Aliyun API requests
|
||||
const (
|
||||
SignatureVersion = "1.0"
|
||||
SignatureMethod = "HMAC-SHA1"
|
||||
JSONResponseFormat = "JSON"
|
||||
XMLResponseFormat = "XML"
|
||||
ECSRequestMethod = "GET"
|
||||
)
|
||||
|
||||
type Request struct {
|
||||
Format string
|
||||
Version string
|
||||
AccessKeyId string
|
||||
Signature string
|
||||
SignatureMethod string
|
||||
Timestamp util.ISO6801Time
|
||||
SignatureVersion string
|
||||
SignatureNonce string
|
||||
ResourceOwnerAccount string
|
||||
Action string
|
||||
}
|
||||
|
||||
func (request *Request) init(version string, action string, AccessKeyId string) {
|
||||
request.Format = JSONResponseFormat
|
||||
request.Timestamp = util.NewISO6801Time(time.Now().UTC())
|
||||
request.Version = version
|
||||
request.SignatureVersion = SignatureVersion
|
||||
request.SignatureMethod = SignatureMethod
|
||||
request.SignatureNonce = util.CreateRandomString()
|
||||
request.Action = action
|
||||
request.AccessKeyId = AccessKeyId
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
RequestId string
|
||||
}
|
||||
|
||||
type ErrorResponse struct {
|
||||
Response
|
||||
HostId string
|
||||
Code string
|
||||
Message string
|
||||
}
|
||||
|
||||
// An Error represents a custom error for Aliyun API failure response
|
||||
type Error struct {
|
||||
ErrorResponse
|
||||
StatusCode int //Status Code of HTTP Response
|
||||
}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
return fmt.Sprintf("Aliyun API Error: RequestId: %s Status Code: %d Code: %s Message: %s", e.RequestId, e.StatusCode, e.Code, e.Message)
|
||||
}
|
||||
|
||||
type Pagination struct {
|
||||
PageNumber int
|
||||
PageSize int
|
||||
}
|
||||
|
||||
func (p *Pagination) SetPageSize(size int) {
|
||||
p.PageSize = size
|
||||
}
|
||||
|
||||
func (p *Pagination) Validate() {
|
||||
if p.PageNumber < 0 {
|
||||
log.Printf("Invalid PageNumber: %d", p.PageNumber)
|
||||
p.PageNumber = 1
|
||||
}
|
||||
if p.PageSize < 0 {
|
||||
log.Printf("Invalid PageSize: %d", p.PageSize)
|
||||
p.PageSize = 10
|
||||
} else if p.PageSize > 50 {
|
||||
log.Printf("Invalid PageSize: %d", p.PageSize)
|
||||
p.PageSize = 50
|
||||
}
|
||||
}
|
||||
|
||||
// A PaginationResponse represents a response with pagination information
|
||||
type PaginationResult struct {
|
||||
TotalCount int
|
||||
PageNumber int
|
||||
PageSize int
|
||||
}
|
||||
|
||||
// NextPage gets the next page of the result set
|
||||
func (r *PaginationResult) NextPage() *Pagination {
|
||||
if r.PageNumber*r.PageSize >= r.TotalCount {
|
||||
return nil
|
||||
}
|
||||
return &Pagination{PageNumber: r.PageNumber + 1, PageSize: r.PageSize}
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
package common
|
||||
|
||||
type InternetChargeType string
|
||||
|
||||
const (
|
||||
PayByBandwidth = InternetChargeType("PayByBandwidth")
|
||||
PayByTraffic = InternetChargeType("PayByTraffic")
|
||||
)
|
||||
|
||||
type InstanceChargeType string
|
||||
|
||||
const (
|
||||
PrePaid = InstanceChargeType("PrePaid")
|
||||
PostPaid = InstanceChargeType("PostPaid")
|
||||
)
|
||||
|
||||
type DescribeEndpointArgs struct {
|
||||
Id Region
|
||||
ServiceCode string
|
||||
Type string
|
||||
}
|
||||
|
||||
type EndpointItem struct {
|
||||
Protocols struct {
|
||||
Protocols []string
|
||||
}
|
||||
Type string
|
||||
Namespace string
|
||||
Id Region
|
||||
SerivceCode string
|
||||
Endpoint string
|
||||
}
|
||||
|
||||
type DescribeEndpointResponse struct {
|
||||
Response
|
||||
EndpointItem
|
||||
}
|
||||
|
||||
type NetType string
|
||||
|
||||
const (
|
||||
Internet = NetType("Internet")
|
||||
Intranet = NetType("Intranet")
|
||||
)
|
||||
|
||||
type TimeType string
|
||||
|
||||
const (
|
||||
Hour = TimeType("Hour")
|
||||
Day = TimeType("Day")
|
||||
Month = TimeType("Month")
|
||||
Year = TimeType("Year")
|
||||
)
|
||||
|
||||
type NetworkType string
|
||||
|
||||
const (
|
||||
Classic = NetworkType("Classic")
|
||||
VPC = NetworkType("VPC")
|
||||
)
|
||||
|
||||
type BusinessInfo struct {
|
||||
Pack string `json:"pack,omitempty"`
|
||||
ActivityId string `json:"activityId,omitempty"`
|
||||
}
|
||||
|
||||
//xml
|
||||
type Endpoints struct {
|
||||
Endpoint []Endpoint `xml:"Endpoint"`
|
||||
}
|
||||
|
||||
type Endpoint struct {
|
||||
Name string `xml:"name,attr"`
|
||||
RegionIds RegionIds `xml:"RegionIds"`
|
||||
Products Products `xml:"Products"`
|
||||
}
|
||||
|
||||
type RegionIds struct {
|
||||
RegionId string `xml:"RegionId"`
|
||||
}
|
||||
|
||||
type Products struct {
|
||||
Product []Product `xml:"Product"`
|
||||
}
|
||||
|
||||
type Product struct {
|
||||
ProductName string `xml:"ProductName"`
|
||||
DomainName string `xml:"DomainName"`
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package common
|
||||
|
||||
const Version = "0.1"
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
)
|
||||
|
||||
type AddDomainArgs struct {
|
||||
DomainName string
|
||||
|
||||
//optional
|
||||
GroupId string
|
||||
}
|
||||
|
||||
type AddDomainResponse struct {
|
||||
common.Response
|
||||
DomainId string
|
||||
DomainName string
|
||||
GroupId string
|
||||
GroupName string
|
||||
PunyCode string
|
||||
DnsServers struct {
|
||||
DnsServer []string
|
||||
}
|
||||
}
|
||||
|
||||
// AddDomain
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/29749.html?spm=5176.doc29805.6.592.6LMqlG
|
||||
func (client *Client) AddDomain(args *AddDomainArgs) (response *AddDomainResponse, err error) {
|
||||
action := "AddDomain"
|
||||
response = &AddDomainResponse{}
|
||||
err = client.Invoke(action, args, response)
|
||||
if err == nil {
|
||||
return response, nil
|
||||
} else {
|
||||
log.Printf("%s error, %v", action, err)
|
||||
return response, err
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
)
|
||||
|
||||
type AddDomainGroupArgs struct {
|
||||
GroupName string
|
||||
}
|
||||
|
||||
type AddDomainGroupResponse struct {
|
||||
common.Response
|
||||
GroupId string
|
||||
GroupName string
|
||||
}
|
||||
|
||||
// AddDomainGroup
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/29762.html?spm=5176.doc29749.6.604.PJtwG1
|
||||
func (client *Client) AddDomainGroup(args *AddDomainGroupArgs) (response *AddDomainGroupResponse, err error) {
|
||||
action := "AddDomainGroup"
|
||||
response = &AddDomainGroupResponse{}
|
||||
err = client.Invoke(action, args, response)
|
||||
if err == nil {
|
||||
return response, nil
|
||||
} else {
|
||||
log.Printf("%s error, %v", action, err)
|
||||
return response, err
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
)
|
||||
|
||||
type AddDomainRecordArgs struct {
|
||||
DomainName string
|
||||
RR string
|
||||
Type string
|
||||
Value string
|
||||
|
||||
//optional
|
||||
TTL int32
|
||||
Priority int
|
||||
Line string
|
||||
}
|
||||
|
||||
type AddDomainRecordResponse struct {
|
||||
common.Response
|
||||
InstanceId string
|
||||
RecordId string
|
||||
}
|
||||
|
||||
// AddDomainRecord
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/dns/api-reference/record-related&AddDomainRecord
|
||||
func (client *Client) AddDomainRecord(args *AddDomainRecordArgs) (response *AddDomainRecordResponse, err error) {
|
||||
action := "AddDomainRecord"
|
||||
response = &AddDomainRecordResponse{}
|
||||
err = client.Invoke(action, args, response)
|
||||
if err == nil {
|
||||
return response, nil
|
||||
} else {
|
||||
log.Printf("%s error, %v", action, err)
|
||||
return response, err
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
)
|
||||
|
||||
type ChangeDomainGroupArgs struct {
|
||||
DomainName string
|
||||
GroupId string
|
||||
}
|
||||
|
||||
type ChangeDomainGroupResponse struct {
|
||||
common.Response
|
||||
GroupId string
|
||||
GroupName string
|
||||
}
|
||||
|
||||
// ChangeDomainGroup
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/29765.html?spm=5176.doc29764.6.607.WUJQgE
|
||||
func (client *Client) ChangeDomainGroup(args *ChangeDomainGroupArgs) (response *ChangeDomainGroupResponse, err error) {
|
||||
action := "ChangeDomainGroup"
|
||||
response = &ChangeDomainGroupResponse{}
|
||||
err = client.Invoke(action, args, response)
|
||||
if err == nil {
|
||||
return response, nil
|
||||
} else {
|
||||
log.Printf("%s error, %v", action, err)
|
||||
return response, err
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
)
|
||||
|
||||
type DeleteDomainArgs struct {
|
||||
DomainName string
|
||||
}
|
||||
|
||||
type DeleteDomainResponse struct {
|
||||
common.Response
|
||||
DomainName string
|
||||
}
|
||||
|
||||
// DeleteDomain
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/29750.html?spm=5176.doc29766.6.593.eELaZ7
|
||||
func (client *Client) DeleteDomain(args *DeleteDomainArgs) (response *DeleteDomainResponse, err error) {
|
||||
action := "DeleteDomain"
|
||||
response = &DeleteDomainResponse{}
|
||||
err = client.Invoke(action, args, response)
|
||||
if err == nil {
|
||||
return response, nil
|
||||
} else {
|
||||
log.Printf("%s error, %v", action, err)
|
||||
return response, err
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
)
|
||||
|
||||
type DeleteDomainGroupArgs struct {
|
||||
GroupId string
|
||||
}
|
||||
|
||||
type DeleteDomainGroupResponse struct {
|
||||
common.Response
|
||||
GroupName string
|
||||
}
|
||||
|
||||
// DeleteDomainGroup
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/29764.html?spm=5176.doc29763.6.606.Vm3FyC
|
||||
func (client *Client) DeleteDomainGroup(args *DeleteDomainGroupArgs) (response *DeleteDomainGroupResponse, err error) {
|
||||
action := "DeleteDomainGroup"
|
||||
response = &DeleteDomainGroupResponse{}
|
||||
err = client.Invoke(action, args, response)
|
||||
if err == nil {
|
||||
return response, nil
|
||||
} else {
|
||||
log.Printf("%s error, %v", action, err)
|
||||
return response, err
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package dns
|
||||
|
||||
import "github.com/denverdino/aliyungo/common"
|
||||
|
||||
type DeleteDomainRecordArgs struct {
|
||||
RecordId string
|
||||
}
|
||||
|
||||
type DeleteDomainRecordResponse struct {
|
||||
common.Response
|
||||
InstanceId string
|
||||
RecordId string
|
||||
}
|
||||
|
||||
// DeleteDomainRecord
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/dns/api-reference/record-related&DeleteDomainRecord
|
||||
func (client *Client) DeleteDomainRecord(args *DeleteDomainRecordArgs) (response *DeleteDomainRecordResponse, err error) {
|
||||
action := "DeleteDomainRecord"
|
||||
response = &DeleteDomainRecordResponse{}
|
||||
err = client.Invoke(action, args, response)
|
||||
if err == nil {
|
||||
return response, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package dns
|
||||
|
||||
import "github.com/denverdino/aliyungo/common"
|
||||
|
||||
type DeleteSubDomainRecordsArgs struct {
|
||||
DomainName string
|
||||
RR string
|
||||
|
||||
//optional
|
||||
Type string
|
||||
}
|
||||
|
||||
type DeleteSubDomainRecordsResponse struct {
|
||||
common.Response
|
||||
InstanceId string
|
||||
RR string
|
||||
// TotalCount int32
|
||||
}
|
||||
|
||||
// DeleteSubDomainRecords
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/dns/api-reference/record-related&DeleteSubDomainRecords
|
||||
func (client *Client) DeleteSubDomainRecords(args *DeleteSubDomainRecordsArgs) (response *DeleteSubDomainRecordsResponse, err error) {
|
||||
action := "DeleteSubDomainRecords"
|
||||
response = &DeleteSubDomainRecordsResponse{}
|
||||
err = client.Invoke(action, args, response)
|
||||
if err == nil {
|
||||
return response, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
)
|
||||
|
||||
type DomainGroupType struct {
|
||||
GroupId string
|
||||
GroupName string
|
||||
}
|
||||
|
||||
type DescribeDomainGroupsArgs struct {
|
||||
//optional
|
||||
PageNumber int32
|
||||
PageSize int32
|
||||
KeyWord string
|
||||
}
|
||||
|
||||
type DescribeDomainGroupsResponse struct {
|
||||
response common.Response
|
||||
TotalCount int32
|
||||
PageNumber int32
|
||||
PageSize int32
|
||||
DomainGroups struct {
|
||||
DomainGroup []DomainGroupType
|
||||
}
|
||||
}
|
||||
|
||||
// DescribeDomainGroups
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/29766.html?spm=5176.doc29765.6.608.qcQr2R
|
||||
func (client *Client) DescribeDomainGroups(args *DescribeDomainGroupsArgs) (groups []DomainGroupType, err error) {
|
||||
action := "DescribeDomainGroups"
|
||||
response := &DescribeDomainGroupsResponse{}
|
||||
err = client.Invoke(action, args, response)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("%s error, %v", action, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return response.DomainGroups.DomainGroup, nil
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
)
|
||||
|
||||
type DomainType struct {
|
||||
DomainId string
|
||||
DomainName string
|
||||
AliDomain bool
|
||||
GroupId string
|
||||
GroupName string
|
||||
InstanceId string
|
||||
VersionCode string
|
||||
PunyCode string
|
||||
DnsServers struct {
|
||||
DnsServer []string
|
||||
}
|
||||
}
|
||||
|
||||
type DescribeDomainInfoArgs struct {
|
||||
DomainName string
|
||||
}
|
||||
|
||||
type DescribeDomainInfoResponse struct {
|
||||
response common.Response
|
||||
DomainType
|
||||
}
|
||||
|
||||
// DescribeDomainInfo
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/29752.html?spm=5176.doc29751.6.595.VJM3Gy
|
||||
func (client *Client) DescribeDomainInfo(args *DescribeDomainInfoArgs) (domain DomainType, err error) {
|
||||
action := "DescribeDomainInfo"
|
||||
response := &DescribeDomainInfoResponse{}
|
||||
err = client.Invoke(action, args, response)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("%s error, %v", action, err)
|
||||
return DomainType{}, err
|
||||
}
|
||||
|
||||
return response.DomainType, nil
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package dns
|
||||
|
||||
import "github.com/denverdino/aliyungo/common"
|
||||
|
||||
type DescribeDomainRecordInfoArgs struct {
|
||||
RecordId string
|
||||
}
|
||||
|
||||
type DescribeDomainRecordInfoResponse struct {
|
||||
common.Response
|
||||
RecordType
|
||||
}
|
||||
|
||||
// DescribeDomainRecordInfo
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/dns/api-reference/record-related&DescribeDomainRecordInfo
|
||||
func (client *Client) DescribeDomainRecordInfo(args *DescribeDomainRecordInfoArgs) (response *DescribeDomainRecordInfoResponse, err error) {
|
||||
action := "DescribeDomainRecordInfo"
|
||||
response = &DescribeDomainRecordInfoResponse{}
|
||||
err = client.Invoke(action, args, response)
|
||||
if err == nil {
|
||||
return response, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package dns
|
||||
|
||||
import "github.com/denverdino/aliyungo/common"
|
||||
|
||||
// endpoint change to 'http://alidns.aliyuncs.com' then record ttl and priority change to string
|
||||
type RecordTypeNew struct {
|
||||
DomainName string
|
||||
RecordId string
|
||||
RR string
|
||||
Type string
|
||||
Value string
|
||||
TTL string
|
||||
Priority string
|
||||
Line string
|
||||
Status string
|
||||
Locked bool
|
||||
}
|
||||
|
||||
type DescribeDomainRecordInfoNewArgs struct {
|
||||
RecordId string
|
||||
}
|
||||
|
||||
type DescribeDomainRecordInfoNewResponse struct {
|
||||
common.Response
|
||||
RecordTypeNew
|
||||
}
|
||||
|
||||
// DescribeDomainRecordInformation
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/dns/api-reference/record-related&DescribeDomainRecordInfo
|
||||
func (client *Client) DescribeDomainRecordInfoNew(args *DescribeDomainRecordInfoNewArgs) (response *DescribeDomainRecordInfoNewResponse, err error) {
|
||||
action := "DescribeDomainRecordInfo"
|
||||
response = &DescribeDomainRecordInfoNewResponse{}
|
||||
err = client.Invoke(action, args, response)
|
||||
if err == nil {
|
||||
return response, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package dns
|
||||
|
||||
import "github.com/denverdino/aliyungo/common"
|
||||
|
||||
type DescribeDomainRecordsArgs struct {
|
||||
DomainName string
|
||||
|
||||
//optional
|
||||
common.Pagination
|
||||
RRKeyWord string
|
||||
TypeKeyWord string
|
||||
ValueKeyWord string
|
||||
}
|
||||
|
||||
type DescribeDomainRecordsResponse struct {
|
||||
common.Response
|
||||
common.PaginationResult
|
||||
InstanceId string
|
||||
DomainRecords struct {
|
||||
Record []RecordType
|
||||
}
|
||||
}
|
||||
|
||||
// DescribeDomainRecords
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/dns/api-reference/record-related&DescribeDomainRecords
|
||||
func (client *Client) DescribeDomainRecords(args *DescribeDomainRecordsArgs) (response *DescribeDomainRecordsResponse, err error) {
|
||||
action := "DescribeDomainRecords"
|
||||
response = &DescribeDomainRecordsResponse{}
|
||||
err = client.Invoke(action, args, response)
|
||||
if err == nil {
|
||||
return response, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package dns
|
||||
|
||||
import "github.com/denverdino/aliyungo/common"
|
||||
|
||||
type DescribeDomainRecordsNewArgs struct {
|
||||
DomainName string
|
||||
|
||||
//optional
|
||||
common.Pagination
|
||||
RRKeyWord string
|
||||
TypeKeyWord string
|
||||
ValueKeyWord string
|
||||
}
|
||||
|
||||
type DescribeDomainRecordsNewResponse struct {
|
||||
common.Response
|
||||
common.PaginationResult
|
||||
InstanceId string
|
||||
DomainRecords struct {
|
||||
Record []RecordTypeNew
|
||||
}
|
||||
}
|
||||
|
||||
// DescribeDomainRecordsNew
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/dns/api-reference/record-related&DescribeDomainRecords
|
||||
func (client *Client) DescribeDomainRecordsNew(args *DescribeDomainRecordsNewArgs) (response *DescribeDomainRecordsNewResponse, err error) {
|
||||
action := "DescribeDomainRecords"
|
||||
response = &DescribeDomainRecordsNewResponse{}
|
||||
err = client.Invoke(action, args, response)
|
||||
if err == nil {
|
||||
return response, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
)
|
||||
|
||||
type DescribeDomainsArgs struct {
|
||||
// optional
|
||||
PageNumber int32
|
||||
PageSize int32
|
||||
KeyWord string
|
||||
GroupId string
|
||||
}
|
||||
|
||||
type DescribeDomainsResponse struct {
|
||||
response common.Response
|
||||
TotalCount int32
|
||||
PageNumber int32
|
||||
PageSize int32
|
||||
Domains struct {
|
||||
Domain []DomainType
|
||||
}
|
||||
}
|
||||
|
||||
// DescribeDomains
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/29751.html?spm=5176.doc29750.6.594.dvyRJV
|
||||
func (client *Client) DescribeDomains(args *DescribeDomainsArgs) (domains []DomainType, err error) {
|
||||
action := "DescribeDomains"
|
||||
response := &DescribeDomainsResponse{}
|
||||
err = client.Invoke(action, args, response)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("%s error, %v", action, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return response.Domains.Domain, err
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package dns
|
||||
|
||||
import "github.com/denverdino/aliyungo/common"
|
||||
|
||||
type DescribeSubDomainRecordsArgs struct {
|
||||
SubDomain string
|
||||
|
||||
//optional
|
||||
PageNumber int32
|
||||
PageSize int32
|
||||
Type string
|
||||
}
|
||||
|
||||
type DescribeSubDomainRecordsResponse struct {
|
||||
common.Response
|
||||
InstanceId string
|
||||
TotalCount int32
|
||||
PageNumber int32
|
||||
PageSize int32
|
||||
DomainRecords struct {
|
||||
Record []RecordType
|
||||
}
|
||||
}
|
||||
|
||||
// DescribeSubDomainRecords
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/dns/api-reference/record-related&DescribeSubDomainRecords
|
||||
func (client *Client) DescribeSubDomainRecords(args *DescribeSubDomainRecordsArgs) (response *DescribeSubDomainRecordsResponse, err error) {
|
||||
action := "DescribeSubDomainRecords"
|
||||
response = &DescribeSubDomainRecordsResponse{}
|
||||
err = client.Invoke(action, args, response)
|
||||
if err == nil {
|
||||
return response, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package dns
|
||||
|
||||
import "github.com/denverdino/aliyungo/common"
|
||||
|
||||
type GetMainDomainNameArgs struct {
|
||||
InputString string
|
||||
}
|
||||
|
||||
type GetMainDomainNameResponse struct {
|
||||
common.Response
|
||||
InstanceId string
|
||||
DomainName string
|
||||
RR string
|
||||
DomainLevel int32
|
||||
}
|
||||
|
||||
// GetMainDomainName
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/dns/api-reference/domain-related&GetMainDomainName
|
||||
func (client *Client) GetMainDomainName(args *GetMainDomainNameArgs) (response *GetMainDomainNameResponse, err error) {
|
||||
action := "GetMainDomainName"
|
||||
response = &GetMainDomainNameResponse{}
|
||||
err = client.Invoke(action, args, response)
|
||||
if err == nil {
|
||||
return response, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
)
|
||||
|
||||
type UpdateDomainGroupArgs struct {
|
||||
GroupId string
|
||||
GroupName string
|
||||
}
|
||||
|
||||
type UpdateDomainGroupResponse struct {
|
||||
common.Response
|
||||
GroupId string
|
||||
GroupName string
|
||||
}
|
||||
|
||||
// UpdateDomainGroup
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/29763.html?spm=5176.doc29762.6.605.iFRKjn
|
||||
func (client *Client) UpdateDomainGroup(args *UpdateDomainGroupArgs) (response *UpdateDomainGroupResponse, err error) {
|
||||
action := "UpdateDomainGroup"
|
||||
response = &UpdateDomainGroupResponse{}
|
||||
err = client.Invoke(action, args, response)
|
||||
if err == nil {
|
||||
return response, nil
|
||||
} else {
|
||||
log.Printf("%s error, %v", action, err)
|
||||
return response, err
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package dns
|
||||
|
||||
import "github.com/denverdino/aliyungo/common"
|
||||
|
||||
type UpdateDomainRecordArgs struct {
|
||||
RecordId string
|
||||
RR string
|
||||
Type string
|
||||
Value string
|
||||
|
||||
//optional
|
||||
TTL int32
|
||||
Priority int32
|
||||
Line string
|
||||
}
|
||||
|
||||
type UpdateDomainRecordResponse struct {
|
||||
common.Response
|
||||
InstanceId string
|
||||
RecordId string
|
||||
}
|
||||
|
||||
// UpdateDomainRecord
|
||||
//
|
||||
// You can read doc at https://docs.aliyun.com/#/pub/dns/api-reference/record-related&UpdateDomainRecord
|
||||
func (client *Client) UpdateDomainRecord(args *UpdateDomainRecordArgs) (response *UpdateDomainRecordResponse, err error) {
|
||||
action := "UpdateDomainRecord"
|
||||
response = &UpdateDomainRecordResponse{}
|
||||
err = client.Invoke(action, args, response)
|
||||
if err == nil {
|
||||
return response, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
common.Client
|
||||
}
|
||||
|
||||
const (
|
||||
// DNSDefaultEndpoint is the default API endpoint of DNS services
|
||||
DNSDefaultEndpoint = "http://dns.aliyuncs.com"
|
||||
DNSAPIVersion = "2015-01-09"
|
||||
|
||||
DNSDefaultEndpointNew = "http://alidns.aliyuncs.com"
|
||||
)
|
||||
|
||||
// NewClient creates a new instance of DNS client
|
||||
func NewClient(accessKeyId, accessKeySecret string) *Client {
|
||||
endpoint := os.Getenv("DNS_ENDPOINT")
|
||||
if endpoint == "" {
|
||||
endpoint = DNSDefaultEndpoint
|
||||
}
|
||||
return NewClientWithEndpoint(endpoint, accessKeyId, accessKeySecret)
|
||||
}
|
||||
|
||||
// NewClientNew creates a new instance of DNS client, with http://alidns.aliyuncs.com as default endpoint
|
||||
func NewClientNew(accessKeyId, accessKeySecret string) *Client {
|
||||
endpoint := os.Getenv("DNS_ENDPOINT")
|
||||
if endpoint == "" {
|
||||
endpoint = DNSDefaultEndpointNew
|
||||
}
|
||||
return NewClientWithEndpoint(endpoint, accessKeyId, accessKeySecret)
|
||||
}
|
||||
|
||||
// NewCustomClient creates a new instance of ECS client with customized API endpoint
|
||||
func NewCustomClient(accessKeyId, accessKeySecret string, endpoint string) *Client {
|
||||
client := &Client{}
|
||||
client.Init(endpoint, DNSAPIVersion, accessKeyId, accessKeySecret)
|
||||
return client
|
||||
}
|
||||
|
||||
func NewClientWithEndpoint(endpoint string, accessKeyId, accessKeySecret string) *Client {
|
||||
client := &Client{}
|
||||
client.Init(endpoint, DNSAPIVersion, accessKeyId, accessKeySecret)
|
||||
return client
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package dns
|
||||
|
||||
//
|
||||
//you can read doc at https://docs.aliyun.com/#/pub/dns/api-reference/enum-type&record-format
|
||||
const (
|
||||
ARecord = "A"
|
||||
NSRecord = "NS"
|
||||
MXRecord = "MX"
|
||||
TXTRecord = "TXT"
|
||||
CNAMERecord = "CNAME"
|
||||
SRVRecord = "SRV"
|
||||
AAAARecord = "AAAA"
|
||||
RedirectURLRecord = "REDIRECT_URL"
|
||||
ForwordURLRecord = "FORWORD_URL"
|
||||
)
|
||||
|
||||
type RecordType struct {
|
||||
DomainName string
|
||||
RecordId string
|
||||
RR string
|
||||
Type string
|
||||
Value string
|
||||
TTL int32
|
||||
Priority int32
|
||||
Line string
|
||||
Status string
|
||||
Locked bool
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// AttemptStrategy is reused from the goamz package
|
||||
|
||||
// AttemptStrategy represents a strategy for waiting for an action
|
||||
// to complete successfully. This is an internal type used by the
|
||||
// implementation of other packages.
|
||||
type AttemptStrategy struct {
|
||||
Total time.Duration // total duration of attempt.
|
||||
Delay time.Duration // interval between each try in the burst.
|
||||
Min int // minimum number of retries; overrides Total
|
||||
}
|
||||
|
||||
type Attempt struct {
|
||||
strategy AttemptStrategy
|
||||
last time.Time
|
||||
end time.Time
|
||||
force bool
|
||||
count int
|
||||
}
|
||||
|
||||
// Start begins a new sequence of attempts for the given strategy.
|
||||
func (s AttemptStrategy) Start() *Attempt {
|
||||
now := time.Now()
|
||||
return &Attempt{
|
||||
strategy: s,
|
||||
last: now,
|
||||
end: now.Add(s.Total),
|
||||
force: true,
|
||||
}
|
||||
}
|
||||
|
||||
// Next waits until it is time to perform the next attempt or returns
|
||||
// false if it is time to stop trying.
|
||||
func (a *Attempt) Next() bool {
|
||||
now := time.Now()
|
||||
sleep := a.nextSleep(now)
|
||||
if !a.force && !now.Add(sleep).Before(a.end) && a.strategy.Min <= a.count {
|
||||
return false
|
||||
}
|
||||
a.force = false
|
||||
if sleep > 0 && a.count > 0 {
|
||||
time.Sleep(sleep)
|
||||
now = time.Now()
|
||||
}
|
||||
a.count++
|
||||
a.last = now
|
||||
return true
|
||||
}
|
||||
|
||||
func (a *Attempt) nextSleep(now time.Time) time.Duration {
|
||||
sleep := a.strategy.Delay - now.Sub(a.last)
|
||||
if sleep < 0 {
|
||||
return 0
|
||||
}
|
||||
return sleep
|
||||
}
|
||||
|
||||
// HasNext returns whether another attempt will be made if the current
|
||||
// one fails. If it returns true, the following call to Next is
|
||||
// guaranteed to return true.
|
||||
func (a *Attempt) HasNext() bool {
|
||||
if a.force || a.strategy.Min > a.count {
|
||||
return true
|
||||
}
|
||||
now := time.Now()
|
||||
if now.Add(a.nextSleep(now)).Before(a.end) {
|
||||
a.force = true
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
+314
@@ -0,0 +1,314 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// change instance=["a", "b"]
|
||||
// to instance.1="a" instance.2="b"
|
||||
func FlattenFn(fieldName string, field reflect.Value, values *url.Values) {
|
||||
l := field.Len()
|
||||
if l > 0 {
|
||||
for i := 0; i < l; i++ {
|
||||
str := field.Index(i).String()
|
||||
values.Set(fieldName+"."+strconv.Itoa(i+1), str)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Underline2Dot(name string) string {
|
||||
return strings.Replace(name, "_", ".", -1)
|
||||
}
|
||||
|
||||
//ConvertToQueryValues converts the struct to url.Values
|
||||
func ConvertToQueryValues(ifc interface{}) url.Values {
|
||||
values := url.Values{}
|
||||
SetQueryValues(ifc, &values)
|
||||
return values
|
||||
}
|
||||
|
||||
//SetQueryValues sets the struct to existing url.Values following ECS encoding rules
|
||||
func SetQueryValues(ifc interface{}, values *url.Values) {
|
||||
setQueryValues(ifc, values, "")
|
||||
}
|
||||
|
||||
func SetQueryValueByFlattenMethod(ifc interface{}, values *url.Values) {
|
||||
setQueryValuesByFlattenMethod(ifc, values, "")
|
||||
}
|
||||
|
||||
func setQueryValues(i interface{}, values *url.Values, prefix string) {
|
||||
// add to support url.Values
|
||||
mapValues, ok := i.(url.Values)
|
||||
if ok {
|
||||
for k, _ := range mapValues {
|
||||
values.Set(k, mapValues.Get(k))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
elem := reflect.ValueOf(i)
|
||||
if elem.Kind() == reflect.Ptr {
|
||||
elem = elem.Elem()
|
||||
}
|
||||
elemType := elem.Type()
|
||||
for i := 0; i < elem.NumField(); i++ {
|
||||
|
||||
fieldName := elemType.Field(i).Name
|
||||
anonymous := elemType.Field(i).Anonymous
|
||||
field := elem.Field(i)
|
||||
// TODO Use Tag for validation
|
||||
// tag := typ.Field(i).Tag.Get("tagname")
|
||||
kind := field.Kind()
|
||||
if (kind == reflect.Ptr || kind == reflect.Array || kind == reflect.Slice || kind == reflect.Map || kind == reflect.Chan) && field.IsNil() {
|
||||
continue
|
||||
}
|
||||
if kind == reflect.Ptr {
|
||||
field = field.Elem()
|
||||
kind = field.Kind()
|
||||
}
|
||||
var value string
|
||||
//switch field.Interface().(type) {
|
||||
switch kind {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
i := field.Int()
|
||||
if i != 0 {
|
||||
value = strconv.FormatInt(i, 10)
|
||||
}
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
i := field.Uint()
|
||||
if i != 0 {
|
||||
value = strconv.FormatUint(i, 10)
|
||||
}
|
||||
case reflect.Float32:
|
||||
value = strconv.FormatFloat(field.Float(), 'f', 4, 32)
|
||||
case reflect.Float64:
|
||||
value = strconv.FormatFloat(field.Float(), 'f', 4, 64)
|
||||
case reflect.Bool:
|
||||
value = strconv.FormatBool(field.Bool())
|
||||
case reflect.String:
|
||||
value = field.String()
|
||||
case reflect.Map:
|
||||
ifc := field.Interface()
|
||||
m := ifc.(map[string]string)
|
||||
if m != nil {
|
||||
j := 0
|
||||
for k, v := range m {
|
||||
j++
|
||||
keyName := fmt.Sprintf("%s.%d.Key", fieldName, j)
|
||||
values.Set(keyName, k)
|
||||
valueName := fmt.Sprintf("%s.%d.Value", fieldName, j)
|
||||
values.Set(valueName, v)
|
||||
}
|
||||
}
|
||||
case reflect.Slice:
|
||||
switch field.Type().Elem().Kind() {
|
||||
case reflect.Uint8:
|
||||
value = string(field.Bytes())
|
||||
case reflect.String:
|
||||
l := field.Len()
|
||||
if l > 0 {
|
||||
strArray := make([]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
strArray[i] = field.Index(i).String()
|
||||
}
|
||||
bytes, err := json.Marshal(strArray)
|
||||
if err == nil {
|
||||
value = string(bytes)
|
||||
} else {
|
||||
log.Printf("Failed to convert JSON: %v", err)
|
||||
}
|
||||
}
|
||||
default:
|
||||
l := field.Len()
|
||||
for j := 0; j < l; j++ {
|
||||
prefixName := fmt.Sprintf("%s.%d.", fieldName, (j + 1))
|
||||
ifc := field.Index(j).Interface()
|
||||
//log.Printf("%s : %v", prefixName, ifc)
|
||||
if ifc != nil {
|
||||
setQueryValues(ifc, values, prefixName)
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
default:
|
||||
switch field.Interface().(type) {
|
||||
case ISO6801Time:
|
||||
t := field.Interface().(ISO6801Time)
|
||||
value = t.String()
|
||||
case time.Time:
|
||||
t := field.Interface().(time.Time)
|
||||
value = GetISO8601TimeStamp(t)
|
||||
default:
|
||||
ifc := field.Interface()
|
||||
if ifc != nil {
|
||||
if anonymous {
|
||||
SetQueryValues(ifc, values)
|
||||
} else {
|
||||
prefixName := fieldName + "."
|
||||
setQueryValues(ifc, values, prefixName)
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
if value != "" {
|
||||
name := elemType.Field(i).Tag.Get("ArgName")
|
||||
if name == "" {
|
||||
name = fieldName
|
||||
}
|
||||
if prefix != "" {
|
||||
name = prefix + name
|
||||
}
|
||||
values.Set(name, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setQueryValuesByFlattenMethod(i interface{}, values *url.Values, prefix string) {
|
||||
// add to support url.Values
|
||||
mapValues, ok := i.(url.Values)
|
||||
if ok {
|
||||
for k, _ := range mapValues {
|
||||
values.Set(k, mapValues.Get(k))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
elem := reflect.ValueOf(i)
|
||||
if elem.Kind() == reflect.Ptr {
|
||||
elem = elem.Elem()
|
||||
}
|
||||
elemType := elem.Type()
|
||||
for i := 0; i < elem.NumField(); i++ {
|
||||
|
||||
fieldName := elemType.Field(i).Name
|
||||
anonymous := elemType.Field(i).Anonymous
|
||||
field := elem.Field(i)
|
||||
|
||||
// TODO Use Tag for validation
|
||||
// tag := typ.Field(i).Tag.Get("tagname")
|
||||
kind := field.Kind()
|
||||
|
||||
if (kind == reflect.Ptr || kind == reflect.Array || kind == reflect.Slice || kind == reflect.Map || kind == reflect.Chan) && field.IsNil() {
|
||||
continue
|
||||
}
|
||||
if kind == reflect.Ptr {
|
||||
field = field.Elem()
|
||||
kind = field.Kind()
|
||||
}
|
||||
|
||||
var value string
|
||||
//switch field.Interface().(type) {
|
||||
switch kind {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
i := field.Int()
|
||||
if i != 0 {
|
||||
value = strconv.FormatInt(i, 10)
|
||||
}
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
i := field.Uint()
|
||||
if i != 0 {
|
||||
value = strconv.FormatUint(i, 10)
|
||||
}
|
||||
case reflect.Float32:
|
||||
value = strconv.FormatFloat(field.Float(), 'f', 4, 32)
|
||||
case reflect.Float64:
|
||||
value = strconv.FormatFloat(field.Float(), 'f', 4, 64)
|
||||
case reflect.Bool:
|
||||
value = strconv.FormatBool(field.Bool())
|
||||
case reflect.String:
|
||||
value = field.String()
|
||||
case reflect.Map:
|
||||
ifc := field.Interface()
|
||||
m := ifc.(map[string]string)
|
||||
if m != nil {
|
||||
j := 0
|
||||
for k, v := range m {
|
||||
j++
|
||||
keyName := fmt.Sprintf("%s.%d.Key", fieldName, j)
|
||||
values.Set(keyName, k)
|
||||
valueName := fmt.Sprintf("%s.%d.Value", fieldName, j)
|
||||
values.Set(valueName, v)
|
||||
}
|
||||
}
|
||||
case reflect.Slice:
|
||||
if field.Type().Name() == "FlattenArray" {
|
||||
FlattenFn(fieldName, field, values)
|
||||
} else {
|
||||
switch field.Type().Elem().Kind() {
|
||||
case reflect.Uint8:
|
||||
value = string(field.Bytes())
|
||||
case reflect.String:
|
||||
l := field.Len()
|
||||
if l > 0 {
|
||||
strArray := make([]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
strArray[i] = field.Index(i).String()
|
||||
}
|
||||
bytes, err := json.Marshal(strArray)
|
||||
if err == nil {
|
||||
value = string(bytes)
|
||||
} else {
|
||||
log.Printf("Failed to convert JSON: %v", err)
|
||||
}
|
||||
}
|
||||
default:
|
||||
l := field.Len()
|
||||
for j := 0; j < l; j++ {
|
||||
prefixName := fmt.Sprintf("%s.%d.", fieldName, (j + 1))
|
||||
ifc := field.Index(j).Interface()
|
||||
//log.Printf("%s : %v", prefixName, ifc)
|
||||
if ifc != nil {
|
||||
setQueryValuesByFlattenMethod(ifc, values, prefixName)
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
switch field.Interface().(type) {
|
||||
case ISO6801Time:
|
||||
t := field.Interface().(ISO6801Time)
|
||||
value = t.String()
|
||||
case time.Time:
|
||||
t := field.Interface().(time.Time)
|
||||
value = GetISO8601TimeStamp(t)
|
||||
default:
|
||||
|
||||
ifc := field.Interface()
|
||||
if ifc != nil {
|
||||
if anonymous {
|
||||
SetQueryValues(ifc, values)
|
||||
} else {
|
||||
prefixName := fieldName + "."
|
||||
setQueryValuesByFlattenMethod(ifc, values, prefixName)
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
if value != "" {
|
||||
name := elemType.Field(i).Tag.Get("ArgName")
|
||||
if name == "" {
|
||||
name = fieldName
|
||||
}
|
||||
if prefix != "" {
|
||||
name = prefix + name
|
||||
}
|
||||
// NOTE: here we will change name to underline style when the type is UnderlineString
|
||||
if field.Type().Name() == "UnderlineString" {
|
||||
name = Underline2Dot(name)
|
||||
}
|
||||
values.Set(name, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// GetISO8601TimeStamp gets timestamp string in ISO8601 format
|
||||
func GetISO8601TimeStamp(ts time.Time) string {
|
||||
t := ts.UTC()
|
||||
return fmt.Sprintf("%04d-%02d-%02dT%02d:%02d:%02dZ", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second())
|
||||
}
|
||||
|
||||
const formatISO8601 = "2006-01-02T15:04:05Z"
|
||||
const jsonFormatISO8601 = `"` + formatISO8601 + `"`
|
||||
const formatISO8601withoutSeconds = "2006-01-02T15:04Z"
|
||||
const jsonFormatISO8601withoutSeconds = `"` + formatISO8601withoutSeconds + `"`
|
||||
|
||||
// A ISO6801Time represents a time in ISO8601 format
|
||||
type ISO6801Time time.Time
|
||||
|
||||
// New constructs a new iso8601.Time instance from an existing
|
||||
// time.Time instance. This causes the nanosecond field to be set to
|
||||
// 0, and its time zone set to a fixed zone with no offset from UTC
|
||||
// (but it is *not* UTC itself).
|
||||
func NewISO6801Time(t time.Time) ISO6801Time {
|
||||
return ISO6801Time(time.Date(
|
||||
t.Year(),
|
||||
t.Month(),
|
||||
t.Day(),
|
||||
t.Hour(),
|
||||
t.Minute(),
|
||||
t.Second(),
|
||||
0,
|
||||
time.UTC,
|
||||
))
|
||||
}
|
||||
|
||||
// IsDefault checks if the time is default
|
||||
func (it *ISO6801Time) IsDefault() bool {
|
||||
return *it == ISO6801Time{}
|
||||
}
|
||||
|
||||
// MarshalJSON serializes the ISO6801Time into JSON string
|
||||
func (it ISO6801Time) MarshalJSON() ([]byte, error) {
|
||||
return []byte(time.Time(it).Format(jsonFormatISO8601)), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON deserializes the ISO6801Time from JSON string
|
||||
func (it *ISO6801Time) UnmarshalJSON(data []byte) error {
|
||||
str := string(data)
|
||||
|
||||
if str == "\"\"" || len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
var t time.Time
|
||||
var err error
|
||||
if str[0] == '"' {
|
||||
t, err = time.ParseInLocation(jsonFormatISO8601, str, time.UTC)
|
||||
if err != nil {
|
||||
t, err = time.ParseInLocation(jsonFormatISO8601withoutSeconds, str, time.UTC)
|
||||
}
|
||||
} else {
|
||||
var i int64
|
||||
i, err = strconv.ParseInt(str, 10, 64)
|
||||
if err == nil {
|
||||
t = time.Unix(i/1000, i%1000)
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
*it = ISO6801Time(t)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// String returns the time in ISO6801Time format
|
||||
func (it ISO6801Time) String() string {
|
||||
return time.Time(it).Format(formatISO8601)
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"encoding/base64"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
//CreateSignature creates signature for string following Aliyun rules
|
||||
func CreateSignature(stringToSignature, accessKeySecret string) string {
|
||||
// Crypto by HMAC-SHA1
|
||||
hmacSha1 := hmac.New(sha1.New, []byte(accessKeySecret))
|
||||
hmacSha1.Write([]byte(stringToSignature))
|
||||
sign := hmacSha1.Sum(nil)
|
||||
|
||||
// Encode to Base64
|
||||
base64Sign := base64.StdEncoding.EncodeToString(sign)
|
||||
|
||||
return base64Sign
|
||||
}
|
||||
|
||||
func percentReplace(str string) string {
|
||||
str = strings.Replace(str, "+", "%20", -1)
|
||||
str = strings.Replace(str, "*", "%2A", -1)
|
||||
str = strings.Replace(str, "%7E", "~", -1)
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
// CreateSignatureForRequest creates signature for query string values
|
||||
func CreateSignatureForRequest(method string, values *url.Values, accessKeySecret string) string {
|
||||
|
||||
canonicalizedQueryString := percentReplace(values.Encode())
|
||||
|
||||
stringToSign := method + "&%2F&" + url.QueryEscape(canonicalizedQueryString)
|
||||
|
||||
return CreateSignature(stringToSign, accessKeySecret)
|
||||
}
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
srand "crypto/rand"
|
||||
"encoding/binary"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
const dictionary = "_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||
|
||||
//CreateRandomString create random string
|
||||
func CreateRandomString() string {
|
||||
b := make([]byte, 32)
|
||||
l := len(dictionary)
|
||||
|
||||
_, err := srand.Read(b)
|
||||
|
||||
if err != nil {
|
||||
// fail back to insecure rand
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
for i := range b {
|
||||
b[i] = dictionary[rand.Int()%l]
|
||||
}
|
||||
} else {
|
||||
for i, v := range b {
|
||||
b[i] = dictionary[v%byte(l)]
|
||||
}
|
||||
}
|
||||
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// Encode encodes the values into ``URL encoded'' form
|
||||
// ("acl&bar=baz&foo=quux") sorted by key.
|
||||
func Encode(v url.Values) string {
|
||||
if v == nil {
|
||||
return ""
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
keys := make([]string, 0, len(v))
|
||||
for k := range v {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, k := range keys {
|
||||
vs := v[k]
|
||||
prefix := url.QueryEscape(k)
|
||||
for _, v := range vs {
|
||||
if buf.Len() > 0 {
|
||||
buf.WriteByte('&')
|
||||
}
|
||||
buf.WriteString(prefix)
|
||||
if v != "" {
|
||||
buf.WriteString("=")
|
||||
buf.WriteString(url.QueryEscape(v))
|
||||
}
|
||||
}
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func GetGMTime() string {
|
||||
return time.Now().UTC().Format(http.TimeFormat)
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
func randUint32() uint32 {
|
||||
return randUint32Slice(1)[0]
|
||||
}
|
||||
|
||||
func randUint32Slice(c int) []uint32 {
|
||||
b := make([]byte, c*4)
|
||||
|
||||
_, err := srand.Read(b)
|
||||
|
||||
if err != nil {
|
||||
// fail back to insecure rand
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
for i := range b {
|
||||
b[i] = byte(rand.Int())
|
||||
}
|
||||
}
|
||||
|
||||
n := make([]uint32, c)
|
||||
|
||||
for i := range n {
|
||||
n[i] = binary.BigEndian.Uint32(b[i*4 : i*4+4])
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
func toByte(n uint32, st, ed byte) byte {
|
||||
return byte(n%uint32(ed-st+1) + uint32(st))
|
||||
}
|
||||
|
||||
func toDigit(n uint32) byte {
|
||||
return toByte(n, '0', '9')
|
||||
}
|
||||
|
||||
func toLowerLetter(n uint32) byte {
|
||||
return toByte(n, 'a', 'z')
|
||||
}
|
||||
|
||||
func toUpperLetter(n uint32) byte {
|
||||
return toByte(n, 'A', 'Z')
|
||||
}
|
||||
|
||||
type convFunc func(uint32) byte
|
||||
|
||||
var convFuncs = []convFunc{toDigit, toLowerLetter, toUpperLetter}
|
||||
|
||||
// tools for generating a random ECS instance password
|
||||
// from 8 to 30 char MUST contain digit upper, case letter and upper case letter
|
||||
// http://docs.aliyun.com/#/pub/ecs/open-api/instance&createinstance
|
||||
func GenerateRandomECSPassword() string {
|
||||
|
||||
// [8, 30]
|
||||
l := int(randUint32()%23 + 8)
|
||||
|
||||
n := randUint32Slice(l)
|
||||
|
||||
b := make([]byte, l)
|
||||
|
||||
b[0] = toDigit(n[0])
|
||||
b[1] = toLowerLetter(n[1])
|
||||
b[2] = toUpperLetter(n[2])
|
||||
|
||||
for i := 3; i < l; i++ {
|
||||
b[i] = convFuncs[n[i]%3](n[i])
|
||||
}
|
||||
|
||||
s := make([]byte, l)
|
||||
perm := rand.Perm(l)
|
||||
for i, v := range perm {
|
||||
s[v] = b[i]
|
||||
}
|
||||
|
||||
return string(s)
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user