alibabacloudstack/connectivity/client.go (1,229 lines of code) (raw):
package connectivity
import (
"encoding/json"
"log"
roaCS "github.com/alibabacloud-go/cs-20151215/v5/client"
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
roa "github.com/alibabacloud-go/tea-roa/client"
rpc "github.com/alibabacloud-go/tea-rpc/client"
"github.com/alibabacloud-go/tea/tea"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
"github.com/aliyun/alibaba-cloud-sdk-go/services/adb"
"github.com/aliyun/alibaba-cloud-sdk-go/services/alidns"
"github.com/aliyun/alibaba-cloud-sdk-go/services/alikafka"
"github.com/aliyun/alibaba-cloud-sdk-go/services/bssopenapi"
"github.com/aliyun/alibaba-cloud-sdk-go/services/cdn"
"github.com/aliyun/alibaba-cloud-sdk-go/services/cloudapi"
"github.com/aliyun/alibaba-cloud-sdk-go/services/cms"
"github.com/aliyun/alibaba-cloud-sdk-go/services/cr_ee"
"github.com/aliyun/alibaba-cloud-sdk-go/services/dds"
"github.com/aliyun/alibaba-cloud-sdk-go/services/drds"
"github.com/aliyun/alibaba-cloud-sdk-go/services/edas"
"github.com/aliyun/alibaba-cloud-sdk-go/services/elasticsearch"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ess"
"github.com/aliyun/alibaba-cloud-sdk-go/services/gpdb"
"github.com/aliyun/alibaba-cloud-sdk-go/services/hbase"
"github.com/aliyun/alibaba-cloud-sdk-go/services/maxcompute"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ons"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ots"
"github.com/aliyun/alibaba-cloud-sdk-go/services/polardb"
r_kvstore "github.com/aliyun/alibaba-cloud-sdk-go/services/r-kvstore"
"github.com/aliyun/alibaba-cloud-sdk-go/services/rds"
"github.com/aliyun/alibaba-cloud-sdk-go/services/slb"
slsPop "github.com/aliyun/alibaba-cloud-sdk-go/services/sls"
"github.com/aliyun/aliyun-datahub-sdk-go/datahub"
sls "github.com/aliyun/aliyun-log-go-sdk"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
"github.com/aliyun/aliyun-tablestore-go-sdk/tablestore"
"github.com/aliyun/fc-go-sdk"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
"github.com/aliyun/alibaba-cloud-sdk-go/services/kms"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ram"
"github.com/aliyun/alibaba-cloud-sdk-go/services/vpc"
"sync"
rpcutil "github.com/alibabacloud-go/tea-rpc-utils/service"
util "github.com/alibabacloud-go/tea-utils/service"
"github.com/denverdino/aliyungo/cs"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/aliyun/terraform-provider-alibabacloudstack/alibabacloudstack/errmsgs"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"fmt"
"net/http"
"net/url"
"os"
"regexp"
"strconv"
"strings"
"time"
)
type AlibabacloudStackClient struct {
SourceIp string
SecureTransport string
Region Region
RegionId string
Domain string
AccessKey string
SecretKey string
Department string
ResourceGroup string
ResourceGroupId string
Config *Config
teaRpcSdkConfig rpc.Config
teaRoaSdkConfig roa.Config
accountId string
roleId int
Conns map[ServiceCode]*sdk.Client
ascmconn *sdk.Client
ecsconn *ecs.Client
accountIdMutex sync.RWMutex
roleIdMutex sync.RWMutex
vpcconn *vpc.Client
slbconn *slb.Client
csconn *cs.Client
polarDBconn *polardb.Client
cdnconn *cdn.Client
kmsconn *kms.Client
bssopenapiconn *bssopenapi.Client
rdsconn *rds.Client
ramconn *ram.Client
gpdbconn *gpdb.Client
drdsconn *drds.Client
elasticsearchconn *elasticsearch.Client
hbaseconn *hbase.Client
adbconn *adb.Client
ossconn *oss.Client
rkvconn *r_kvstore.Client
fcconn *fc.Client
ddsconn *dds.Client
onsconn *ons.Client
logconn *sls.Client
logpopconn *slsPop.Client
dnsconn *alidns.Client
edasconn *edas.Client
creeconn *cr_ee.Client
cmsconn *cms.Client
maxcomputeconn *maxcompute.Client
alikafkaconn *alikafka.Client
otsconn *ots.Client
OtsInstanceName string
tablestoreconnByInstanceName map[string]*tablestore.TableStoreClient
dhconn datahub.DataHubApi
cloudapiconn *cloudapi.Client
Eagleeye EagleEye
}
const (
ApiVersion20140526 = ApiVersion("2014-05-26")
ApiVersion20160815 = ApiVersion("2016-08-15")
ApiVersion20140515 = ApiVersion("2014-05-15")
ApiVersion20190510 = ApiVersion("2019-05-10")
)
const DefaultClientRetryCountSmall = 5
const Terraform = "HashiCorp-Terraform"
const Provider = "Terraform-Provider"
const Module = "Terraform-Module"
type ApiVersion string
// The main version number that is being run at the moment.
var ProviderVersion = "0.0.99"
var TerraformVersion = strings.TrimSuffix(schema.Provider{}.TerraformVersion, "-dev")
var goSdkMutex = sync.RWMutex{} // The Go SDK is not thread-safe
var loadSdkfromRemoteMutex = sync.Mutex{}
var loadSdkEndpointMutex = sync.Mutex{}
// Client for AlibabacloudStackClient
func (c *Config) Client() (*AlibabacloudStackClient, error) {
// Get the auth and region. This can fail if keys/regions were not
// specified and we're attempting to use the environment.
teaRpcSdkConfig, err := c.getTeaRpcDslSdkConfig(true)
if err != nil {
return nil, err
}
teaRoaSdkConfig, err := c.getTeaRoaDslSdkConfig(true)
if err != nil {
return nil, err
}
return &AlibabacloudStackClient{
Config: c,
teaRpcSdkConfig: teaRpcSdkConfig,
teaRoaSdkConfig: teaRoaSdkConfig,
Region: c.Region,
RegionId: c.RegionId,
AccessKey: c.AccessKey,
SecretKey: c.SecretKey,
Department: c.Department,
ResourceGroup: c.ResourceGroup,
ResourceGroupId: c.ResourceGroupId,
Domain: c.Domain,
OtsInstanceName: c.OtsInstanceName,
Conns: make(map[ServiceCode]*sdk.Client),
tablestoreconnByInstanceName: make(map[string]*tablestore.TableStoreClient),
Eagleeye: c.Eagleeye,
}, nil
}
func (client *AlibabacloudStackClient) NewTeaSDkClient(productCode string, endpoint string) (*rpc.Client, error) {
if endpoint == "" {
return nil, fmt.Errorf("[ERROR] missing the product %s endpoint.", productCode)
}
sdkConfig := client.teaRpcSdkConfig
sdkConfig.SetEndpoint(endpoint).SetReadTimeout(client.Config.ClientReadTimeout * 1000) //单位毫秒
conn, err := rpc.NewClient(&sdkConfig)
for key, value := range client.defaultHeaders(productCode) {
conn.Headers[key] = &value
}
if err != nil {
return nil, fmt.Errorf("unable to initialize the %s client: %#v", productCode, err)
}
return conn, nil
}
func (client *AlibabacloudStackClient) WithProductSDKClient(popcode ServiceCode) (*sdk.Client, error) {
endpoint := client.Config.Endpoints[popcode]
if endpoint == "" {
return nil, fmt.Errorf("[ERROR] unable to initialize the %s client: endpoint or domain is not provided", string(popcode))
}
ramSupported := true
if popcode == STSCode {
ramSupported = false // TODO: STS不支持NewRamRoleArnWithPolicyCredential,待排查
}
conn, err := sdk.NewClientWithOptions(client.Config.RegionId, client.getSdkConfig(), client.Config.getAuthCredential(true, ramSupported))
if err != nil {
return nil, fmt.Errorf("unable to initialize the %s client: %#v", popcode, err)
}
conn.Domain = endpoint
conn.SetReadTimeout(time.Duration(client.Config.ClientReadTimeout) * time.Hour)
conn.SetConnectTimeout(time.Duration(client.Config.ClientConnectTimeout) * time.Hour)
conn.SourceIp = client.Config.SourceIp
conn.SecureTransport = client.Config.SecureTransport
conn.AppendUserAgent(Terraform, TerraformVersion)
conn.AppendUserAgent(Provider, ProviderVersion)
conn.AppendUserAgent(Module, client.Config.ConfigurationSource)
conn.SetHTTPSInsecure(client.Config.Insecure)
if client.Config.Proxy != "" {
conn.SetHttpsProxy(client.Config.Proxy)
conn.SetHttpProxy(client.Config.Proxy)
}
return conn, nil
}
func (client *AlibabacloudStackClient) WithEcsClient(do func(*ecs.Client) (interface{}, error)) (interface{}, error) {
if client.ecsconn == nil {
conn, error := client.WithProductSDKClient(EcsCode)
if error != nil {
return nil, error
}
client.ecsconn = &ecs.Client{
Client: *conn,
}
}
return do(client.ecsconn)
}
func (client *AlibabacloudStackClient) WithAscmClient(do func(*sdk.Client) (interface{}, error)) (interface{}, error) {
var err error
if client.ascmconn == nil {
client.ascmconn, err = client.WithProductSDKClient(ASCMCode)
if err != nil {
return nil, err
}
}
return do(client.ascmconn)
}
func (client *AlibabacloudStackClient) WithElasticsearchClient(do func(*elasticsearch.Client) (interface{}, error)) (interface{}, error) {
if client.elasticsearchconn == nil {
conn, error := client.WithProductSDKClient(ELASTICSEARCHCode)
if error != nil {
return nil, error
}
client.elasticsearchconn = &elasticsearch.Client{
Client: *conn,
}
}
return do(client.elasticsearchconn)
}
func (client *AlibabacloudStackClient) WithCloudApiClient(do func(*cloudapi.Client) (interface{}, error)) (interface{}, error) {
if client.cloudapiconn == nil {
conn, error := client.WithProductSDKClient(CLOUDAPICode)
if error != nil {
return nil, error
}
client.cloudapiconn = &cloudapi.Client{
Client: *conn,
}
}
return do(client.cloudapiconn)
}
func (client *AlibabacloudStackClient) WithEssClient(do func(*ess.Client) (interface{}, error)) (interface{}, error) {
conn, err := client.getConnectClient("ESS")
if err != nil {
return nil, err
}
essconn := &ess.Client{
Client: *conn,
}
return retryDo(func() (interface{}, error) {
return do(essconn)
})
}
func (client *AlibabacloudStackClient) WithOnsClient(do func(*ons.Client) (interface{}, error)) (interface{}, error) {
if client.onsconn == nil {
conn, error := client.WithProductSDKClient(ONSCode)
if error != nil {
return nil, error
}
client.onsconn = &ons.Client{
Client: *conn,
}
}
return do(client.onsconn)
}
func (client *AlibabacloudStackClient) WithRkvClient(do func(*r_kvstore.Client) (interface{}, error)) (interface{}, error) {
if client.rkvconn == nil {
conn, error := client.WithProductSDKClient(KVSTORECode)
if error != nil {
return nil, error
}
client.rkvconn = &r_kvstore.Client{
Client: *conn,
}
}
return do(client.rkvconn)
}
func (client *AlibabacloudStackClient) WithGpdbClient(do func(*gpdb.Client) (interface{}, error)) (interface{}, error) {
if client.gpdbconn == nil {
conn, error := client.WithProductSDKClient(GPDBCode)
if error != nil {
return nil, error
}
client.gpdbconn = &gpdb.Client{
Client: *conn,
}
}
return do(client.gpdbconn)
}
func (client *AlibabacloudStackClient) WithAdbClient(do func(*adb.Client) (interface{}, error)) (interface{}, error) {
if client.adbconn == nil {
conn, error := client.WithProductSDKClient(ADBCode)
if error != nil {
return nil, error
}
client.adbconn = &adb.Client{
Client: *conn,
}
}
return do(client.adbconn)
}
func (client *AlibabacloudStackClient) WithHbaseClient(do func(*hbase.Client) (interface{}, error)) (interface{}, error) {
if client.hbaseconn == nil {
conn, error := client.WithProductSDKClient(HBASECode)
if error != nil {
return nil, error
}
client.hbaseconn = &hbase.Client{
Client: *conn,
}
}
return do(client.hbaseconn)
}
func (client *AlibabacloudStackClient) WithVpcClient(do func(*vpc.Client) (interface{}, error)) (interface{}, error) {
if client.vpcconn == nil {
conn, error := client.WithProductSDKClient(VPCCode)
if error != nil {
return nil, error
}
client.vpcconn = &vpc.Client{
Client: *conn,
}
}
return do(client.vpcconn)
}
func (client *AlibabacloudStackClient) WithSlbClient(do func(*slb.Client) (interface{}, error)) (interface{}, error) {
if client.slbconn == nil {
conn, error := client.WithProductSDKClient(SLBCode)
if error != nil {
return nil, error
}
client.slbconn = &slb.Client{
Client: *conn,
}
}
return do(client.slbconn)
}
func (client *AlibabacloudStackClient) WithDdsClient(do func(*dds.Client) (interface{}, error)) (interface{}, error) {
if client.ddsconn == nil {
conn, error := client.WithProductSDKClient(DDSCode)
if error != nil {
return nil, error
}
client.ddsconn = &dds.Client{
Client: *conn,
}
}
return do(client.ddsconn)
}
func (client *AlibabacloudStackClient) getSdkConfig() *sdk.Config {
log.Printf("Protocol is set to %s", client.Config.Protocol)
return sdk.NewConfig().
WithMaxRetryTime(DefaultClientRetryCountSmall).
WithTimeout(time.Duration(30) * time.Second).
WithEnableAsync(true).
WithGoRoutinePoolSize(100).
WithMaxTaskQueueSize(10000).
WithDebug(false).
WithHttpTransport(client.getTransport()).
WithScheme(strings.ToLower(client.Config.Protocol))
}
func (client *AlibabacloudStackClient) getTransport() *http.Transport {
handshakeTimeout, err := strconv.Atoi(os.Getenv("TLSHandshakeTimeout"))
if err != nil {
handshakeTimeout = 120
}
transport := &http.Transport{}
transport.TLSHandshakeTimeout = time.Duration(handshakeTimeout) * time.Second
return transport
}
func (client *AlibabacloudStackClient) AccountId() (string, error) {
client.accountIdMutex.Lock()
defer client.accountIdMutex.Unlock()
if client.accountId == "" {
log.Printf("[DEBUG] account_id not provided, attempting to retrieve it automatically...")
identity, err := client.GetCallerIdentity()
if err != nil {
return "", err
}
if identity == "" {
return "", fmt.Errorf("caller identity doesn't contain any AccountId")
}
client.accountId = identity
}
return client.accountId, nil
}
func (client *AlibabacloudStackClient) RoleIds() (int, error) {
client.roleIdMutex.Lock()
defer client.roleIdMutex.Unlock()
if client.roleId == 0 {
log.Printf("[DEBUG] role_ids not provided, attempting to retrieve it automatically...")
roleId, err := client.GetCallerDefaultRole()
if err != nil {
return 0, err
}
if roleId == 0 {
return 0, fmt.Errorf("caller identity doesn't contain default RoleId")
}
client.roleId = roleId
}
return client.roleId, nil
}
func (client *AlibabacloudStackClient) getHttpProxy() (proxy *url.URL, err error) {
if client.Config.Protocol == "HTTPS" {
if rawurl := os.Getenv("HTTPS_PROXY"); rawurl != "" {
proxy, err = url.Parse(rawurl)
} else if rawurl := os.Getenv("https_proxy"); rawurl != "" {
proxy, err = url.Parse(rawurl)
}
} else {
if rawurl := os.Getenv("HTTP_PROXY"); rawurl != "" {
proxy, err = url.Parse(rawurl)
} else if rawurl := os.Getenv("http_proxy"); rawurl != "" {
proxy, err = url.Parse(rawurl)
}
}
return proxy, err
}
func (client *AlibabacloudStackClient) skipProxy(endpoint string) (bool, error) {
var urls []string
if rawurl := os.Getenv("NO_PROXY"); rawurl != "" {
urls = strings.Split(rawurl, ",")
} else if rawurl := os.Getenv("no_proxy"); rawurl != "" {
urls = strings.Split(rawurl, ",")
}
for _, value := range urls {
if strings.HasPrefix(value, "*") {
value = fmt.Sprintf(".%s", value)
}
noProxyReg, err := regexp.Compile(value)
if err != nil {
return false, err
}
if noProxyReg.MatchString(endpoint) {
return true, nil
}
}
return false, nil
}
func (client *AlibabacloudStackClient) WithKmsClient(do func(*kms.Client) (interface{}, error)) (interface{}, error) {
// Initialize the KMS client if necessary
if client.kmsconn == nil {
conn, error := client.WithProductSDKClient(KmsCode)
if error != nil {
return nil, error
}
client.kmsconn = &kms.Client{
Client: *conn,
}
}
return do(client.kmsconn)
}
func (client *AlibabacloudStackClient) GetCallerInfo() (*responses.BaseResponse, error) {
endpoint := client.Config.Endpoints[ASCMCode]
if endpoint == "" {
return nil, fmt.Errorf("unable to initialize the ascm client: endpoint or domain is not provided for ascm service")
}
ascmClient, err := sdk.NewClientWithAccessKey(client.Config.RegionId, client.Config.AccessKey, client.Config.SecretKey)
if err != nil {
return nil, fmt.Errorf("unable to initialize the ascm client: %#v", err)
}
ascmClient.AppendUserAgent(Terraform, TerraformVersion)
ascmClient.AppendUserAgent(Provider, ProviderVersion)
ascmClient.AppendUserAgent(Module, client.Config.ConfigurationSource)
ascmClient.SetHTTPSInsecure(client.Config.Insecure)
ascmClient.Domain = endpoint
if client.Config.Proxy != "" {
ascmClient.SetHttpProxy(client.Config.Proxy)
}
if client.Config.Department == "" || client.Config.ResourceGroup == "" {
return nil, fmt.Errorf("unable to initialize the ascm client: department or resource_group is not provided")
}
request := requests.NewCommonRequest()
if strings.ToLower(client.Config.Protocol) == "https" {
request.Scheme = "https"
} else {
request.Scheme = "http"
}
if client.Config.Insecure {
request.SetHTTPSInsecure(client.Config.Insecure)
}
request.Method = "GET" // Set request method
request.Product = "ascm" // Specify product
request.Domain = endpoint // Location Service will not be enabled if the host is specified. For example, service with a Certification type-Bearer Token should be specified
request.Version = "2019-05-10" // Specify product version
request.ApiName = "GetUserInfo"
request.QueryParams = map[string]string{
// "AccessKeySecret": client.Config.SecretKey,
// "SecurityToken": client.Config.SecurityToken,
// "Product": "ascm",
// "Department": client.Config.Department,
// "ResourceGroup": client.Config.ResourceGroup,
// "RegionId": client.RegionId,
// "Action": "GetAllNavigationInfo",
// "Version": "2019-05-10",
"SignatureVersion": "1.0",
}
resp := responses.BaseResponse{}
request.TransToAcsRequest()
err = ascmClient.DoAction(request, &resp)
if err != nil {
return nil, err
}
return &resp, nil
}
func (client *AlibabacloudStackClient) GetCallerIdentity() (string, error) {
resp, err := client.GetCallerInfo()
if err != nil {
return "", err
}
response := &AccountId{}
err = json.Unmarshal(resp.GetHttpContentBytes(), response)
ownerId := response.Data.PrimaryKey
if ownerId == "" {
return "", fmt.Errorf("ownerId not found")
}
return ownerId, err
}
func (client *AlibabacloudStackClient) GetCallerDefaultRole() (int, error) {
resp, err := client.GetCallerInfo()
if err != nil {
return 1, err
}
response := &RoleId{}
err = json.Unmarshal(resp.GetHttpContentBytes(), response)
roleId := response.Data.DefaultRole.Id
if roleId == 0 {
return 0, fmt.Errorf("default roleId not found")
}
return roleId, err
}
type AccountId struct {
Data struct {
PrimaryKey string `json:"primaryKey"`
} `json:"data"`
}
type RoleId struct {
Data struct {
DefaultRole struct {
Id int `json:"id"`
} `json:"defaultRole"`
} `json:"data"`
}
func (client *AlibabacloudStackClient) WithBssopenapiClient(do func(*bssopenapi.Client) (interface{}, error)) (interface{}, error) {
// Initialize the bssopenapi client if necessary
if client.bssopenapiconn == nil {
conn, error := client.WithProductSDKClient(BssDataCode)
if error != nil {
return nil, error
}
client.bssopenapiconn = &bssopenapi.Client{
Client: *conn,
}
}
return do(client.bssopenapiconn)
}
func (client *AlibabacloudStackClient) NewNasClient() (*rpc.Client, error) {
return client.NewTeaSDkClient("nas", client.Config.Endpoints[NasCode])
}
func (client *AlibabacloudStackClient) WithOssDataClient(do func(*oss.Client) (interface{}, error)) (interface{}, error) {
goSdkMutex.Lock()
defer goSdkMutex.Unlock()
// Initialize the OSS client if necessary
if client.ossconn == nil {
schma := strings.ToLower(client.Config.Protocol)
endpoint := client.Config.Endpoints[OssDataCode]
if endpoint == "" {
return nil, fmt.Errorf("unable to initialize the oss client: endpoint or domain is not provided for OSS service")
}
if !strings.HasPrefix(endpoint, "http") {
endpoint = fmt.Sprintf("%s://%s", schma, endpoint)
}
clientOptions := []oss.ClientOption{oss.UserAgent(client.getUserAgent()),
oss.SecurityToken(client.Config.SecurityToken)}
if client.Config.Proxy != "" {
clientOptions = append(clientOptions, oss.Proxy(client.Config.Proxy))
}
clientOptions = append(clientOptions, oss.UseCname(false))
ossconn, err := oss.New(endpoint, client.Config.AccessKey, client.Config.SecretKey, clientOptions...)
if err != nil {
return nil, fmt.Errorf("unable to initialize the OSS client: %#v", err)
}
client.ossconn = ossconn
}
return do(client.ossconn)
}
func (client *AlibabacloudStackClient) WithRamClient(do func(*ram.Client) (interface{}, error)) (interface{}, error) {
// Initialize the RAM client if necessary
if client.ramconn == nil {
conn, error := client.WithProductSDKClient(RAMCode)
if error != nil {
return nil, error
}
client.ramconn = &ram.Client{
Client: *conn,
}
}
return do(client.ramconn)
}
func (client *AlibabacloudStackClient) WithRdsClient(do func(*rds.Client) (interface{}, error)) (interface{}, error) {
if client.rdsconn == nil {
conn, error := client.WithProductSDKClient(RDSCode)
if error != nil {
return nil, error
}
client.rdsconn = &rds.Client{
Client: *conn,
}
}
return do(client.rdsconn)
}
func (client *AlibabacloudStackClient) WithPolardbClient(do func(*polardb.Client) (interface{}, error)) (interface{}, error) {
if client.rdsconn == nil {
conn, error := client.WithProductSDKClient(RDSCode)
if error != nil {
return nil, error
}
client.rdsconn = &rds.Client{
Client: *conn,
}
}
return do(client.polarDBconn)
}
func (client *AlibabacloudStackClient) WithCdnClient(do func(*cdn.Client) (interface{}, error)) (interface{}, error) {
if client.cdnconn == nil {
conn, error := client.WithProductSDKClient(CDNCode)
if error != nil {
return nil, error
}
client.cdnconn = &cdn.Client{
Client: *conn,
}
}
return do(client.cdnconn)
}
func (client *AlibabacloudStackClient) getUserAgent() string {
return fmt.Sprintf("%s/%s %s/%s %s/%s", Terraform, TerraformVersion, Provider, ProviderVersion, Module, client.Config.ConfigurationSource)
}
func (client *AlibabacloudStackClient) WithCsClient(do func(*cs.Client) (interface{}, error)) (interface{}, error) {
goSdkMutex.Lock()
defer goSdkMutex.Unlock()
// Initialize the CS client if necessary
if client.csconn == nil {
csconn := cs.NewClientForAussumeRole(client.Config.AccessKey, client.Config.SecretKey, client.Config.SecurityToken)
csconn.SetUserAgent(client.getUserAgent())
endpoint := client.Config.Endpoints[CONTAINCode]
if endpoint == "" {
return nil, fmt.Errorf("unable to initialize the cs client: endpoint or domain is not provided for cs service")
}
if endpoint != "" {
if strings.ToLower(client.Config.Protocol) == "https" {
endpoint = fmt.Sprintf("https://%s", endpoint)
} else {
endpoint = fmt.Sprintf("http://%s", endpoint)
}
csconn.SetEndpoint(endpoint)
}
if client.Config.Proxy != "" {
// FIXME: 修改环境变量会存在风险
os.Setenv("http_proxy", client.Config.Proxy)
}
client.csconn = csconn
}
return do(client.csconn)
}
func (client *AlibabacloudStackClient) getHttpProxyUrl() *url.URL {
for _, v := range []string{"HTTPS_PROXY", "https_proxy", "HTTP_PROXY", "http_proxy"} {
value := strings.Trim(os.Getenv(v), " ")
if value != "" {
if !regexp.MustCompile(`^http(s)?://`).MatchString(value) {
value = fmt.Sprintf("https://%s", value)
}
proxyUrl, err := url.Parse(value)
if err == nil {
return proxyUrl
}
break
}
}
return nil
}
func (client *AlibabacloudStackClient) WithOssBucketClient(bucketName string, do func(*oss.Bucket) (interface{}, error)) (interface{}, error) {
return client.WithOssDataClient(func(ossClient *oss.Client) (interface{}, error) {
bucket, err := client.ossconn.Bucket(bucketName)
if err != nil {
return nil, fmt.Errorf("unable to get the bucket %s: %#v", bucketName, err)
}
return do(bucket)
})
}
func (client *AlibabacloudStackClient) WithSlsClient(do func(*slsPop.Client) (interface{}, error)) (interface{}, error) {
if client.logpopconn == nil {
conn, error := client.WithProductSDKClient(SLSCode)
if error != nil {
return nil, error
}
client.logpopconn = &slsPop.Client{
Client: *conn,
}
}
return do(client.logpopconn)
}
func (client *AlibabacloudStackClient) WithSlsDataClient(do func(*sls.Client) (interface{}, error)) (interface{}, error) {
goSdkMutex.Lock()
defer goSdkMutex.Unlock()
// Initialize the LOG client if necessary
if client.logconn == nil {
endpoint := client.Config.Endpoints[SlSDataCode]
if endpoint == "" {
return nil, fmt.Errorf("unable to initialize the log client: endpoint or domain is not provided for log service")
}
if client.Config.Proxy != "" {
// FIXME: 修改环境变量会存在风险
os.Setenv("http_proxy", client.Config.Proxy)
os.Setenv("https_proxy", client.Config.Proxy)
}
client.logconn = &sls.Client{
// AccessKeyID: client.Config.OrganizationAccessKey,
// AccessKeySecret: client.Config.OrganizationSecretKey,
AccessKeyID: client.Config.AccessKey,
AccessKeySecret: client.Config.SecretKey,
Endpoint: client.Config.Endpoints[SlSDataCode],
SecurityToken: client.Config.SecurityToken,
UserAgent: client.getUserAgent(),
}
}
return do(client.logconn)
}
func (client *AlibabacloudStackClient) WithAlikafkaClient(do func(*alikafka.Client) (interface{}, error)) (interface{}, error) {
if client.alikafkaconn == nil {
conn, error := client.WithProductSDKClient(ALIKAFKACode)
if error != nil {
return nil, error
}
client.alikafkaconn = &alikafka.Client{
Client: *conn,
}
}
return do(client.alikafkaconn)
}
func (client *AlibabacloudStackClient) WithEdasClient(do func(*edas.Client) (interface{}, error)) (interface{}, error) {
// Initialize the edas client if necessary
if client.edasconn == nil {
endpoint := client.Config.Endpoints[EDASCode]
if endpoint == "" {
return nil, fmt.Errorf("unable to initialize the Edas client: endpoint or domain is not provided for Edas service")
}
// edasconn, err := edas.NewClientWithOptions(client.Config.RegionId, client.getSdkConfig().WithTimeout(time.Duration(60)*time.Second), client.Config.getAuthCredential(true))
edasconn, err := edas.NewClientWithAccessKey(client.Config.RegionId, client.Config.AccessKey, client.Config.SecretKey)
if err != nil {
return nil, fmt.Errorf("unable to initialize the Edas client: %#v", err)
}
edasconn.SetReadTimeout(time.Duration(client.Config.ClientReadTimeout) * time.Millisecond)
edasconn.SetConnectTimeout(time.Duration(client.Config.ClientConnectTimeout) * time.Millisecond)
edasconn.SourceIp = client.Config.SourceIp
edasconn.SecureTransport = client.Config.SecureTransport
edasconn.Domain = endpoint
edasconn.AppendUserAgent(Terraform, TerraformVersion)
edasconn.AppendUserAgent(Provider, ProviderVersion)
edasconn.AppendUserAgent(Module, client.Config.ConfigurationSource)
if client.Config.Proxy != "" {
edasconn.SetHttpsProxy(client.Config.Proxy)
edasconn.SetHttpProxy(client.Config.Proxy)
}
client.edasconn = edasconn
}
return do(client.edasconn)
}
func (client *AlibabacloudStackClient) WithCrEeClient(do func(*cr_ee.Client) (interface{}, error)) (interface{}, error) {
if client.creeconn == nil {
conn, error := client.WithProductSDKClient(CREECode)
if error != nil {
return nil, error
}
client.creeconn = &cr_ee.Client{
Client: *conn,
}
}
return do(client.creeconn)
}
func (client *AlibabacloudStackClient) WithDnsClient(do func(*alidns.Client) (interface{}, error)) (interface{}, error) {
if client.dnsconn == nil {
conn, error := client.WithProductSDKClient(DNSCode)
if error != nil {
return nil, error
}
client.dnsconn = &alidns.Client{
Client: *conn,
}
}
return do(client.dnsconn)
}
func (client *AlibabacloudStackClient) WithCmsClient(do func(*cms.Client) (interface{}, error)) (interface{}, error) {
// Initialize the CMS client if necessary
if client.cmsconn == nil {
conn, error := client.WithProductSDKClient(CMSCode)
if error != nil {
return nil, error
}
client.cmsconn = &cms.Client{
Client: *conn,
}
}
return do(client.cmsconn)
}
func (client *AlibabacloudStackClient) NewHitsdbClient() (*rpc.Client, error) {
return client.NewTeaSDkClient("hitsdb", client.Config.Endpoints[HitsdbCode])
}
func (client *AlibabacloudStackClient) NewOdpsClient() (*rpc.Client, error) {
return client.NewTeaSDkClient("odps", client.Config.Endpoints[ASCMCode])
}
func (client *AlibabacloudStackClient) NewKmsClient() (*rpc.Client, error) {
return client.NewTeaSDkClient("kms", client.Config.Endpoints[KmsCode])
}
func (client *AlibabacloudStackClient) NewAscmClient() (*rpc.Client, error) {
return client.NewTeaSDkClient("ascm", client.Config.Endpoints[ASCMCode])
}
func (client *AlibabacloudStackClient) NewCloudApiClient() (*rpc.Client, error) {
//sdkConfig.SetEndpoint(endpoint).SetReadTimeout(60000)
return client.NewTeaSDkClient("apigateway", client.Config.Endpoints[CLOUDAPICode])
}
func (client *AlibabacloudStackClient) NewAdsClient() (*rpc.Client, error) {
return client.NewTeaSDkClient("ads", client.Config.Endpoints[ADBCode])
}
func (client *AlibabacloudStackClient) NewCmsClient() (*rpc.Client, error) {
return client.NewTeaSDkClient("cms", client.Config.Endpoints[CMSCode])
}
func (client *AlibabacloudStackClient) WithTableStoreClient(instanceName string, do func(*tablestore.TableStoreClient) (interface{}, error)) (interface{}, error) {
goSdkMutex.Lock()
defer goSdkMutex.Unlock()
// Initialize the TABLESTORE client if necessary
tableStoreClient, ok := client.tablestoreconnByInstanceName[instanceName]
if !ok {
endpoint := client.Config.Endpoints[OTSCode]
if endpoint == "" {
return nil, fmt.Errorf("[ERROR] missing the product Ots endpoint.")
}
tableStoreClient = tablestore.NewClientWithConfig(endpoint, instanceName, client.Config.AccessKey, client.Config.SecretKey, client.Config.SecurityToken, tablestore.NewDefaultTableStoreConfig())
client.tablestoreconnByInstanceName[instanceName] = tableStoreClient
}
return do(tableStoreClient)
}
func (client *AlibabacloudStackClient) WithOtsClient(do func(*ots.Client) (interface{}, error)) (interface{}, error) {
// Initialize the OTS client if necessary
if client.otsconn == nil {
conn, error := client.WithProductSDKClient(OTSCode)
if error != nil {
return nil, error
}
client.otsconn = &ots.Client{
Client: *conn,
}
}
return do(client.otsconn)
}
func (client *AlibabacloudStackClient) WithDataHubClient(do func(api datahub.DataHubApi) (interface{}, error)) (interface{}, error) {
goSdkMutex.Lock()
defer goSdkMutex.Unlock()
// Initialize the DataHub client if necessary
if client.dhconn == nil {
endpoint := client.Config.Endpoints[DatahubCode]
if endpoint == "" {
return nil, fmt.Errorf("[ERROR] missing the product Ots endpoint.")
}
if !strings.HasPrefix(endpoint, "http") {
endpoint = fmt.Sprintf("https://%s", endpoint)
}
account := datahub.NewStsCredential(client.Config.AccessKey, client.Config.SecretKey, client.Config.SecurityToken)
config := &datahub.Config{
UserAgent: client.getUserAgent(),
}
client.dhconn = datahub.NewClientWithConfig(endpoint, config, account)
}
return do(client.dhconn)
}
func (client *AlibabacloudStackClient) NewVpcClient() (*rpc.Client, error) {
return client.NewTeaSDkClient("vpc", client.Config.Endpoints[VPCCode])
}
func (client *AlibabacloudStackClient) NewEcsClient() (*rpc.Client, error) {
//sdkConfig.SetEndpoint(endpoint).SetReadTimeout(60000)
return client.NewTeaSDkClient("ecs", client.Config.Endpoints[EcsCode])
}
func (client *AlibabacloudStackClient) NewElasticsearchClient() (*rpc.Client, error) {
return client.NewTeaSDkClient("elasticsearch", client.Config.Endpoints[ELASTICSEARCHCode])
}
func (client *AlibabacloudStackClient) NewRosClient() (*rpc.Client, error) {
return client.NewTeaSDkClient("ros", client.Config.Endpoints[RosCode])
}
func (client *AlibabacloudStackClient) NewRdsClient() (*rpc.Client, error) {
return client.NewTeaSDkClient("rds", client.Config.Endpoints[RDSCode])
}
func (client *AlibabacloudStackClient) NewRoaCsClient() (*roaCS.Client, error) {
productCode := "ros"
endpoint := client.Config.Endpoints[RosCode]
if endpoint == "" {
return nil, fmt.Errorf("[ERROR] missing the product %s endpoint.", productCode)
}
// Initialize the CS client if necessary
roaCSConn, err := roaCS.NewClient(&openapi.Config{
AccessKeyId: tea.String(client.Config.AccessKey),
AccessKeySecret: tea.String(client.Config.SecretKey),
SecurityToken: tea.String(client.Config.SecurityToken),
RegionId: tea.String(client.Config.RegionId),
UserAgent: tea.String(client.getUserAgent()),
Endpoint: tea.String(endpoint),
ReadTimeout: tea.Int(client.Config.ClientReadTimeout),
ConnectTimeout: tea.Int(client.Config.ClientConnectTimeout),
})
roaCSConn.Headers = map[string]*string{
"x-acs-organizationid": &client.Config.Department,
"x-acs-resourcegroupid": &client.Config.ResourceGroup,
}
if err != nil {
return nil, err
}
return roaCSConn, nil
}
func (client *AlibabacloudStackClient) NewDtsClient() (*rpc.Client, error) {
return client.NewTeaSDkClient("dts", client.Config.Endpoints[DTSCode])
}
func (client *AlibabacloudStackClient) NewDmsenterpriseClient() (*rpc.Client, error) {
return client.NewTeaSDkClient("dmsenterprise", client.Config.Endpoints[DmsEnterpriseCode])
}
func (client *AlibabacloudStackClient) NewHbaseClient() (*rpc.Client, error) {
return client.NewTeaSDkClient("hbase", client.Config.Endpoints[HBASECode])
}
func (client *AlibabacloudStackClient) WithDrdsClient(do func(*drds.Client) (interface{}, error)) (interface{}, error) {
if client.drdsconn == nil {
conn, error := client.WithProductSDKClient(DRDSCode)
if error != nil {
return nil, error
}
client.drdsconn = &drds.Client{
Client: *conn,
}
}
return do(client.drdsconn)
}
func (client *AlibabacloudStackClient) NewGpdbClient() (*rpc.Client, error) {
return client.NewTeaSDkClient("gpdb", client.Config.Endpoints[GPDBCode])
}
func (client *AlibabacloudStackClient) NewQuickbiClient() (*rpc.Client, error) {
return client.NewTeaSDkClient("quickbi", client.Config.Endpoints[QuickbiCode])
}
func (client *AlibabacloudStackClient) NewCsbClient() (*rpc.Client, error) {
return client.NewTeaSDkClient("csb", client.Config.Endpoints[CSBCode])
}
func (client *AlibabacloudStackClient) NewGdbClient() (*rpc.Client, error) {
return client.NewTeaSDkClient("gdb", client.Config.Endpoints[GDBCode])
}
func (client *AlibabacloudStackClient) NewDataworkspublicClient() (*rpc.Client, error) {
return client.NewTeaSDkClient("dataworkspublic", client.Config.Endpoints[DataworkspublicCode])
}
func (client *AlibabacloudStackClient) NewDataworksPrivateClient() (*rpc.Client, error) {
endpoint := client.Config.Endpoints[DataworkspublicCode]
index := strings.Index(endpoint, ".")
privateEndpoint := "dataworks" + endpoint[index:]
return client.NewTeaSDkClient("dataworks-private-cloud", privateEndpoint)
}
func (client *AlibabacloudStackClient) NewDbsClient() (*rpc.Client, error) {
return client.NewTeaSDkClient("dbs", client.Config.Endpoints[DDSCode])
}
func (client *AlibabacloudStackClient) NewArmsClient() (*rpc.Client, error) {
return client.NewTeaSDkClient("arms", client.Config.Endpoints[ARMSCode])
}
func (client *AlibabacloudStackClient) NewOosClient() (*rpc.Client, error) {
return client.NewTeaSDkClient("oos", client.Config.Endpoints[OosCode])
}
func (client *AlibabacloudStackClient) NewCloudfwClient() (*rpc.Client, error) {
return client.NewTeaSDkClient("cloudfw", client.Config.Endpoints[WafOpenapiCode])
}
func (client *AlibabacloudStackClient) defaultHeaders(popcode string) map[string]string {
return map[string]string{
"RegionId": client.RegionId, // ASAPI
"x-acs-organizationid": client.Department,
"x-acs-resourcegroupid": client.ResourceGroup,
"x-acs-regionid": client.RegionId,
"x-acs-request-version": "v1",
"x-acs-asapi-product": popcode,
"x-ascm-product-name": popcode,
"EagleEye-TraceId": client.Eagleeye.GetTraceId(),
"EagleEye-RpcId": client.Eagleeye.GetRpcId(),
//"x-acs-caller-sdk-source": "Terraform"
//"x-acs-asapi-gateway-version": "3.0" 这个是指定走ASAPI的v3网关流程,目前在维护的是v4,默认会走v4,指定了走v3。不建议走v3,除非有不兼容的地方必须走
}
}
func (client *AlibabacloudStackClient) defaultQueryParams() map[string]string {
return map[string]string{
"RegionId": client.RegionId,
"Department": client.Department,
"OrganizationId": client.Department,
"ResourceGroup": client.ResourceGroup,
}
}
func (client *AlibabacloudStackClient) NewCommonRequest(method string, popcode string, version string, apiname string, pathpattern string) *requests.CommonRequest {
request := requests.NewCommonRequest()
if client.Config.Insecure {
request.SetHTTPSInsecure(client.Config.Insecure)
}
if strings.ToLower(client.Config.Protocol) == "https" {
request.Scheme = "https"
} else {
request.Scheme = "http"
}
request.Method = method
request.RegionId = client.RegionId
request.Headers = client.defaultHeaders(popcode)
request.QueryParams = client.defaultQueryParams()
request.Product = popcode
request.Version = version
request.ApiName = apiname
if pathpattern != "" {
request.PathPattern = pathpattern
}
return request
}
func (client *AlibabacloudStackClient) InitRpcRequest(request requests.RpcRequest) {
if client.Config.Insecure {
request.SetHTTPSInsecure(client.Config.Insecure)
}
if strings.ToLower(client.Config.Protocol) == "https" {
request.Scheme = "https"
} else {
request.Scheme = "http"
}
request.RegionId = client.RegionId
request.Headers = client.defaultHeaders(request.GetProduct())
request.QueryParams = client.defaultQueryParams()
}
func (client *AlibabacloudStackClient) InitRoaRequest(request requests.RoaRequest) {
if client.Config.Insecure {
request.SetHTTPSInsecure(client.Config.Insecure)
}
if strings.ToLower(client.Config.Protocol) == "https" {
request.Scheme = "https"
} else {
request.Scheme = "http"
}
request.RegionId = client.RegionId
request.Headers = client.defaultHeaders(request.GetProduct())
request.QueryParams = client.defaultQueryParams()
}
func (client *AlibabacloudStackClient) DoTeaRequest(method string, popcode string, version string, apiname string, pathpattern string, headers map[string]*string, query map[string]interface{}, body map[string]interface{}) (_result map[string]interface{}, _err error) {
ServiceCodeStr := strings.ReplaceAll(strings.ToUpper(popcode), "-", "_")
endpoint := client.Config.Endpoints[ServiceCode(ServiceCodeStr)]
if endpoint == "" {
return nil, fmt.Errorf("[ERROR] missing the product %s endpoint.", popcode)
}
if headers == nil {
headers = make(map[string]*string)
}
for key, value := range client.defaultHeaders(popcode) {
v := value
headers[key] = &v
}
if query == nil {
query = make(map[string]interface{})
}
for key, value := range client.defaultQueryParams() {
if _, exist := query[key]; !exist {
query[key] = value
}
}
query["Product"] = popcode
var protocol string
if strings.ToLower(client.Config.Protocol) == "https" {
protocol = "https"
} else {
protocol = "http"
}
if popcode == "CloudDns" {
// CloudDns不支持HTTPS
protocol = "http"
}
authType := "AK"
runtime := util.RuntimeOptions{IgnoreSSL: tea.Bool(client.Config.Insecure)}
if client.Config.Proxy != "" {
runtime.HttpProxy = &client.Config.Proxy
runtime.HttpsProxy = &client.Config.Proxy
}
runtime.SetAutoretry(false) // 使用ASAPI时,Tea包不能重试,他会修改endpoint
var response map[string]interface{}
wait := IncrementalWait(3*time.Second, 3*time.Second)
err := resource.Retry(5*time.Minute, func() *resource.RetryError {
var err error
// conn 必须在每次请求前初始化,因为DoRequest会修改conn的内容,会导致下次conn的配置失效
if pathpattern != "" {
response, err = func() (map[string]interface{}, error) {
sdkConfig := client.teaRoaSdkConfig
sdkConfig.SetEndpoint(endpoint).SetReadTimeout(client.Config.ClientReadTimeout * 1000) //单位毫秒
conn, err := roa.NewClient(&sdkConfig)
if err != nil {
return nil, err
}
roa_query := rpcutil.Query(tea.ToMap(map[string]interface{}{
"Format": "json",
"Timestamp": tea.StringValue(rpcutil.GetTimestamp()),
"Version": tea.StringValue(&version),
"SignatureNonce": tea.StringValue(util.GetNonce()),
}, query))
r, e := conn.DoRequestWithAction(&apiname, &version, &protocol, &method, &authType, &pathpattern, roa_query, headers, body, &runtime)
if e != nil {
return r, e
} else {
return r["body"].(map[string]interface{}), e
}
}()
} else {
response, err = func() (map[string]interface{}, error) {
sdkConfig := client.teaRpcSdkConfig
sdkConfig.SetEndpoint(endpoint).SetReadTimeout(client.Config.ClientReadTimeout * 1000) //单位毫秒
conn, err := rpc.NewClient(&sdkConfig)
if err != nil {
return nil, err
}
conn.Headers = headers
return conn.DoRequest(&apiname, &protocol, &method, &version, &authType, query, body, &runtime)
}()
}
log.Printf(" ================================ %s ======================================\n query %v \n request %v \n response: %v", apiname, query, body, response)
if err != nil {
if errmsgs.NotFoundError(err) {
return resource.NonRetryableError(err)
}
errmsg := errmsgs.GetAsapiErrorMessage(response)
if errmsg != "" {
return resource.NonRetryableError(errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, "popcode", apiname, errmsgs.AlibabacloudStackSdkGoERROR, errmsg))
}
wait()
return resource.RetryableError(err)
}
return nil
})
return response, err
}
func (client *AlibabacloudStackClient) getConnectClient(popcode ServiceCode) (*sdk.Client, error) {
var conn *sdk.Client
var exists bool
if conn, exists = client.Conns[popcode]; !exists {
c, err := client.WithProductSDKClient(popcode)
if err != nil {
return nil, err
}
client.Conns[popcode] = c
conn = c
}
return conn, nil
}
func (client *AlibabacloudStackClient) ProcessCommonRequest(request *requests.CommonRequest) (*responses.CommonResponse, error) {
popcode := ServiceCode(strings.ReplaceAll(strings.ToUpper(request.Product),"-","_"))
conn, err := client.getConnectClient(popcode)
if err != nil {
return nil, err
}
//request.Domain = conn.Domain
domain := request.Domain
if domain == "" {
domain = conn.Domain
}
if strings.HasPrefix(domain, "internal.asapi.") || strings.HasPrefix(domain, "public.asapi.") {
// asapi兼容逻辑
// # asapi 使用common SDK时不能拼接pathpattern,否则会报错
if request.PathPattern != "" {
var r []string = strings.SplitN(domain, "/", 2)
request.Domain = r[0]
request.PathPattern = "/asapi/v3"
}
if len(request.Content) > 0 {
request.QueryParams["x-acs-body"] = string(request.Content)
}
if popcode == OneRouterCode {
request.QueryParams["AccountInfo"] = "terraform-provider" //TODO: 3162 ~ 3180 onerouter必传,后续版本移除
}
request.Method = "POST"
if strings.HasPrefix(domain, "public.asapi.") {
// 如果public的asapi网关,强制使用https
request.SetScheme("https")
} else {
// 如果internal的asapi网关,强制使用http
request.SetScheme("http")
}
}
var response *responses.CommonResponse
wait := IncrementalWait(3*time.Second, 3*time.Second)
resource.Retry(5*time.Minute, func() *resource.RetryError {
//仅在请求无正常返回时重试
response, err = conn.ProcessCommonRequest(request)
if err == nil {
return nil
}
if response == nil {
wait()
return resource.RetryableError(err)
}
if errmsgs.IsExpectedErrors(err, []string{errmsgs.LogClientTimeout, "RequestTimeout"}) {
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
})
return response, err
}
func IncrementalWait(firstDuration time.Duration, increaseDuration time.Duration) func() {
retryCount := 1
return func() {
var waitTime time.Duration
if retryCount == 1 {
waitTime = firstDuration
} else if retryCount > 1 {
waitTime += increaseDuration
}
time.Sleep(waitTime)
retryCount++
}
}
func GetResourceData(d *schema.ResourceData, keys ...string) interface{} {
v, _ := GetResourceDataOk(d, keys...)
return v
}
func GetResourceDataOk(d *schema.ResourceData, keys ...string) (interface{}, bool) {
if d.IsNewResource() {
for _, key := range keys {
value, ok := d.GetOk(key)
if ok {
return value, true
}
}
} else {
for _, key := range keys {
if d.HasChange(key) {
return d.Get(key), true
}
}
}
return d.GetOk(keys[0])
}
func SetResourceData(d *schema.ResourceData, value interface{}, keys ...string) error {
for _, key := range keys {
if err := d.Set(key, value); err != nil {
return errmsgs.WrapError(err)
}
}
return nil
}
func retryDo(do func() (interface{}, error)) (interface{}, error) {
var response interface{}
var err error
wait := IncrementalWait(3*time.Second, 3*time.Second)
resource.Retry(5*time.Minute, func() *resource.RetryError {
//仅在请求无正常返回时重试
response, err = do()
if err == nil {
return nil
}
if response == nil {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
})
return response, err
}