github.com/GoogleCloudPlatform/terraformer@v0.8.18/providers/alicloud/connectivity/client.go (about)

     1  package connectivity
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"net/url"
     7  	"os"
     8  	"regexp"
     9  	"strconv"
    10  	"strings"
    11  	"sync"
    12  	"time"
    13  
    14  	"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
    15  	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/endpoints"
    16  	"github.com/aliyun/alibaba-cloud-sdk-go/services/alidns"
    17  	"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
    18  	"github.com/aliyun/alibaba-cloud-sdk-go/services/pvtz"
    19  	"github.com/aliyun/alibaba-cloud-sdk-go/services/ram"
    20  	"github.com/aliyun/alibaba-cloud-sdk-go/services/rds"
    21  	"github.com/aliyun/alibaba-cloud-sdk-go/services/slb"
    22  	"github.com/aliyun/alibaba-cloud-sdk-go/services/vpc"
    23  	"github.com/aliyun/aliyun-tablestore-go-sdk/tablestore"
    24  	"github.com/denverdino/aliyungo/cs"
    25  	"github.com/hashicorp/terraform/terraform"
    26  )
    27  
    28  // AliyunClient of aliyun
    29  type AliyunClient struct {
    30  	Region                       Region
    31  	RegionID                     string
    32  	AccessKey                    string
    33  	SecretKey                    string
    34  	SecurityToken                string
    35  	OtsInstanceName              string
    36  	config                       *Config
    37  	accountID                    string
    38  	ecsconn                      *ecs.Client
    39  	rdsconn                      *rds.Client
    40  	vpcconn                      *vpc.Client
    41  	slbconn                      *slb.Client
    42  	dnsconn                      *alidns.Client
    43  	ramconn                      *ram.Client
    44  	pvtzconn                     *pvtz.Client
    45  	tablestoreconnByInstanceName map[string]*tablestore.TableStoreClient
    46  	csprojectconnByKey           map[string]*cs.ProjectClient
    47  }
    48  
    49  type APIVersion string
    50  
    51  const DefaultClientRetryCountSmall = 5
    52  const Terraform = "HashiCorp-Terraform"
    53  const Provider = "Terraform-Provider"
    54  const Module = "Terraform-Module"
    55  
    56  var goSdkMutex = sync.RWMutex{} // The Go SDK is not thread-safe
    57  // The main version number that is being run at the moment.
    58  var providerVersion = "1.57.1"
    59  var terraformVersion = strings.TrimSuffix(terraform.VersionString(), "-dev") //nolint
    60  
    61  // Client for AliyunClient
    62  func (c *Config) Client() (*AliyunClient, error) {
    63  	// Get the auth and region. This can fail if keys/regions were not
    64  	// specified and we're attempting to use the environment.
    65  	if !c.SkipRegionValidation {
    66  		err := c.loadAndValidate()
    67  		if err != nil {
    68  			return nil, err
    69  		}
    70  	}
    71  
    72  	return &AliyunClient{
    73  		config:                       c,
    74  		Region:                       c.Region,
    75  		RegionID:                     c.RegionID,
    76  		AccessKey:                    c.AccessKey,
    77  		SecretKey:                    c.SecretKey,
    78  		SecurityToken:                c.SecurityToken,
    79  		OtsInstanceName:              c.OtsInstanceName,
    80  		accountID:                    c.AccountID,
    81  		tablestoreconnByInstanceName: make(map[string]*tablestore.TableStoreClient),
    82  		csprojectconnByKey:           make(map[string]*cs.ProjectClient),
    83  	}, nil
    84  }
    85  
    86  func (client *AliyunClient) WithEcsClient(do func(*ecs.Client) (interface{}, error)) (interface{}, error) {
    87  	goSdkMutex.Lock()
    88  	defer goSdkMutex.Unlock()
    89  
    90  	// Initialize the ECS client if necessary
    91  	if client.ecsconn == nil {
    92  		endpoint := client.config.EcsEndpoint
    93  		if endpoint == "" {
    94  			endpoint = loadEndpoint(client.config.RegionID, ECSCode)
    95  		}
    96  
    97  		if endpoint != "" {
    98  			err := endpoints.AddEndpointMapping(client.config.RegionID, string(ECSCode), endpoint)
    99  			if err != nil {
   100  				return nil, err
   101  			}
   102  		}
   103  
   104  		ecsconn, err := ecs.NewClientWithOptions(client.config.RegionID, client.getSdkConfig().WithTimeout(time.Duration(60)*time.Second), client.config.getAuthCredential())
   105  
   106  		if err != nil {
   107  			return nil, fmt.Errorf("unable to initialize the ECS client: %#v", err)
   108  		}
   109  
   110  		if _, err := ecsconn.DescribeRegions(ecs.CreateDescribeRegionsRequest()); err != nil {
   111  			return nil, err
   112  		}
   113  		ecsconn.AppendUserAgent(Terraform, terraformVersion)
   114  		ecsconn.AppendUserAgent(Provider, providerVersion)
   115  		if client.config.ConfigurationSource != "" {
   116  			ecsconn.AppendUserAgent(Module, client.config.ConfigurationSource)
   117  		}
   118  		client.ecsconn = ecsconn
   119  	}
   120  
   121  	return do(client.ecsconn)
   122  }
   123  
   124  func (client *AliyunClient) WithRdsClient(do func(*rds.Client) (interface{}, error)) (interface{}, error) {
   125  	goSdkMutex.Lock()
   126  	defer goSdkMutex.Unlock()
   127  
   128  	// Initialize the RDS client if necessary
   129  	if client.rdsconn == nil {
   130  		endpoint := client.config.RdsEndpoint
   131  		if endpoint == "" {
   132  			endpoint = loadEndpoint(client.config.RegionID, RDSCode)
   133  		}
   134  		if endpoint != "" {
   135  			err := endpoints.AddEndpointMapping(client.config.RegionID, string(RDSCode), endpoint)
   136  			if err != nil {
   137  				return nil, err
   138  			}
   139  		}
   140  		rdsconn, err := rds.NewClientWithOptions(client.config.RegionID, client.getSdkConfig(), client.config.getAuthCredential())
   141  		if err != nil {
   142  			return nil, fmt.Errorf("unable to initialize the RDS client: %#v", err)
   143  		}
   144  
   145  		rdsconn.AppendUserAgent(Terraform, terraformVersion)
   146  		rdsconn.AppendUserAgent(Provider, providerVersion)
   147  		if client.config.ConfigurationSource != "" {
   148  			rdsconn.AppendUserAgent(Module, client.config.ConfigurationSource)
   149  		}
   150  		client.rdsconn = rdsconn
   151  	}
   152  
   153  	return do(client.rdsconn)
   154  }
   155  
   156  func (client *AliyunClient) WithSlbClient(do func(*slb.Client) (interface{}, error)) (interface{}, error) {
   157  	goSdkMutex.Lock()
   158  	defer goSdkMutex.Unlock()
   159  
   160  	// Initialize the SLB client if necessary
   161  	if client.slbconn == nil {
   162  		endpoint := client.config.SlbEndpoint
   163  		if endpoint == "" {
   164  			endpoint = loadEndpoint(client.config.RegionID, SLBCode)
   165  		}
   166  		if endpoint != "" {
   167  			err := endpoints.AddEndpointMapping(client.config.RegionID, string(SLBCode), endpoint)
   168  			if err != nil {
   169  				return nil, err
   170  			}
   171  		}
   172  		slbconn, err := slb.NewClientWithOptions(client.config.RegionID, client.getSdkConfig(), client.config.getAuthCredential())
   173  		if err != nil {
   174  			return nil, fmt.Errorf("unable to initialize the SLB client: %#v", err)
   175  		}
   176  
   177  		slbconn.AppendUserAgent(Terraform, terraformVersion)
   178  		slbconn.AppendUserAgent(Provider, providerVersion)
   179  		if client.config.ConfigurationSource != "" {
   180  			slbconn.AppendUserAgent(Module, client.config.ConfigurationSource)
   181  		}
   182  		client.slbconn = slbconn
   183  	}
   184  
   185  	return do(client.slbconn)
   186  }
   187  
   188  func (client *AliyunClient) WithVpcClient(do func(*vpc.Client) (interface{}, error)) (interface{}, error) {
   189  	goSdkMutex.Lock()
   190  	defer goSdkMutex.Unlock()
   191  
   192  	// Initialize the VPC client if necessary
   193  	if client.vpcconn == nil {
   194  		endpoint := client.config.VpcEndpoint
   195  		if endpoint == "" {
   196  			endpoint = loadEndpoint(client.config.RegionID, VPCCode)
   197  		}
   198  		if endpoint != "" {
   199  			err := endpoints.AddEndpointMapping(client.config.RegionID, string(VPCCode), endpoint)
   200  			if err != nil {
   201  				return nil, err
   202  			}
   203  		}
   204  		vpcconn, err := vpc.NewClientWithOptions(client.config.RegionID, client.getSdkConfig(), client.config.getAuthCredential())
   205  		if err != nil {
   206  			return nil, fmt.Errorf("unable to initialize the VPC client: %#v", err)
   207  		}
   208  
   209  		vpcconn.AppendUserAgent(Terraform, terraformVersion)
   210  		vpcconn.AppendUserAgent(Provider, providerVersion)
   211  		if client.config.ConfigurationSource != "" {
   212  			vpcconn.AppendUserAgent(Module, client.config.ConfigurationSource)
   213  		}
   214  		client.vpcconn = vpcconn
   215  	}
   216  
   217  	return do(client.vpcconn)
   218  }
   219  
   220  func (client *AliyunClient) WithDNSClient(do func(*alidns.Client) (interface{}, error)) (interface{}, error) {
   221  	goSdkMutex.Lock()
   222  	defer goSdkMutex.Unlock()
   223  
   224  	// Initialize the DNS client if necessary
   225  	if client.dnsconn == nil {
   226  		endpoint := client.config.DNSEndpoint
   227  		if endpoint == "" {
   228  			endpoint = loadEndpoint(client.config.RegionID, DNSCode)
   229  		}
   230  		if endpoint != "" {
   231  			err := endpoints.AddEndpointMapping(client.config.RegionID, string(DNSCode), endpoint)
   232  			if err != nil {
   233  				return nil, err
   234  			}
   235  		}
   236  
   237  		dnsconn, err := alidns.NewClientWithOptions(client.config.RegionID, client.getSdkConfig(), client.config.getAuthCredential())
   238  		if err != nil {
   239  			return nil, fmt.Errorf("unable to initialize the DNS client: %#v", err)
   240  		}
   241  		dnsconn.AppendUserAgent(Terraform, terraformVersion)
   242  		dnsconn.AppendUserAgent(Provider, providerVersion)
   243  		if client.config.ConfigurationSource != "" {
   244  			dnsconn.AppendUserAgent(Module, client.config.ConfigurationSource)
   245  		}
   246  		client.dnsconn = dnsconn
   247  	}
   248  
   249  	return do(client.dnsconn)
   250  }
   251  
   252  func (client *AliyunClient) WithRAMClient(do func(*ram.Client) (interface{}, error)) (interface{}, error) {
   253  	goSdkMutex.Lock()
   254  	defer goSdkMutex.Unlock()
   255  
   256  	// Initialize the RAM client if necessary
   257  	if client.ramconn == nil {
   258  		endpoint := client.config.RAMEndpoint
   259  		if endpoint == "" {
   260  			endpoint = loadEndpoint(client.config.RegionID, RAMCode)
   261  		}
   262  		if strings.HasPrefix(endpoint, "http") {
   263  			endpoint = fmt.Sprintf("https://%s", strings.TrimPrefix(endpoint, "http://"))
   264  		}
   265  		if endpoint != "" {
   266  			err := endpoints.AddEndpointMapping(client.config.RegionID, string(RAMCode), endpoint)
   267  			if err != nil {
   268  				return nil, err
   269  			}
   270  		}
   271  
   272  		ramconn, err := ram.NewClientWithOptions(client.config.RegionID, client.getSdkConfig(), client.config.getAuthCredential())
   273  		if err != nil {
   274  			return nil, fmt.Errorf("unable to initialize the RAM client: %#v", err)
   275  		}
   276  		ramconn.AppendUserAgent(Terraform, terraformVersion)
   277  		ramconn.AppendUserAgent(Provider, providerVersion)
   278  		if client.config.ConfigurationSource != "" {
   279  			ramconn.AppendUserAgent(Module, client.config.ConfigurationSource)
   280  		}
   281  		client.ramconn = ramconn
   282  	}
   283  
   284  	return do(client.ramconn)
   285  }
   286  
   287  func (client *AliyunClient) WithPvtzClient(do func(*pvtz.Client) (interface{}, error)) (interface{}, error) {
   288  	goSdkMutex.Lock()
   289  	defer goSdkMutex.Unlock()
   290  
   291  	// Initialize the PVTZ client if necessary
   292  	if client.pvtzconn == nil {
   293  		endpoint := client.config.PvtzEndpoint
   294  		if endpoint == "" {
   295  			endpoint = loadEndpoint(client.config.RegionID, PVTZCode)
   296  		}
   297  		if endpoint != "" {
   298  			err := endpoints.AddEndpointMapping(client.config.RegionID, string(PVTZCode), endpoint)
   299  			if err != nil {
   300  				return nil, err
   301  			}
   302  		} else {
   303  			err := endpoints.AddEndpointMapping(client.config.RegionID, string(PVTZCode), "pvtz.aliyuncs.com")
   304  			if err != nil {
   305  				return nil, err
   306  			}
   307  		}
   308  		pvtzconn, err := pvtz.NewClientWithOptions(client.config.RegionID, client.getSdkConfig(), client.config.getAuthCredential())
   309  		if err != nil {
   310  			return nil, fmt.Errorf("unable to initialize the PVTZ client: %#v", err)
   311  		}
   312  
   313  		pvtzconn.AppendUserAgent(Terraform, terraformVersion)
   314  		pvtzconn.AppendUserAgent(Provider, providerVersion)
   315  		if client.config.ConfigurationSource != "" {
   316  			pvtzconn.AppendUserAgent(Module, client.config.ConfigurationSource)
   317  		}
   318  		client.pvtzconn = pvtzconn
   319  	}
   320  
   321  	return do(client.pvtzconn)
   322  }
   323  
   324  func (client *AliyunClient) getSdkConfig() *sdk.Config {
   325  	return sdk.NewConfig().
   326  		WithMaxRetryTime(DefaultClientRetryCountSmall).
   327  		WithTimeout(time.Duration(30) * time.Second).
   328  		WithGoRoutinePoolSize(10).
   329  		WithDebug(false).
   330  		WithHttpTransport(client.getTransport()).
   331  		WithScheme("HTTPS")
   332  }
   333  
   334  func (client *AliyunClient) getTransport() *http.Transport {
   335  	handshakeTimeout, err := strconv.Atoi(os.Getenv("TLSHandshakeTimeout"))
   336  	if err != nil {
   337  		handshakeTimeout = 120
   338  	}
   339  	transport := &http.Transport{}
   340  	transport.TLSHandshakeTimeout = time.Duration(handshakeTimeout) * time.Second
   341  
   342  	// After building a new transport and it need to set http proxy to support proxy.
   343  	proxyURL := client.getHTTPProxyURL()
   344  	if proxyURL != nil {
   345  		transport.Proxy = http.ProxyURL(proxyURL)
   346  	}
   347  	return transport
   348  }
   349  
   350  func (client *AliyunClient) getHTTPProxyURL() *url.URL {
   351  	for _, v := range []string{"HTTPS_PROXY", "https_proxy", "HTTP_PROXY", "http_proxy"} {
   352  		value := strings.Trim(os.Getenv(v), " ")
   353  		if value != "" {
   354  			if !regexp.MustCompile(`^http(s)?://`).MatchString(value) {
   355  				value = fmt.Sprintf("https://%s", value)
   356  			}
   357  			proxyURL, err := url.Parse(value)
   358  			if err == nil {
   359  				return proxyURL
   360  			}
   361  			break
   362  		}
   363  	}
   364  	return nil
   365  }