providers/alicloud/connectivity/client.go (309 lines of code) (raw):

package connectivity import ( "fmt" "net/http" "net/url" "os" "regexp" "strconv" "strings" "sync" "time" "github.com/aliyun/alibaba-cloud-sdk-go/sdk" "github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints" "github.com/aliyun/alibaba-cloud-sdk-go/services/alidns" "github.com/aliyun/alibaba-cloud-sdk-go/services/ecs" "github.com/aliyun/alibaba-cloud-sdk-go/services/pvtz" "github.com/aliyun/alibaba-cloud-sdk-go/services/ram" "github.com/aliyun/alibaba-cloud-sdk-go/services/rds" "github.com/aliyun/alibaba-cloud-sdk-go/services/slb" "github.com/aliyun/alibaba-cloud-sdk-go/services/vpc" "github.com/aliyun/aliyun-tablestore-go-sdk/tablestore" "github.com/denverdino/aliyungo/cs" "github.com/hashicorp/terraform/terraform" ) // AliyunClient of aliyun type AliyunClient struct { Region Region RegionID string AccessKey string SecretKey string SecurityToken string OtsInstanceName string config *Config accountID string ecsconn *ecs.Client rdsconn *rds.Client vpcconn *vpc.Client slbconn *slb.Client dnsconn *alidns.Client ramconn *ram.Client pvtzconn *pvtz.Client tablestoreconnByInstanceName map[string]*tablestore.TableStoreClient csprojectconnByKey map[string]*cs.ProjectClient } type APIVersion string const DefaultClientRetryCountSmall = 5 const Terraform = "HashiCorp-Terraform" const Provider = "Terraform-Provider" const Module = "Terraform-Module" var goSdkMutex = sync.RWMutex{} // The Go SDK is not thread-safe // The main version number that is being run at the moment. var providerVersion = "1.57.1" var terraformVersion = strings.TrimSuffix(terraform.VersionString(), "-dev") //nolint // Client for AliyunClient func (c *Config) Client() (*AliyunClient, error) { // Get the auth and region. This can fail if keys/regions were not // specified and we're attempting to use the environment. if !c.SkipRegionValidation { err := c.loadAndValidate() if err != nil { return nil, err } } return &AliyunClient{ config: c, Region: c.Region, RegionID: c.RegionID, AccessKey: c.AccessKey, SecretKey: c.SecretKey, SecurityToken: c.SecurityToken, OtsInstanceName: c.OtsInstanceName, accountID: c.AccountID, tablestoreconnByInstanceName: make(map[string]*tablestore.TableStoreClient), csprojectconnByKey: make(map[string]*cs.ProjectClient), }, nil } func (client *AliyunClient) WithEcsClient(do func(*ecs.Client) (interface{}, error)) (interface{}, error) { goSdkMutex.Lock() defer goSdkMutex.Unlock() // Initialize the ECS client if necessary if client.ecsconn == nil { endpoint := client.config.EcsEndpoint if endpoint == "" { endpoint = loadEndpoint(client.config.RegionID, ECSCode) } if endpoint != "" { err := endpoints.AddEndpointMapping(client.config.RegionID, string(ECSCode), endpoint) if err != nil { return nil, err } } ecsconn, err := ecs.NewClientWithOptions(client.config.RegionID, client.getSdkConfig().WithTimeout(time.Duration(60)*time.Second), client.config.getAuthCredential()) if err != nil { return nil, fmt.Errorf("unable to initialize the ECS client: %#v", err) } if _, err := ecsconn.DescribeRegions(ecs.CreateDescribeRegionsRequest()); err != nil { return nil, err } ecsconn.AppendUserAgent(Terraform, terraformVersion) ecsconn.AppendUserAgent(Provider, providerVersion) if client.config.ConfigurationSource != "" { ecsconn.AppendUserAgent(Module, client.config.ConfigurationSource) } client.ecsconn = ecsconn } return do(client.ecsconn) } func (client *AliyunClient) WithRdsClient(do func(*rds.Client) (interface{}, error)) (interface{}, error) { goSdkMutex.Lock() defer goSdkMutex.Unlock() // Initialize the RDS client if necessary if client.rdsconn == nil { endpoint := client.config.RdsEndpoint if endpoint == "" { endpoint = loadEndpoint(client.config.RegionID, RDSCode) } if endpoint != "" { err := endpoints.AddEndpointMapping(client.config.RegionID, string(RDSCode), endpoint) if err != nil { return nil, err } } rdsconn, err := rds.NewClientWithOptions(client.config.RegionID, client.getSdkConfig(), client.config.getAuthCredential()) if err != nil { return nil, fmt.Errorf("unable to initialize the RDS client: %#v", err) } rdsconn.AppendUserAgent(Terraform, terraformVersion) rdsconn.AppendUserAgent(Provider, providerVersion) if client.config.ConfigurationSource != "" { rdsconn.AppendUserAgent(Module, client.config.ConfigurationSource) } client.rdsconn = rdsconn } return do(client.rdsconn) } func (client *AliyunClient) WithSlbClient(do func(*slb.Client) (interface{}, error)) (interface{}, error) { goSdkMutex.Lock() defer goSdkMutex.Unlock() // Initialize the SLB client if necessary if client.slbconn == nil { endpoint := client.config.SlbEndpoint if endpoint == "" { endpoint = loadEndpoint(client.config.RegionID, SLBCode) } if endpoint != "" { err := endpoints.AddEndpointMapping(client.config.RegionID, string(SLBCode), endpoint) if err != nil { return nil, err } } slbconn, err := slb.NewClientWithOptions(client.config.RegionID, client.getSdkConfig(), client.config.getAuthCredential()) if err != nil { return nil, fmt.Errorf("unable to initialize the SLB client: %#v", err) } slbconn.AppendUserAgent(Terraform, terraformVersion) slbconn.AppendUserAgent(Provider, providerVersion) if client.config.ConfigurationSource != "" { slbconn.AppendUserAgent(Module, client.config.ConfigurationSource) } client.slbconn = slbconn } return do(client.slbconn) } func (client *AliyunClient) WithVpcClient(do func(*vpc.Client) (interface{}, error)) (interface{}, error) { goSdkMutex.Lock() defer goSdkMutex.Unlock() // Initialize the VPC client if necessary if client.vpcconn == nil { endpoint := client.config.VpcEndpoint if endpoint == "" { endpoint = loadEndpoint(client.config.RegionID, VPCCode) } if endpoint != "" { err := endpoints.AddEndpointMapping(client.config.RegionID, string(VPCCode), endpoint) if err != nil { return nil, err } } vpcconn, err := vpc.NewClientWithOptions(client.config.RegionID, client.getSdkConfig(), client.config.getAuthCredential()) if err != nil { return nil, fmt.Errorf("unable to initialize the VPC client: %#v", err) } vpcconn.AppendUserAgent(Terraform, terraformVersion) vpcconn.AppendUserAgent(Provider, providerVersion) if client.config.ConfigurationSource != "" { vpcconn.AppendUserAgent(Module, client.config.ConfigurationSource) } client.vpcconn = vpcconn } return do(client.vpcconn) } func (client *AliyunClient) WithDNSClient(do func(*alidns.Client) (interface{}, error)) (interface{}, error) { goSdkMutex.Lock() defer goSdkMutex.Unlock() // Initialize the DNS client if necessary if client.dnsconn == nil { endpoint := client.config.DNSEndpoint if endpoint == "" { endpoint = loadEndpoint(client.config.RegionID, DNSCode) } if endpoint != "" { err := endpoints.AddEndpointMapping(client.config.RegionID, string(DNSCode), endpoint) if err != nil { return nil, err } } dnsconn, err := alidns.NewClientWithOptions(client.config.RegionID, client.getSdkConfig(), client.config.getAuthCredential()) if err != nil { return nil, fmt.Errorf("unable to initialize the DNS client: %#v", err) } dnsconn.AppendUserAgent(Terraform, terraformVersion) dnsconn.AppendUserAgent(Provider, providerVersion) if client.config.ConfigurationSource != "" { dnsconn.AppendUserAgent(Module, client.config.ConfigurationSource) } client.dnsconn = dnsconn } return do(client.dnsconn) } func (client *AliyunClient) WithRAMClient(do func(*ram.Client) (interface{}, error)) (interface{}, error) { goSdkMutex.Lock() defer goSdkMutex.Unlock() // Initialize the RAM client if necessary if client.ramconn == nil { endpoint := client.config.RAMEndpoint if endpoint == "" { endpoint = loadEndpoint(client.config.RegionID, RAMCode) } if strings.HasPrefix(endpoint, "http") { endpoint = fmt.Sprintf("https://%s", strings.TrimPrefix(endpoint, "http://")) } if endpoint != "" { err := endpoints.AddEndpointMapping(client.config.RegionID, string(RAMCode), endpoint) if err != nil { return nil, err } } ramconn, err := ram.NewClientWithOptions(client.config.RegionID, client.getSdkConfig(), client.config.getAuthCredential()) if err != nil { return nil, fmt.Errorf("unable to initialize the RAM client: %#v", err) } ramconn.AppendUserAgent(Terraform, terraformVersion) ramconn.AppendUserAgent(Provider, providerVersion) if client.config.ConfigurationSource != "" { ramconn.AppendUserAgent(Module, client.config.ConfigurationSource) } client.ramconn = ramconn } return do(client.ramconn) } func (client *AliyunClient) WithPvtzClient(do func(*pvtz.Client) (interface{}, error)) (interface{}, error) { goSdkMutex.Lock() defer goSdkMutex.Unlock() // Initialize the PVTZ client if necessary if client.pvtzconn == nil { endpoint := client.config.PvtzEndpoint if endpoint == "" { endpoint = loadEndpoint(client.config.RegionID, PVTZCode) } if endpoint != "" { err := endpoints.AddEndpointMapping(client.config.RegionID, string(PVTZCode), endpoint) if err != nil { return nil, err } } else { err := endpoints.AddEndpointMapping(client.config.RegionID, string(PVTZCode), "pvtz.aliyuncs.com") if err != nil { return nil, err } } pvtzconn, err := pvtz.NewClientWithOptions(client.config.RegionID, client.getSdkConfig(), client.config.getAuthCredential()) if err != nil { return nil, fmt.Errorf("unable to initialize the PVTZ client: %#v", err) } pvtzconn.AppendUserAgent(Terraform, terraformVersion) pvtzconn.AppendUserAgent(Provider, providerVersion) if client.config.ConfigurationSource != "" { pvtzconn.AppendUserAgent(Module, client.config.ConfigurationSource) } client.pvtzconn = pvtzconn } return do(client.pvtzconn) } func (client *AliyunClient) getSdkConfig() *sdk.Config { return sdk.NewConfig(). WithMaxRetryTime(DefaultClientRetryCountSmall). WithTimeout(time.Duration(30) * time.Second). WithGoRoutinePoolSize(10). WithDebug(false). WithHttpTransport(client.getTransport()). WithScheme("HTTPS") } func (client *AliyunClient) 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 // After building a new transport and it need to set http proxy to support proxy. proxyURL := client.getHTTPProxyURL() if proxyURL != nil { transport.Proxy = http.ProxyURL(proxyURL) } return transport } func (client *AliyunClient) 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 }