provider alicloud:add new rds resource and some bugs fix (#12913)
* add new rds resource and some bugs fix * add docs * fix validator conflix fix validator conflix
This commit is contained in:
parent
4fe7ee16e6
commit
11768bcf5b
|
@ -2,6 +2,7 @@ package alicloud
|
|||
|
||||
import (
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
"github.com/denverdino/aliyungo/ecs"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
)
|
||||
|
||||
|
@ -12,8 +13,12 @@ const (
|
|||
VpcNet = InstanceNetWork("vpc")
|
||||
)
|
||||
|
||||
// timeout for common product, ecs e.g.
|
||||
const defaultTimeout = 120
|
||||
|
||||
// timeout for long time progerss product, rds e.g.
|
||||
const defaultLongTimeout = 800
|
||||
|
||||
func getRegion(d *schema.ResourceData, meta interface{}) common.Region {
|
||||
return meta.(*AliyunClient).Region
|
||||
}
|
||||
|
@ -50,3 +55,26 @@ func isProtocalValid(value string) bool {
|
|||
}
|
||||
return res
|
||||
}
|
||||
|
||||
var DefaultBusinessInfo = ecs.BusinessInfo{
|
||||
Pack: "terraform",
|
||||
}
|
||||
|
||||
// default region for all resource
|
||||
const DEFAULT_REGION = "cn-beijing"
|
||||
|
||||
// default security ip for db
|
||||
const DEFAULT_DB_SECURITY_IP = "127.0.0.1"
|
||||
|
||||
// we the count of create instance is only one
|
||||
const DEFAULT_INSTANCE_COUNT = 1
|
||||
|
||||
// symbol of multiIZ
|
||||
const MULTI_IZ_SYMBOL = "MAZ"
|
||||
|
||||
// default connect port of db
|
||||
const DB_DEFAULT_CONNECT_PORT = "3306"
|
||||
|
||||
const COMMA_SEPARATED = ","
|
||||
|
||||
const LOCAL_HOST_IP = "127.0.0.1"
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
"github.com/denverdino/aliyungo/ecs"
|
||||
"github.com/denverdino/aliyungo/rds"
|
||||
"github.com/denverdino/aliyungo/slb"
|
||||
)
|
||||
|
||||
|
@ -19,6 +20,9 @@ type Config struct {
|
|||
type AliyunClient struct {
|
||||
Region common.Region
|
||||
ecsconn *ecs.Client
|
||||
rdsconn *rds.Client
|
||||
// use new version
|
||||
ecsNewconn *ecs.Client
|
||||
vpcconn *ecs.Client
|
||||
slbconn *slb.Client
|
||||
}
|
||||
|
@ -35,6 +39,17 @@ func (c *Config) Client() (*AliyunClient, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
ecsNewconn, err := c.ecsConn()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ecsNewconn.SetVersion(EcsApiVersion20160314)
|
||||
|
||||
rdsconn, err := c.rdsConn()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
slbconn, err := c.slbConn()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -48,11 +63,15 @@ func (c *Config) Client() (*AliyunClient, error) {
|
|||
return &AliyunClient{
|
||||
Region: c.Region,
|
||||
ecsconn: ecsconn,
|
||||
ecsNewconn: ecsNewconn,
|
||||
vpcconn: vpcconn,
|
||||
slbconn: slbconn,
|
||||
rdsconn: rdsconn,
|
||||
}, nil
|
||||
}
|
||||
|
||||
const BusinessInfoKey = "Terraform"
|
||||
|
||||
func (c *Config) loadAndValidate() error {
|
||||
err := c.validateRegion()
|
||||
if err != nil {
|
||||
|
@ -74,7 +93,9 @@ func (c *Config) validateRegion() error {
|
|||
}
|
||||
|
||||
func (c *Config) ecsConn() (*ecs.Client, error) {
|
||||
client := ecs.NewClient(c.AccessKey, c.SecretKey)
|
||||
client := ecs.NewECSClient(c.AccessKey, c.SecretKey, c.Region)
|
||||
client.SetBusinessInfo(BusinessInfoKey)
|
||||
|
||||
_, err := client.DescribeRegions()
|
||||
|
||||
if err != nil {
|
||||
|
@ -84,20 +105,21 @@ func (c *Config) ecsConn() (*ecs.Client, error) {
|
|||
return client, nil
|
||||
}
|
||||
|
||||
func (c *Config) slbConn() (*slb.Client, error) {
|
||||
client := slb.NewClient(c.AccessKey, c.SecretKey)
|
||||
func (c *Config) rdsConn() (*rds.Client, error) {
|
||||
client := rds.NewRDSClient(c.AccessKey, c.SecretKey, c.Region)
|
||||
client.SetBusinessInfo(BusinessInfoKey)
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (c *Config) slbConn() (*slb.Client, error) {
|
||||
client := slb.NewSLBClient(c.AccessKey, c.SecretKey, c.Region)
|
||||
client.SetBusinessInfo(BusinessInfoKey)
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (c *Config) vpcConn() (*ecs.Client, error) {
|
||||
_, err := c.ecsConn()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := &ecs.Client{}
|
||||
client.Init("https://vpc.aliyuncs.com/", "2016-04-28", c.AccessKey, c.SecretKey)
|
||||
client := ecs.NewVPCClient(c.AccessKey, c.SecretKey, c.Region)
|
||||
client.SetBusinessInfo(BusinessInfoKey)
|
||||
return client, nil
|
||||
|
||||
}
|
||||
|
|
|
@ -5,10 +5,10 @@ import (
|
|||
"log"
|
||||
"regexp"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/denverdino/aliyungo/ecs"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"time"
|
||||
)
|
||||
|
||||
func dataSourceAlicloudImages() *schema.Resource {
|
||||
|
@ -175,15 +175,28 @@ func dataSourceAlicloudImagesRead(d *schema.ResourceData, meta interface{}) erro
|
|||
params.ImageOwnerAlias = ecs.ImageOwnerAlias(owners.(string))
|
||||
}
|
||||
|
||||
resp, _, err := conn.DescribeImages(params)
|
||||
var allImages []ecs.ImageType
|
||||
|
||||
for {
|
||||
images, paginationResult, err := conn.DescribeImages(params)
|
||||
if err != nil {
|
||||
return err
|
||||
break
|
||||
}
|
||||
|
||||
allImages = append(allImages, images...)
|
||||
|
||||
pagination := paginationResult.NextPage()
|
||||
if pagination == nil {
|
||||
break
|
||||
}
|
||||
|
||||
params.Pagination = *pagination
|
||||
}
|
||||
|
||||
var filteredImages []ecs.ImageType
|
||||
if nameRegexOk {
|
||||
r := regexp.MustCompile(nameRegex.(string))
|
||||
for _, image := range resp {
|
||||
for _, image := range allImages {
|
||||
// Check for a very rare case where the response would include no
|
||||
// image name. No name means nothing to attempt a match against,
|
||||
// therefore we are skipping such image.
|
||||
|
@ -198,7 +211,7 @@ func dataSourceAlicloudImagesRead(d *schema.ResourceData, meta interface{}) erro
|
|||
}
|
||||
}
|
||||
} else {
|
||||
filteredImages = resp[:]
|
||||
filteredImages = allImages[:]
|
||||
}
|
||||
|
||||
var images []ecs.ImageType
|
||||
|
|
|
@ -97,6 +97,22 @@ func TestAccAlicloudImagesDataSource_nameRegexFilter(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestAccAlicloudImagesDataSource_imageNotInFirstPage(t *testing.T) {
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccCheckAlicloudImagesDataSourceImageNotInFirstPageConfig,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAlicloudDataSourceID("data.alicloud_images.name_regex_filtered_image"),
|
||||
resource.TestMatchResourceAttr("data.alicloud_images.name_regex_filtered_image", "images.0.image_id", regexp.MustCompile("^ubuntu_14")),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Instance store test - using centos images
|
||||
const testAccCheckAlicloudImagesDataSourceImagesConfig = `
|
||||
data "alicloud_images" "multi_image" {
|
||||
|
@ -128,3 +144,12 @@ data "alicloud_images" "name_regex_filtered_image" {
|
|||
name_regex = "^centos_6\\w{1,5}[64]{1}.*"
|
||||
}
|
||||
`
|
||||
|
||||
// Testing image not in first page response
|
||||
const testAccCheckAlicloudImagesDataSourceImageNotInFirstPageConfig = `
|
||||
data "alicloud_images" "name_regex_filtered_image" {
|
||||
most_recent = true
|
||||
owners = "system"
|
||||
name_regex = "^ubuntu_14.*_64"
|
||||
}
|
||||
`
|
||||
|
|
|
@ -17,8 +17,6 @@ func TestAccAlicloudInstanceTypesDataSource_basic(t *testing.T) {
|
|||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAlicloudDataSourceID("data.alicloud_instance_types.4c8g"),
|
||||
|
||||
resource.TestCheckResourceAttr("data.alicloud_instance_types.4c8g", "instance_types.#", "4"),
|
||||
|
||||
resource.TestCheckResourceAttr("data.alicloud_instance_types.4c8g", "instance_types.0.cpu_core_count", "4"),
|
||||
resource.TestCheckResourceAttr("data.alicloud_instance_types.4c8g", "instance_types.0.memory_size", "8"),
|
||||
resource.TestCheckResourceAttr("data.alicloud_instance_types.4c8g", "instance_types.0.id", "ecs.s3.large"),
|
||||
|
|
|
@ -71,11 +71,6 @@ func TestAccAlicloudRegionsDataSource_empty(t *testing.T) {
|
|||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAlicloudDataSourceID("data.alicloud_regions.empty_params_region"),
|
||||
|
||||
resource.TestCheckResourceAttr("data.alicloud_regions.empty_params_region", "name", ""),
|
||||
resource.TestCheckResourceAttr("data.alicloud_regions.empty_params_region", "current", ""),
|
||||
|
||||
resource.TestCheckResourceAttr("data.alicloud_regions.empty_params_region", "regions.#", "13"),
|
||||
|
||||
resource.TestCheckResourceAttr("data.alicloud_regions.empty_params_region", "regions.0.id", "cn-shenzhen"),
|
||||
resource.TestCheckResourceAttr("data.alicloud_regions.empty_params_region", "regions.0.region_id", "cn-shenzhen"),
|
||||
resource.TestCheckResourceAttr("data.alicloud_regions.empty_params_region", "regions.0.local_name", "华南 1"),
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package alicloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -23,6 +26,7 @@ func TestAccAlicloudZonesDataSource_basic(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAccAlicloudZonesDataSource_filter(t *testing.T) {
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() {
|
||||
testAccPreCheck(t)
|
||||
|
@ -33,7 +37,7 @@ func TestAccAlicloudZonesDataSource_filter(t *testing.T) {
|
|||
Config: testAccCheckAlicloudZonesDataSourceFilter,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAlicloudDataSourceID("data.alicloud_zones.foo"),
|
||||
resource.TestCheckResourceAttr("data.alicloud_zones.foo", "zones.#", "2"),
|
||||
testCheckZoneLength("data.alicloud_zones.foo"),
|
||||
),
|
||||
},
|
||||
|
||||
|
@ -41,13 +45,59 @@ func TestAccAlicloudZonesDataSource_filter(t *testing.T) {
|
|||
Config: testAccCheckAlicloudZonesDataSourceFilterIoOptimized,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAlicloudDataSourceID("data.alicloud_zones.foo"),
|
||||
resource.TestCheckResourceAttr("data.alicloud_zones.foo", "zones.#", "1"),
|
||||
testCheckZoneLength("data.alicloud_zones.foo"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAlicloudZonesDataSource_unitRegion(t *testing.T) {
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() {
|
||||
testAccPreCheck(t)
|
||||
},
|
||||
Providers: testAccProviders,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccCheckAlicloudZonesDataSource_unitRegion,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAlicloudDataSourceID("data.alicloud_zones.foo"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// the zone length changed occasionally
|
||||
// check by range to avoid test case failure
|
||||
func testCheckZoneLength(name string) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
ms := s.RootModule()
|
||||
rs, ok := ms.Resources[name]
|
||||
if !ok {
|
||||
return fmt.Errorf("Not found: %s", name)
|
||||
}
|
||||
|
||||
is := rs.Primary
|
||||
if is == nil {
|
||||
return fmt.Errorf("No primary instance: %s", name)
|
||||
}
|
||||
|
||||
i, err := strconv.Atoi(is.Attributes["zones.#"])
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("convert zone length err: %#v", err)
|
||||
}
|
||||
|
||||
if i <= 0 {
|
||||
return fmt.Errorf("zone length expected greater than 0 got err: %d", i)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
const testAccCheckAlicloudZonesDataSourceBasicConfig = `
|
||||
data "alicloud_zones" "foo" {
|
||||
}
|
||||
|
@ -55,16 +105,28 @@ data "alicloud_zones" "foo" {
|
|||
|
||||
const testAccCheckAlicloudZonesDataSourceFilter = `
|
||||
data "alicloud_zones" "foo" {
|
||||
"available_instance_type"= "ecs.c2.xlarge"
|
||||
"available_resource_creation"= "VSwitch"
|
||||
"available_disk_category"= "cloud_efficiency"
|
||||
available_instance_type= "ecs.c2.xlarge"
|
||||
available_resource_creation= "VSwitch"
|
||||
available_disk_category= "cloud_efficiency"
|
||||
}
|
||||
`
|
||||
|
||||
const testAccCheckAlicloudZonesDataSourceFilterIoOptimized = `
|
||||
data "alicloud_zones" "foo" {
|
||||
"available_instance_type"= "ecs.c2.xlarge"
|
||||
"available_resource_creation"= "IoOptimized"
|
||||
"available_disk_category"= "cloud"
|
||||
available_instance_type= "ecs.c2.xlarge"
|
||||
available_resource_creation= "IoOptimized"
|
||||
available_disk_category= "cloud"
|
||||
}
|
||||
`
|
||||
|
||||
const testAccCheckAlicloudZonesDataSource_unitRegion = `
|
||||
provider "alicloud" {
|
||||
alias = "northeast"
|
||||
region = "ap-northeast-1"
|
||||
}
|
||||
|
||||
data "alicloud_zones" "foo" {
|
||||
provider = "alicloud.northeast"
|
||||
available_resource_creation= "VSwitch"
|
||||
}
|
||||
`
|
||||
|
|
|
@ -9,6 +9,7 @@ const (
|
|||
DiskIncorrectStatus = "IncorrectDiskStatus"
|
||||
DiskCreatingSnapshot = "DiskCreatingSnapshot"
|
||||
InstanceLockedForSecurity = "InstanceLockedForSecurity"
|
||||
SystemDiskNotFound = "SystemDiskNotFound"
|
||||
// eip
|
||||
EipIncorrectStatus = "IncorrectEipStatus"
|
||||
InstanceIncorrectStatus = "IncorrectInstanceStatus"
|
||||
|
|
|
@ -30,3 +30,8 @@ const (
|
|||
GroupRulePolicyAccept = GroupRulePolicy("accept")
|
||||
GroupRulePolicyDrop = GroupRulePolicy("drop")
|
||||
)
|
||||
|
||||
const (
|
||||
EcsApiVersion20160314 = "2016-03-14"
|
||||
EcsApiVersion20140526 = "2014-05-26"
|
||||
)
|
||||
|
|
|
@ -8,13 +8,41 @@ import (
|
|||
)
|
||||
|
||||
type Listener struct {
|
||||
slb.HTTPListenerType
|
||||
|
||||
InstancePort int
|
||||
LoadBalancerPort int
|
||||
Protocol string
|
||||
//tcp & udp
|
||||
PersistenceTimeout int
|
||||
|
||||
//https
|
||||
SSLCertificateId string
|
||||
Bandwidth int
|
||||
|
||||
//tcp
|
||||
HealthCheckType slb.HealthCheckType
|
||||
|
||||
//api interface: http & https is HealthCheckTimeout, tcp & udp is HealthCheckConnectTimeout
|
||||
HealthCheckConnectTimeout int
|
||||
}
|
||||
|
||||
type ListenerErr struct {
|
||||
ErrType string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *ListenerErr) Error() string {
|
||||
return e.ErrType + " " + e.Err.Error()
|
||||
|
||||
}
|
||||
|
||||
const (
|
||||
HealthCheckErrType = "healthCheckErrType"
|
||||
StickySessionErrType = "stickySessionErrType"
|
||||
CookieTimeOutErrType = "cookieTimeoutErrType"
|
||||
CookieErrType = "cookieErrType"
|
||||
)
|
||||
|
||||
// Takes the result of flatmap.Expand for an array of listeners and
|
||||
// returns ELB API compatible objects
|
||||
func expandListeners(configured []interface{}) ([]*Listener, error) {
|
||||
|
@ -31,13 +59,78 @@ func expandListeners(configured []interface{}) ([]*Listener, error) {
|
|||
InstancePort: ip,
|
||||
LoadBalancerPort: lp,
|
||||
Protocol: data["lb_protocol"].(string),
|
||||
Bandwidth: data["bandwidth"].(int),
|
||||
}
|
||||
|
||||
l.Bandwidth = data["bandwidth"].(int)
|
||||
|
||||
if v, ok := data["scheduler"]; ok {
|
||||
l.Scheduler = slb.SchedulerType(v.(string))
|
||||
}
|
||||
|
||||
if v, ok := data["ssl_certificate_id"]; ok {
|
||||
l.SSLCertificateId = v.(string)
|
||||
}
|
||||
|
||||
if v, ok := data["sticky_session"]; ok {
|
||||
l.StickySession = slb.FlagType(v.(string))
|
||||
}
|
||||
|
||||
if v, ok := data["sticky_session_type"]; ok {
|
||||
l.StickySessionType = slb.StickySessionType(v.(string))
|
||||
}
|
||||
|
||||
if v, ok := data["cookie_timeout"]; ok {
|
||||
l.CookieTimeout = v.(int)
|
||||
}
|
||||
|
||||
if v, ok := data["cookie"]; ok {
|
||||
l.Cookie = v.(string)
|
||||
}
|
||||
|
||||
if v, ok := data["persistence_timeout"]; ok {
|
||||
l.PersistenceTimeout = v.(int)
|
||||
}
|
||||
|
||||
if v, ok := data["health_check"]; ok {
|
||||
l.HealthCheck = slb.FlagType(v.(string))
|
||||
}
|
||||
|
||||
if v, ok := data["health_check_type"]; ok {
|
||||
l.HealthCheckType = slb.HealthCheckType(v.(string))
|
||||
}
|
||||
|
||||
if v, ok := data["health_check_domain"]; ok {
|
||||
l.HealthCheckDomain = v.(string)
|
||||
}
|
||||
|
||||
if v, ok := data["health_check_uri"]; ok {
|
||||
l.HealthCheckURI = v.(string)
|
||||
}
|
||||
|
||||
if v, ok := data["health_check_connect_port"]; ok {
|
||||
l.HealthCheckConnectPort = v.(int)
|
||||
}
|
||||
|
||||
if v, ok := data["healthy_threshold"]; ok {
|
||||
l.HealthyThreshold = v.(int)
|
||||
}
|
||||
|
||||
if v, ok := data["unhealthy_threshold"]; ok {
|
||||
l.UnhealthyThreshold = v.(int)
|
||||
}
|
||||
|
||||
if v, ok := data["health_check_timeout"]; ok {
|
||||
l.HealthCheckTimeout = v.(int)
|
||||
}
|
||||
|
||||
if v, ok := data["health_check_interval"]; ok {
|
||||
l.HealthCheckInterval = v.(int)
|
||||
}
|
||||
|
||||
if v, ok := data["health_check_http_code"]; ok {
|
||||
l.HealthCheckHttpCode = slb.HealthCheckHttpCodeType(v.(string))
|
||||
}
|
||||
|
||||
var valid bool
|
||||
if l.SSLCertificateId != "" {
|
||||
// validate the protocol is correct
|
||||
|
|
|
@ -26,7 +26,7 @@ func Provider() terraform.ResourceProvider {
|
|||
"region": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_REGION", "cn-beijing"),
|
||||
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_REGION", DEFAULT_REGION),
|
||||
Description: descriptions["region"],
|
||||
},
|
||||
},
|
||||
|
@ -43,6 +43,7 @@ func Provider() terraform.ResourceProvider {
|
|||
"alicloud_disk_attachment": resourceAliyunDiskAttachment(),
|
||||
"alicloud_security_group": resourceAliyunSecurityGroup(),
|
||||
"alicloud_security_group_rule": resourceAliyunSecurityGroupRule(),
|
||||
"alicloud_db_instance": resourceAlicloudDBInstance(),
|
||||
"alicloud_vpc": resourceAliyunVpc(),
|
||||
"alicloud_nat_gateway": resourceAliyunNatGateway(),
|
||||
//both subnet and vswith exists,cause compatible old version, and compatible aws habit.
|
||||
|
|
|
@ -0,0 +1,545 @@
|
|||
package alicloud
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
"github.com/denverdino/aliyungo/rds"
|
||||
"github.com/hashicorp/terraform/helper/hashcode"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func resourceAlicloudDBInstance() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceAlicloudDBInstanceCreate,
|
||||
Read: resourceAlicloudDBInstanceRead,
|
||||
Update: resourceAlicloudDBInstanceUpdate,
|
||||
Delete: resourceAlicloudDBInstanceDelete,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"engine": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
ValidateFunc: validateAllowedStringValue([]string{"MySQL", "SQLServer", "PostgreSQL", "PPAS"}),
|
||||
ForceNew: true,
|
||||
Required: true,
|
||||
},
|
||||
"engine_version": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
ValidateFunc: validateAllowedStringValue([]string{"5.5", "5.6", "5.7", "2008r2", "2012", "9.4", "9.3"}),
|
||||
ForceNew: true,
|
||||
Required: true,
|
||||
},
|
||||
"db_instance_class": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"db_instance_storage": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
|
||||
"instance_charge_type": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
ValidateFunc: validateAllowedStringValue([]string{string(rds.Postpaid), string(rds.Prepaid)}),
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Default: rds.Postpaid,
|
||||
},
|
||||
"period": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
ValidateFunc: validateAllowedIntValue([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 24, 36}),
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Default: 1,
|
||||
},
|
||||
|
||||
"zone_id": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"multi_az": &schema.Schema{
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
"db_instance_net_type": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
ValidateFunc: validateAllowedStringValue([]string{string(common.Internet), string(common.Intranet)}),
|
||||
Optional: true,
|
||||
},
|
||||
"allocate_public_connection": &schema.Schema{
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Default: false,
|
||||
},
|
||||
|
||||
"instance_network_type": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
ValidateFunc: validateAllowedStringValue([]string{string(common.VPC), string(common.Classic)}),
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"vswitch_id": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
ForceNew: true,
|
||||
Optional: true,
|
||||
},
|
||||
|
||||
"master_user_name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
ForceNew: true,
|
||||
Optional: true,
|
||||
},
|
||||
"master_user_password": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
ForceNew: true,
|
||||
Optional: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
|
||||
"preferred_backup_period": &schema.Schema{
|
||||
Type: schema.TypeList,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
// terraform does not support ValidateFunc of TypeList attr
|
||||
// ValidateFunc: validateAllowedStringValue([]string{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}),
|
||||
Optional: true,
|
||||
},
|
||||
"preferred_backup_time": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
ValidateFunc: validateAllowedStringValue(rds.BACKUP_TIME),
|
||||
Optional: true,
|
||||
},
|
||||
"backup_retention_period": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
ValidateFunc: validateIntegerInRange(7, 730),
|
||||
Optional: true,
|
||||
},
|
||||
|
||||
"security_ips": &schema.Schema{
|
||||
Type: schema.TypeList,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
Computed: true,
|
||||
Optional: true,
|
||||
},
|
||||
|
||||
"port": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"connections": &schema.Schema{
|
||||
Type: schema.TypeList,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"connection_string": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"ip_type": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"ip_address": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"db_mappings": &schema.Schema{
|
||||
Type: schema.TypeSet,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"db_name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"character_set_name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
ValidateFunc: validateAllowedStringValue(rds.CHARACTER_SET_NAME),
|
||||
Required: true,
|
||||
},
|
||||
"db_description": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Optional: true,
|
||||
Set: resourceAlicloudDatabaseHash,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceAlicloudDatabaseHash(v interface{}) int {
|
||||
var buf bytes.Buffer
|
||||
m := v.(map[string]interface{})
|
||||
buf.WriteString(fmt.Sprintf("%s-", m["db_name"].(string)))
|
||||
buf.WriteString(fmt.Sprintf("%s-", m["character_set_name"].(string)))
|
||||
buf.WriteString(fmt.Sprintf("%s-", m["db_description"].(string)))
|
||||
|
||||
return hashcode.String(buf.String())
|
||||
}
|
||||
|
||||
func resourceAlicloudDBInstanceCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
client := meta.(*AliyunClient)
|
||||
conn := client.rdsconn
|
||||
|
||||
args, err := buildDBCreateOrderArgs(d, meta)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := conn.CreateOrder(args)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating Alicloud db instance: %#v", err)
|
||||
}
|
||||
|
||||
instanceId := resp.DBInstanceId
|
||||
if instanceId == "" {
|
||||
return fmt.Errorf("Error get Alicloud db instance id")
|
||||
}
|
||||
|
||||
d.SetId(instanceId)
|
||||
d.Set("instance_charge_type", d.Get("instance_charge_type"))
|
||||
d.Set("period", d.Get("period"))
|
||||
d.Set("period_type", d.Get("period_type"))
|
||||
|
||||
// wait instance status change from Creating to running
|
||||
if err := conn.WaitForInstance(d.Id(), rds.Running, defaultLongTimeout); err != nil {
|
||||
log.Printf("[DEBUG] WaitForInstance %s got error: %#v", rds.Running, err)
|
||||
}
|
||||
|
||||
if err := modifySecurityIps(d.Id(), d.Get("security_ips"), meta); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
masterUserName := d.Get("master_user_name").(string)
|
||||
masterUserPwd := d.Get("master_user_password").(string)
|
||||
if masterUserName != "" && masterUserPwd != "" {
|
||||
if err := client.CreateAccountByInfo(d.Id(), masterUserName, masterUserPwd); err != nil {
|
||||
return fmt.Errorf("Create db account %s error: %v", masterUserName, err)
|
||||
}
|
||||
}
|
||||
|
||||
if d.Get("allocate_public_connection").(bool) {
|
||||
if err := client.AllocateDBPublicConnection(d.Id(), DB_DEFAULT_CONNECT_PORT); err != nil {
|
||||
return fmt.Errorf("Allocate public connection error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return resourceAlicloudDBInstanceUpdate(d, meta)
|
||||
}
|
||||
|
||||
func modifySecurityIps(id string, ips interface{}, meta interface{}) error {
|
||||
client := meta.(*AliyunClient)
|
||||
ipList := expandStringList(ips.([]interface{}))
|
||||
|
||||
ipstr := strings.Join(ipList[:], COMMA_SEPARATED)
|
||||
// default disable connect from outside
|
||||
if ipstr == "" {
|
||||
ipstr = LOCAL_HOST_IP
|
||||
}
|
||||
|
||||
if err := client.ModifyDBSecurityIps(id, ipstr); err != nil {
|
||||
return fmt.Errorf("Error modify security ips %s: %#v", ipstr, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceAlicloudDBInstanceUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||
client := meta.(*AliyunClient)
|
||||
conn := client.rdsconn
|
||||
d.Partial(true)
|
||||
|
||||
if d.HasChange("db_mappings") {
|
||||
o, n := d.GetChange("db_mappings")
|
||||
os := o.(*schema.Set)
|
||||
ns := n.(*schema.Set)
|
||||
|
||||
var allDbs []string
|
||||
remove := os.Difference(ns).List()
|
||||
add := ns.Difference(os).List()
|
||||
|
||||
if len(remove) > 0 && len(add) > 0 {
|
||||
return fmt.Errorf("Failure modify database, we neither support create and delete database simultaneous nor modify database attributes.")
|
||||
}
|
||||
|
||||
if len(remove) > 0 {
|
||||
for _, db := range remove {
|
||||
dbm, _ := db.(map[string]interface{})
|
||||
if err := conn.DeleteDatabase(d.Id(), dbm["db_name"].(string)); err != nil {
|
||||
return fmt.Errorf("Failure delete database %s: %#v", dbm["db_name"].(string), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(add) > 0 {
|
||||
for _, db := range add {
|
||||
dbm, _ := db.(map[string]interface{})
|
||||
dbName := dbm["db_name"].(string)
|
||||
allDbs = append(allDbs, dbName)
|
||||
|
||||
if err := client.CreateDatabaseByInfo(d.Id(), dbName, dbm["character_set_name"].(string), dbm["db_description"].(string)); err != nil {
|
||||
return fmt.Errorf("Failure create database %s: %#v", dbName, err)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if err := conn.WaitForAllDatabase(d.Id(), allDbs, rds.Running, 600); err != nil {
|
||||
return fmt.Errorf("Failure create database %#v", err)
|
||||
}
|
||||
|
||||
if user := d.Get("master_user_name").(string); user != "" {
|
||||
for _, dbName := range allDbs {
|
||||
if err := client.GrantDBPrivilege2Account(d.Id(), user, dbName); err != nil {
|
||||
return fmt.Errorf("Failed to grant database %s readwrite privilege to account %s: %#v", dbName, user, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d.SetPartial("db_mappings")
|
||||
}
|
||||
|
||||
if d.HasChange("preferred_backup_period") || d.HasChange("preferred_backup_time") || d.HasChange("backup_retention_period") {
|
||||
period := d.Get("preferred_backup_period").([]interface{})
|
||||
periodList := expandStringList(period)
|
||||
time := d.Get("preferred_backup_time").(string)
|
||||
retention := d.Get("backup_retention_period").(int)
|
||||
|
||||
if time == "" || retention == 0 || len(periodList) < 1 {
|
||||
return fmt.Errorf("Both backup_time, backup_period and retention_period are required to set backup policy.")
|
||||
}
|
||||
|
||||
ps := strings.Join(periodList[:], COMMA_SEPARATED)
|
||||
|
||||
if err := client.ConfigDBBackup(d.Id(), time, ps, retention); err != nil {
|
||||
return fmt.Errorf("Error set backup policy: %#v", err)
|
||||
}
|
||||
d.SetPartial("preferred_backup_period")
|
||||
d.SetPartial("preferred_backup_time")
|
||||
d.SetPartial("backup_retention_period")
|
||||
}
|
||||
|
||||
if d.HasChange("security_ips") {
|
||||
if err := modifySecurityIps(d.Id(), d.Get("security_ips"), meta); err != nil {
|
||||
return err
|
||||
}
|
||||
d.SetPartial("security_ips")
|
||||
}
|
||||
|
||||
if d.HasChange("db_instance_class") || d.HasChange("db_instance_storage") {
|
||||
co, cn := d.GetChange("db_instance_class")
|
||||
so, sn := d.GetChange("db_instance_storage")
|
||||
classOld := co.(string)
|
||||
classNew := cn.(string)
|
||||
storageOld := so.(int)
|
||||
storageNew := sn.(int)
|
||||
|
||||
// update except the first time, because we will do it in create function
|
||||
if classOld != "" && storageOld != 0 {
|
||||
chargeType := d.Get("instance_charge_type").(string)
|
||||
if chargeType == string(rds.Prepaid) {
|
||||
return fmt.Errorf("Prepaid db instance does not support modify db_instance_class or db_instance_storage")
|
||||
}
|
||||
|
||||
if err := client.ModifyDBClassStorage(d.Id(), classNew, strconv.Itoa(storageNew)); err != nil {
|
||||
return fmt.Errorf("Error modify db instance class or storage error: %#v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d.Partial(false)
|
||||
return resourceAlicloudDBInstanceRead(d, meta)
|
||||
}
|
||||
|
||||
func resourceAlicloudDBInstanceRead(d *schema.ResourceData, meta interface{}) error {
|
||||
client := meta.(*AliyunClient)
|
||||
conn := client.rdsconn
|
||||
|
||||
instance, err := client.DescribeDBInstanceById(d.Id())
|
||||
if err != nil {
|
||||
if notFoundError(err) {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Error Describe DB InstanceAttribute: %#v", err)
|
||||
}
|
||||
|
||||
args := rds.DescribeDatabasesArgs{
|
||||
DBInstanceId: d.Id(),
|
||||
}
|
||||
|
||||
resp, err := conn.DescribeDatabases(&args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.Set("db_mappings", flattenDatabaseMappings(resp.Databases.Database))
|
||||
|
||||
argn := rds.DescribeDBInstanceNetInfoArgs{
|
||||
DBInstanceId: d.Id(),
|
||||
}
|
||||
|
||||
resn, err := conn.DescribeDBInstanceNetInfo(&argn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.Set("connections", flattenDBConnections(resn.DBInstanceNetInfos.DBInstanceNetInfo))
|
||||
|
||||
ips, err := client.GetSecurityIps(d.Id())
|
||||
if err != nil {
|
||||
log.Printf("Describe DB security ips error: %#v", err)
|
||||
}
|
||||
d.Set("security_ips", ips)
|
||||
|
||||
d.Set("engine", instance.Engine)
|
||||
d.Set("engine_version", instance.EngineVersion)
|
||||
d.Set("db_instance_class", instance.DBInstanceClass)
|
||||
d.Set("port", instance.Port)
|
||||
d.Set("db_instance_storage", instance.DBInstanceStorage)
|
||||
d.Set("zone_id", instance.ZoneId)
|
||||
d.Set("db_instance_net_type", instance.DBInstanceNetType)
|
||||
d.Set("instance_network_type", instance.InstanceNetworkType)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceAlicloudDBInstanceDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AliyunClient).rdsconn
|
||||
|
||||
return resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
err := conn.DeleteInstance(d.Id())
|
||||
|
||||
if err != nil {
|
||||
return resource.RetryableError(fmt.Errorf("DB Instance in use - trying again while it is deleted."))
|
||||
}
|
||||
|
||||
args := &rds.DescribeDBInstancesArgs{
|
||||
DBInstanceId: d.Id(),
|
||||
}
|
||||
resp, err := conn.DescribeDBInstanceAttribute(args)
|
||||
if err != nil {
|
||||
return resource.NonRetryableError(err)
|
||||
} else if len(resp.Items.DBInstanceAttribute) < 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return resource.RetryableError(fmt.Errorf("DB in use - trying again while it is deleted."))
|
||||
})
|
||||
}
|
||||
|
||||
func buildDBCreateOrderArgs(d *schema.ResourceData, meta interface{}) (*rds.CreateOrderArgs, error) {
|
||||
client := meta.(*AliyunClient)
|
||||
args := &rds.CreateOrderArgs{
|
||||
RegionId: getRegion(d, meta),
|
||||
// we does not expose this param to user,
|
||||
// because create prepaid instance progress will be stopped when set auto_pay to false,
|
||||
// then could not get instance info, cause timeout error
|
||||
AutoPay: "true",
|
||||
EngineVersion: d.Get("engine_version").(string),
|
||||
Engine: rds.Engine(d.Get("engine").(string)),
|
||||
DBInstanceStorage: d.Get("db_instance_storage").(int),
|
||||
DBInstanceClass: d.Get("db_instance_class").(string),
|
||||
Quantity: DEFAULT_INSTANCE_COUNT,
|
||||
Resource: rds.DefaultResource,
|
||||
}
|
||||
|
||||
bussStr, err := json.Marshal(DefaultBusinessInfo)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to translate bussiness info %#v from json to string", DefaultBusinessInfo)
|
||||
}
|
||||
|
||||
args.BusinessInfo = string(bussStr)
|
||||
|
||||
zoneId := d.Get("zone_id").(string)
|
||||
args.ZoneId = zoneId
|
||||
|
||||
multiAZ := d.Get("multi_az").(bool)
|
||||
if multiAZ {
|
||||
if zoneId != "" {
|
||||
return nil, fmt.Errorf("You cannot set the ZoneId parameter when the MultiAZ parameter is set to true")
|
||||
}
|
||||
izs, err := client.DescribeMultiIZByRegion()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Get multiAZ id error")
|
||||
}
|
||||
|
||||
if len(izs) < 1 {
|
||||
return nil, fmt.Errorf("Current region does not support MultiAZ.")
|
||||
}
|
||||
|
||||
args.ZoneId = izs[0]
|
||||
}
|
||||
|
||||
vswitchId := d.Get("vswitch_id").(string)
|
||||
|
||||
networkType := d.Get("instance_network_type").(string)
|
||||
args.InstanceNetworkType = common.NetworkType(networkType)
|
||||
|
||||
if vswitchId != "" {
|
||||
args.VSwitchId = vswitchId
|
||||
|
||||
// check InstanceNetworkType with vswitchId
|
||||
if networkType == string(common.Classic) {
|
||||
return nil, fmt.Errorf("When fill vswitchId, you shold set instance_network_type to VPC")
|
||||
} else if networkType == "" {
|
||||
args.InstanceNetworkType = common.VPC
|
||||
}
|
||||
|
||||
// get vpcId
|
||||
vpcId, err := client.GetVpcIdByVSwitchId(vswitchId)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("VswitchId %s is not valid of current region", vswitchId)
|
||||
}
|
||||
// fill vpcId by vswitchId
|
||||
args.VPCId = vpcId
|
||||
|
||||
// check vswitchId in zone
|
||||
vsw, err := client.QueryVswitchById(vpcId, vswitchId)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("VswitchId %s is not valid of current region", vswitchId)
|
||||
}
|
||||
|
||||
if zoneId == "" {
|
||||
args.ZoneId = vsw.ZoneId
|
||||
} else if vsw.ZoneId != zoneId {
|
||||
return nil, fmt.Errorf("VswitchId %s is not belong to the zone %s", vswitchId, zoneId)
|
||||
}
|
||||
}
|
||||
|
||||
if v := d.Get("db_instance_net_type").(string); v != "" {
|
||||
args.DBInstanceNetType = common.NetType(v)
|
||||
}
|
||||
|
||||
chargeType := d.Get("instance_charge_type").(string)
|
||||
if chargeType != "" {
|
||||
args.PayType = rds.DBPayType(chargeType)
|
||||
} else {
|
||||
args.PayType = rds.Postpaid
|
||||
}
|
||||
|
||||
// if charge type is postpaid, the commodity code must set to bards
|
||||
if chargeType == string(rds.Postpaid) {
|
||||
args.CommodityCode = rds.Bards
|
||||
} else {
|
||||
args.CommodityCode = rds.Rds
|
||||
}
|
||||
|
||||
period := d.Get("period").(int)
|
||||
args.UsedTime, args.TimeType = TransformPeriod2Time(period, chargeType)
|
||||
|
||||
return args, nil
|
||||
}
|
|
@ -0,0 +1,765 @@
|
|||
package alicloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
"github.com/denverdino/aliyungo/rds"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
"log"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAccAlicloudDBInstance_basic(t *testing.T) {
|
||||
var instance rds.DBInstanceAttribute
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() {
|
||||
testAccPreCheck(t)
|
||||
},
|
||||
|
||||
// module name
|
||||
IDRefreshName: "alicloud_db_instance.foo",
|
||||
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckDBInstanceDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccDBInstanceConfig,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckDBInstanceExists(
|
||||
"alicloud_db_instance.foo", &instance),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_db_instance.foo",
|
||||
"port",
|
||||
"3306"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_db_instance.foo",
|
||||
"db_instance_storage",
|
||||
"10"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_db_instance.foo",
|
||||
"instance_network_type",
|
||||
"Classic"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_db_instance.foo",
|
||||
"db_instance_net_type",
|
||||
"Intranet"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_db_instance.foo",
|
||||
"engine_version",
|
||||
"5.6"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_db_instance.foo",
|
||||
"engine",
|
||||
"MySQL"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestAccAlicloudDBInstance_vpc(t *testing.T) {
|
||||
var instance rds.DBInstanceAttribute
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() {
|
||||
testAccPreCheck(t)
|
||||
},
|
||||
|
||||
// module name
|
||||
IDRefreshName: "alicloud_db_instance.foo",
|
||||
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckDBInstanceDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccDBInstance_vpc,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckDBInstanceExists(
|
||||
"alicloud_db_instance.foo", &instance),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_db_instance.foo",
|
||||
"port",
|
||||
"3306"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_db_instance.foo",
|
||||
"db_instance_storage",
|
||||
"10"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_db_instance.foo",
|
||||
"instance_network_type",
|
||||
"VPC"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_db_instance.foo",
|
||||
"db_instance_net_type",
|
||||
"Intranet"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_db_instance.foo",
|
||||
"engine_version",
|
||||
"5.6"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_db_instance.foo",
|
||||
"engine",
|
||||
"MySQL"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestC2CAlicloudDBInstance_prepaid_order(t *testing.T) {
|
||||
var instance rds.DBInstanceAttribute
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() {
|
||||
testAccPreCheck(t)
|
||||
},
|
||||
|
||||
// module name
|
||||
IDRefreshName: "alicloud_db_instance.foo",
|
||||
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckDBInstanceDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccDBInstance_prepaid_order,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckDBInstanceExists(
|
||||
"alicloud_db_instance.foo", &instance),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_db_instance.foo",
|
||||
"port",
|
||||
"3306"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_db_instance.foo",
|
||||
"db_instance_storage",
|
||||
"10"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_db_instance.foo",
|
||||
"instance_network_type",
|
||||
"VPC"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_db_instance.foo",
|
||||
"db_instance_net_type",
|
||||
"Intranet"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_db_instance.foo",
|
||||
"engine_version",
|
||||
"5.6"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_db_instance.foo",
|
||||
"engine",
|
||||
"MySQL"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestAccAlicloudDBInstance_multiIZ(t *testing.T) {
|
||||
var instance rds.DBInstanceAttribute
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() {
|
||||
testAccPreCheck(t)
|
||||
},
|
||||
|
||||
// module name
|
||||
IDRefreshName: "alicloud_db_instance.foo",
|
||||
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckDBInstanceDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccDBInstance_multiIZ,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckDBInstanceExists(
|
||||
"alicloud_db_instance.foo", &instance),
|
||||
testAccCheckDBInstanceMultiIZ(&instance),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestAccAlicloudDBInstance_database(t *testing.T) {
|
||||
var instance rds.DBInstanceAttribute
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() {
|
||||
testAccPreCheck(t)
|
||||
},
|
||||
|
||||
// module name
|
||||
IDRefreshName: "alicloud_db_instance.foo",
|
||||
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckDBInstanceDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccDBInstance_database,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckDBInstanceExists(
|
||||
"alicloud_db_instance.foo", &instance),
|
||||
resource.TestCheckResourceAttr("alicloud_db_instance.foo", "db_mappings.#", "2"),
|
||||
),
|
||||
},
|
||||
|
||||
resource.TestStep{
|
||||
Config: testAccDBInstance_database_update,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckDBInstanceExists(
|
||||
"alicloud_db_instance.foo", &instance),
|
||||
resource.TestCheckResourceAttr("alicloud_db_instance.foo", "db_mappings.#", "3"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestAccAlicloudDBInstance_account(t *testing.T) {
|
||||
var instance rds.DBInstanceAttribute
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() {
|
||||
testAccPreCheck(t)
|
||||
},
|
||||
|
||||
// module name
|
||||
IDRefreshName: "alicloud_db_instance.foo",
|
||||
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckDBInstanceDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccDBInstance_grantDatabasePrivilege2Account,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckDBInstanceExists(
|
||||
"alicloud_db_instance.foo", &instance),
|
||||
resource.TestCheckResourceAttr("alicloud_db_instance.foo", "db_mappings.#", "2"),
|
||||
testAccCheckAccountHasPrivilege2Database("alicloud_db_instance.foo", "tester", "foo", "ReadWrite"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestAccAlicloudDBInstance_allocatePublicConnection(t *testing.T) {
|
||||
var instance rds.DBInstanceAttribute
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() {
|
||||
testAccPreCheck(t)
|
||||
},
|
||||
|
||||
// module name
|
||||
IDRefreshName: "alicloud_db_instance.foo",
|
||||
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckDBInstanceDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccDBInstance_allocatePublicConnection,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckDBInstanceExists(
|
||||
"alicloud_db_instance.foo", &instance),
|
||||
resource.TestCheckResourceAttr("alicloud_db_instance.foo", "connections.#", "2"),
|
||||
testAccCheckHasPublicConnection("alicloud_db_instance.foo"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestAccAlicloudDBInstance_backupPolicy(t *testing.T) {
|
||||
var policies []map[string]interface{}
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() {
|
||||
testAccPreCheck(t)
|
||||
},
|
||||
|
||||
// module name
|
||||
IDRefreshName: "alicloud_db_instance.foo",
|
||||
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckDBInstanceDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccDBInstance_backup,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckBackupPolicyExists(
|
||||
"alicloud_db_instance.foo", policies),
|
||||
testAccCheckKeyValueInMaps(policies, "backup policy", "preferred_backup_period", "Wednesday,Thursday"),
|
||||
testAccCheckKeyValueInMaps(policies, "backup policy", "preferred_backup_time", "00:00Z-01:00Z"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestAccAlicloudDBInstance_securityIps(t *testing.T) {
|
||||
var ips []map[string]interface{}
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() {
|
||||
testAccPreCheck(t)
|
||||
},
|
||||
|
||||
// module name
|
||||
IDRefreshName: "alicloud_db_instance.foo",
|
||||
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckDBInstanceDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccDBInstance_securityIps,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckSecurityIpExists(
|
||||
"alicloud_db_instance.foo", ips),
|
||||
testAccCheckKeyValueInMaps(ips, "security ip", "security_ips", "127.0.0.1"),
|
||||
),
|
||||
},
|
||||
|
||||
resource.TestStep{
|
||||
Config: testAccDBInstance_securityIpsConfig,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckSecurityIpExists(
|
||||
"alicloud_db_instance.foo", ips),
|
||||
testAccCheckKeyValueInMaps(ips, "security ip", "security_ips", "10.168.1.12,100.69.7.112"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestAccAlicloudDBInstance_upgradeClass(t *testing.T) {
|
||||
var instance rds.DBInstanceAttribute
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() {
|
||||
testAccPreCheck(t)
|
||||
},
|
||||
|
||||
// module name
|
||||
IDRefreshName: "alicloud_db_instance.foo",
|
||||
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckDBInstanceDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccDBInstance_class,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckDBInstanceExists(
|
||||
"alicloud_db_instance.foo", &instance),
|
||||
resource.TestCheckResourceAttr("alicloud_db_instance.foo", "db_instance_class", "rds.mysql.t1.small"),
|
||||
),
|
||||
},
|
||||
|
||||
resource.TestStep{
|
||||
Config: testAccDBInstance_classUpgrade,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckDBInstanceExists(
|
||||
"alicloud_db_instance.foo", &instance),
|
||||
resource.TestCheckResourceAttr("alicloud_db_instance.foo", "db_instance_class", "rds.mysql.s1.small"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func testAccCheckSecurityIpExists(n string, ips []map[string]interface{}) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[n]
|
||||
if !ok {
|
||||
return fmt.Errorf("Not found: %s", n)
|
||||
}
|
||||
|
||||
if rs.Primary.ID == "" {
|
||||
return fmt.Errorf("No DB Instance ID is set")
|
||||
}
|
||||
|
||||
conn := testAccProvider.Meta().(*AliyunClient).rdsconn
|
||||
args := rds.DescribeDBInstanceIPsArgs{
|
||||
DBInstanceId: rs.Primary.ID,
|
||||
}
|
||||
|
||||
resp, err := conn.DescribeDBInstanceIPs(&args)
|
||||
log.Printf("[DEBUG] check instance %s security ip %#v", rs.Primary.ID, resp)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p := resp.Items.DBInstanceIPArray
|
||||
|
||||
if len(p) < 1 {
|
||||
return fmt.Errorf("DB security ip not found")
|
||||
}
|
||||
|
||||
ips = flattenDBSecurityIPs(p)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckDBInstanceMultiIZ(i *rds.DBInstanceAttribute) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
if !strings.Contains(i.ZoneId, MULTI_IZ_SYMBOL) {
|
||||
return fmt.Errorf("Current region does not support multiIZ.")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckAccountHasPrivilege2Database(n, accountName, dbName, privilege string) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[n]
|
||||
if !ok {
|
||||
return fmt.Errorf("Not found: %s", n)
|
||||
}
|
||||
|
||||
if rs.Primary.ID == "" {
|
||||
return fmt.Errorf("No DB instance ID is set")
|
||||
}
|
||||
|
||||
conn := testAccProvider.Meta().(*AliyunClient).rdsconn
|
||||
if err := conn.WaitForAccountPrivilege(rs.Primary.ID, accountName, dbName, rds.AccountPrivilege(privilege), 50); err != nil {
|
||||
return fmt.Errorf("Failed to grant database %s privilege to account %s: %v", dbName, accountName, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckHasPublicConnection(n string) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[n]
|
||||
if !ok {
|
||||
return fmt.Errorf("Not found: %s", n)
|
||||
}
|
||||
|
||||
if rs.Primary.ID == "" {
|
||||
return fmt.Errorf("No DB instance ID is set")
|
||||
}
|
||||
|
||||
conn := testAccProvider.Meta().(*AliyunClient).rdsconn
|
||||
if err := conn.WaitForPublicConnection(rs.Primary.ID, 50); err != nil {
|
||||
return fmt.Errorf("Failed to allocate public connection: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckDBInstanceExists(n string, d *rds.DBInstanceAttribute) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[n]
|
||||
if !ok {
|
||||
return fmt.Errorf("Not found: %s", n)
|
||||
}
|
||||
|
||||
if rs.Primary.ID == "" {
|
||||
return fmt.Errorf("No DB Instance ID is set")
|
||||
}
|
||||
|
||||
client := testAccProvider.Meta().(*AliyunClient)
|
||||
attr, err := client.DescribeDBInstanceById(rs.Primary.ID)
|
||||
log.Printf("[DEBUG] check instance %s attribute %#v", rs.Primary.ID, attr)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if attr == nil {
|
||||
return fmt.Errorf("DB Instance not found")
|
||||
}
|
||||
|
||||
*d = *attr
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckBackupPolicyExists(n string, ps []map[string]interface{}) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[n]
|
||||
if !ok {
|
||||
return fmt.Errorf("Backup policy not found: %s", n)
|
||||
}
|
||||
|
||||
if rs.Primary.ID == "" {
|
||||
return fmt.Errorf("No DB Instance ID is set")
|
||||
}
|
||||
|
||||
conn := testAccProvider.Meta().(*AliyunClient).rdsconn
|
||||
|
||||
args := rds.DescribeBackupPolicyArgs{
|
||||
DBInstanceId: rs.Primary.ID,
|
||||
}
|
||||
resp, err := conn.DescribeBackupPolicy(&args)
|
||||
log.Printf("[DEBUG] check instance %s backup policy %#v", rs.Primary.ID, resp)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var bs []rds.BackupPolicy
|
||||
bs = append(bs, resp.BackupPolicy)
|
||||
ps = flattenDBBackup(bs)
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckKeyValueInMaps(ps []map[string]interface{}, propName, key, value string) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
for _, policy := range ps {
|
||||
if policy[key].(string) != value {
|
||||
return fmt.Errorf("DB %s attribute '%s' expected %#v, got %#v", propName, key, value, policy[key])
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckDBInstanceDestroy(s *terraform.State) error {
|
||||
client := testAccProvider.Meta().(*AliyunClient)
|
||||
|
||||
for _, rs := range s.RootModule().Resources {
|
||||
if rs.Type != "alicloud_db_instance.foo" {
|
||||
continue
|
||||
}
|
||||
|
||||
ins, err := client.DescribeDBInstanceById(rs.Primary.ID)
|
||||
|
||||
if ins != nil {
|
||||
return fmt.Errorf("Error DB Instance still exist")
|
||||
}
|
||||
|
||||
// Verify the error is what we want
|
||||
if err != nil {
|
||||
// Verify the error is what we want
|
||||
e, _ := err.(*common.Error)
|
||||
if e.ErrorResponse.Code == InstanceNotfound {
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
const testAccDBInstanceConfig = `
|
||||
resource "alicloud_db_instance" "foo" {
|
||||
engine = "MySQL"
|
||||
engine_version = "5.6"
|
||||
db_instance_class = "rds.mysql.t1.small"
|
||||
db_instance_storage = "10"
|
||||
instance_charge_type = "Postpaid"
|
||||
db_instance_net_type = "Intranet"
|
||||
}
|
||||
`
|
||||
|
||||
const testAccDBInstance_vpc = `
|
||||
data "alicloud_zones" "default" {
|
||||
"available_resource_creation"= "VSwitch"
|
||||
}
|
||||
|
||||
resource "alicloud_vpc" "foo" {
|
||||
name = "tf_test_foo"
|
||||
cidr_block = "172.16.0.0/12"
|
||||
}
|
||||
|
||||
resource "alicloud_vswitch" "foo" {
|
||||
vpc_id = "${alicloud_vpc.foo.id}"
|
||||
cidr_block = "172.16.0.0/21"
|
||||
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||
}
|
||||
|
||||
resource "alicloud_db_instance" "foo" {
|
||||
engine = "MySQL"
|
||||
engine_version = "5.6"
|
||||
db_instance_class = "rds.mysql.t1.small"
|
||||
db_instance_storage = "10"
|
||||
instance_charge_type = "Postpaid"
|
||||
db_instance_net_type = "Intranet"
|
||||
|
||||
vswitch_id = "${alicloud_vswitch.foo.id}"
|
||||
}
|
||||
`
|
||||
const testAccDBInstance_multiIZ = `
|
||||
resource "alicloud_db_instance" "foo" {
|
||||
engine = "MySQL"
|
||||
engine_version = "5.6"
|
||||
db_instance_class = "rds.mysql.t1.small"
|
||||
db_instance_storage = "10"
|
||||
db_instance_net_type = "Intranet"
|
||||
multi_az = true
|
||||
}
|
||||
`
|
||||
|
||||
const testAccDBInstance_prepaid_order = `
|
||||
resource "alicloud_db_instance" "foo" {
|
||||
engine = "MySQL"
|
||||
engine_version = "5.6"
|
||||
db_instance_class = "rds.mysql.t1.small"
|
||||
db_instance_storage = "10"
|
||||
instance_charge_type = "Prepaid"
|
||||
db_instance_net_type = "Intranet"
|
||||
}
|
||||
`
|
||||
|
||||
const testAccDBInstance_database = `
|
||||
resource "alicloud_db_instance" "foo" {
|
||||
engine = "MySQL"
|
||||
engine_version = "5.6"
|
||||
db_instance_class = "rds.mysql.t1.small"
|
||||
db_instance_storage = "10"
|
||||
instance_charge_type = "Postpaid"
|
||||
db_instance_net_type = "Intranet"
|
||||
|
||||
db_mappings = [
|
||||
{
|
||||
"db_name" = "foo"
|
||||
"character_set_name" = "utf8"
|
||||
"db_description" = "tf"
|
||||
},{
|
||||
"db_name" = "bar"
|
||||
"character_set_name" = "utf8"
|
||||
"db_description" = "tf"
|
||||
}]
|
||||
}
|
||||
`
|
||||
const testAccDBInstance_database_update = `
|
||||
resource "alicloud_db_instance" "foo" {
|
||||
engine = "MySQL"
|
||||
engine_version = "5.6"
|
||||
db_instance_class = "rds.mysql.t1.small"
|
||||
db_instance_storage = "10"
|
||||
instance_charge_type = "Postpaid"
|
||||
db_instance_net_type = "Intranet"
|
||||
|
||||
db_mappings = [
|
||||
{
|
||||
"db_name" = "foo"
|
||||
"character_set_name" = "utf8"
|
||||
"db_description" = "tf"
|
||||
},{
|
||||
"db_name" = "bar"
|
||||
"character_set_name" = "utf8"
|
||||
"db_description" = "tf"
|
||||
},{
|
||||
"db_name" = "zzz"
|
||||
"character_set_name" = "utf8"
|
||||
"db_description" = "tf"
|
||||
}]
|
||||
}
|
||||
`
|
||||
|
||||
const testAccDBInstance_grantDatabasePrivilege2Account = `
|
||||
resource "alicloud_db_instance" "foo" {
|
||||
engine = "MySQL"
|
||||
engine_version = "5.6"
|
||||
db_instance_class = "rds.mysql.t1.small"
|
||||
db_instance_storage = "10"
|
||||
instance_charge_type = "Postpaid"
|
||||
db_instance_net_type = "Intranet"
|
||||
|
||||
master_user_name = "tester"
|
||||
master_user_password = "Test12345"
|
||||
|
||||
db_mappings = [
|
||||
{
|
||||
"db_name" = "foo"
|
||||
"character_set_name" = "utf8"
|
||||
"db_description" = "tf"
|
||||
},{
|
||||
"db_name" = "bar"
|
||||
"character_set_name" = "utf8"
|
||||
"db_description" = "tf"
|
||||
}]
|
||||
}
|
||||
`
|
||||
|
||||
const testAccDBInstance_allocatePublicConnection = `
|
||||
resource "alicloud_db_instance" "foo" {
|
||||
engine = "MySQL"
|
||||
engine_version = "5.6"
|
||||
db_instance_class = "rds.mysql.t1.small"
|
||||
db_instance_storage = "10"
|
||||
instance_charge_type = "Postpaid"
|
||||
db_instance_net_type = "Intranet"
|
||||
|
||||
master_user_name = "tester"
|
||||
master_user_password = "Test12345"
|
||||
|
||||
allocate_public_connection = true
|
||||
}
|
||||
`
|
||||
|
||||
const testAccDBInstance_backup = `
|
||||
resource "alicloud_db_instance" "foo" {
|
||||
engine = "MySQL"
|
||||
engine_version = "5.6"
|
||||
db_instance_class = "rds.mysql.t1.small"
|
||||
db_instance_storage = "10"
|
||||
instance_charge_type = "Postpaid"
|
||||
db_instance_net_type = "Intranet"
|
||||
|
||||
preferred_backup_period = ["Wednesday","Thursday"]
|
||||
preferred_backup_time = "00:00Z-01:00Z"
|
||||
backup_retention_period = 9
|
||||
}
|
||||
`
|
||||
|
||||
const testAccDBInstance_securityIps = `
|
||||
resource "alicloud_db_instance" "foo" {
|
||||
engine = "MySQL"
|
||||
engine_version = "5.6"
|
||||
db_instance_class = "rds.mysql.t1.small"
|
||||
db_instance_storage = "10"
|
||||
instance_charge_type = "Postpaid"
|
||||
db_instance_net_type = "Intranet"
|
||||
}
|
||||
`
|
||||
const testAccDBInstance_securityIpsConfig = `
|
||||
resource "alicloud_db_instance" "foo" {
|
||||
engine = "MySQL"
|
||||
engine_version = "5.6"
|
||||
db_instance_class = "rds.mysql.t1.small"
|
||||
db_instance_storage = "10"
|
||||
instance_charge_type = "Postpaid"
|
||||
db_instance_net_type = "Intranet"
|
||||
|
||||
security_ips = ["10.168.1.12", "100.69.7.112"]
|
||||
}
|
||||
`
|
||||
|
||||
const testAccDBInstance_class = `
|
||||
resource "alicloud_db_instance" "foo" {
|
||||
engine = "MySQL"
|
||||
engine_version = "5.6"
|
||||
db_instance_class = "rds.mysql.t1.small"
|
||||
db_instance_storage = "10"
|
||||
db_instance_net_type = "Intranet"
|
||||
}
|
||||
`
|
||||
const testAccDBInstance_classUpgrade = `
|
||||
resource "alicloud_db_instance" "foo" {
|
||||
engine = "MySQL"
|
||||
engine_version = "5.6"
|
||||
db_instance_class = "rds.mysql.s1.small"
|
||||
db_instance_storage = "10"
|
||||
db_instance_net_type = "Intranet"
|
||||
}
|
||||
`
|
|
@ -151,4 +151,5 @@ resource "alicloud_security_group" "group" {
|
|||
name = "terraform-test-group"
|
||||
description = "New security group"
|
||||
}
|
||||
|
||||
`
|
||||
|
|
|
@ -136,9 +136,13 @@ func testAccCheckDiskDestroy(s *terraform.State) error {
|
|||
}
|
||||
|
||||
const testAccDiskConfig = `
|
||||
data "alicloud_zones" "default" {
|
||||
"available_disk_category"= "cloud_efficiency"
|
||||
}
|
||||
|
||||
resource "alicloud_disk" "foo" {
|
||||
# cn-beijing
|
||||
availability_zone = "cn-beijing-b"
|
||||
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||
name = "New-disk"
|
||||
description = "Hello ecs disk."
|
||||
category = "cloud_efficiency"
|
||||
|
@ -146,10 +150,15 @@ resource "alicloud_disk" "foo" {
|
|||
}
|
||||
`
|
||||
const testAccDiskConfigWithTags = `
|
||||
data "alicloud_zones" "default" {
|
||||
"available_disk_category"= "cloud_efficiency"
|
||||
}
|
||||
|
||||
resource "alicloud_disk" "bar" {
|
||||
# cn-beijing
|
||||
availability_zone = "cn-beijing-b"
|
||||
size = "10"
|
||||
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||
category = "cloud_efficiency"
|
||||
size = "20"
|
||||
tags {
|
||||
Name = "TerraformTest"
|
||||
}
|
||||
|
|
|
@ -108,6 +108,10 @@ func testAccCheckEIPAssociationDestroy(s *terraform.State) error {
|
|||
}
|
||||
|
||||
const testAccEIPAssociationConfig = `
|
||||
data "alicloud_zones" "default" {
|
||||
"available_resource_creation"= "VSwitch"
|
||||
}
|
||||
|
||||
resource "alicloud_vpc" "main" {
|
||||
cidr_block = "10.1.0.0/21"
|
||||
}
|
||||
|
@ -115,19 +119,23 @@ resource "alicloud_vpc" "main" {
|
|||
resource "alicloud_vswitch" "main" {
|
||||
vpc_id = "${alicloud_vpc.main.id}"
|
||||
cidr_block = "10.1.1.0/24"
|
||||
availability_zone = "cn-beijing-a"
|
||||
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||
depends_on = [
|
||||
"alicloud_vpc.main"]
|
||||
}
|
||||
|
||||
resource "alicloud_instance" "instance" {
|
||||
image_id = "ubuntu_140405_64_40G_cloudinit_20161115.vhd"
|
||||
instance_type = "ecs.s1.small"
|
||||
availability_zone = "cn-beijing-a"
|
||||
security_groups = ["${alicloud_security_group.group.id}"]
|
||||
# cn-beijing
|
||||
vswitch_id = "${alicloud_vswitch.main.id}"
|
||||
instance_name = "hello"
|
||||
io_optimized = "none"
|
||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||
|
||||
# series II
|
||||
instance_type = "ecs.n1.medium"
|
||||
io_optimized = "optimized"
|
||||
system_disk_category = "cloud_efficiency"
|
||||
|
||||
security_groups = ["${alicloud_security_group.group.id}"]
|
||||
instance_name = "test_foo"
|
||||
|
||||
tags {
|
||||
Name = "TerraformTest-instance"
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"log"
|
||||
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
"github.com/denverdino/aliyungo/ecs"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
|
@ -21,8 +22,9 @@ func resourceAliyunInstance() *schema.Resource {
|
|||
Schema: map[string]*schema.Schema{
|
||||
"availability_zone": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"image_id": &schema.Schema{
|
||||
|
@ -60,11 +62,6 @@ func resourceAliyunInstance() *schema.Resource {
|
|||
ValidateFunc: validateInstanceDescription,
|
||||
},
|
||||
|
||||
"instance_network_type": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"internet_charge_type": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
|
@ -104,11 +101,19 @@ func resourceAliyunInstance() *schema.Resource {
|
|||
Default: "cloud",
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validateAllowedStringValue([]string{
|
||||
string(ecs.DiskCategoryCloud),
|
||||
string(ecs.DiskCategoryCloudSSD),
|
||||
string(ecs.DiskCategoryCloudEfficiency),
|
||||
string(ecs.DiskCategoryEphemeralSSD),
|
||||
}),
|
||||
},
|
||||
"system_disk_size": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validateIntegerInRange(40, 500),
|
||||
},
|
||||
|
||||
//subnet_id and vswitch_id both exists, cause compatible old version, and aws habit.
|
||||
|
@ -145,7 +150,6 @@ func resourceAliyunInstance() *schema.Resource {
|
|||
|
||||
"private_ip": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
|
@ -168,6 +172,11 @@ func resourceAliyunInstance() *schema.Resource {
|
|||
func resourceAliyunInstanceCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AliyunClient).ecsconn
|
||||
|
||||
// create postpaid instance by runInstances API
|
||||
if v := d.Get("instance_charge_type").(string); v != string(common.PrePaid) {
|
||||
return resourceAliyunRunInstance(d, meta)
|
||||
}
|
||||
|
||||
args, err := buildAliyunInstanceArgs(d, meta)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -181,7 +190,8 @@ func resourceAliyunInstanceCreate(d *schema.ResourceData, meta interface{}) erro
|
|||
d.SetId(instanceID)
|
||||
|
||||
d.Set("password", d.Get("password"))
|
||||
d.Set("system_disk_category", d.Get("system_disk_category"))
|
||||
//d.Set("system_disk_category", d.Get("system_disk_category"))
|
||||
//d.Set("system_disk_size", d.Get("system_disk_size"))
|
||||
|
||||
if d.Get("allocate_public_ip").(bool) {
|
||||
_, err := conn.AllocatePublicIpAddress(d.Id())
|
||||
|
@ -207,11 +217,56 @@ func resourceAliyunInstanceCreate(d *schema.ResourceData, meta interface{}) erro
|
|||
return resourceAliyunInstanceUpdate(d, meta)
|
||||
}
|
||||
|
||||
func resourceAliyunRunInstance(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AliyunClient).ecsconn
|
||||
newConn := meta.(*AliyunClient).ecsNewconn
|
||||
|
||||
args, err := buildAliyunInstanceArgs(d, meta)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runArgs, err := buildAliyunRunInstancesArgs(d, meta)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runArgs.CreateInstanceArgs = *args
|
||||
|
||||
// runInstances is support in version 2016-03-14
|
||||
instanceIds, err := newConn.RunInstances(runArgs)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating Aliyun ecs instance: %#v", err)
|
||||
}
|
||||
|
||||
d.SetId(instanceIds[0])
|
||||
|
||||
d.Set("password", d.Get("password"))
|
||||
d.Set("system_disk_category", d.Get("system_disk_category"))
|
||||
d.Set("system_disk_size", d.Get("system_disk_size"))
|
||||
|
||||
if d.Get("allocate_public_ip").(bool) {
|
||||
_, err := conn.AllocatePublicIpAddress(d.Id())
|
||||
if err != nil {
|
||||
log.Printf("[DEBUG] AllocatePublicIpAddress for instance got error: %#v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// after instance created, its status change from pending, starting to running
|
||||
if err := conn.WaitForInstanceAsyn(d.Id(), ecs.Running, defaultTimeout); err != nil {
|
||||
log.Printf("[DEBUG] WaitForInstance %s got error: %#v", ecs.Running, err)
|
||||
}
|
||||
|
||||
return resourceAliyunInstanceUpdate(d, meta)
|
||||
}
|
||||
|
||||
func resourceAliyunInstanceRead(d *schema.ResourceData, meta interface{}) error {
|
||||
client := meta.(*AliyunClient)
|
||||
conn := client.ecsconn
|
||||
|
||||
instance, err := client.QueryInstancesById(d.Id())
|
||||
|
||||
if err != nil {
|
||||
if notFoundError(err) {
|
||||
d.SetId("")
|
||||
|
@ -220,7 +275,15 @@ func resourceAliyunInstanceRead(d *schema.ResourceData, meta interface{}) error
|
|||
return fmt.Errorf("Error DescribeInstanceAttribute: %#v", err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] DescribeInstanceAttribute for instance: %#v", instance)
|
||||
disk, diskErr := client.QueryInstanceSystemDisk(d.Id())
|
||||
|
||||
if diskErr != nil {
|
||||
if notFoundError(diskErr) {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Error DescribeSystemDisk: %#v", err)
|
||||
}
|
||||
|
||||
d.Set("instance_name", instance.InstanceName)
|
||||
d.Set("description", instance.Description)
|
||||
|
@ -229,6 +292,8 @@ func resourceAliyunInstanceRead(d *schema.ResourceData, meta interface{}) error
|
|||
d.Set("host_name", instance.HostName)
|
||||
d.Set("image_id", instance.ImageId)
|
||||
d.Set("instance_type", instance.InstanceType)
|
||||
d.Set("system_disk_category", disk.Category)
|
||||
d.Set("system_disk_size", disk.Size)
|
||||
|
||||
// In Classic network, internet_charge_type is valid in any case, and its default value is 'PayByBanwidth'.
|
||||
// In VPC network, internet_charge_type is valid when instance has public ip, and its default value is 'PayByBanwidth'.
|
||||
|
@ -244,10 +309,6 @@ func resourceAliyunInstanceRead(d *schema.ResourceData, meta interface{}) error
|
|||
d.Set("io_optimized", "none")
|
||||
}
|
||||
|
||||
log.Printf("instance.InternetChargeType: %#v", instance.InternetChargeType)
|
||||
|
||||
d.Set("instance_network_type", instance.InstanceNetworkType)
|
||||
|
||||
if d.Get("subnet_id").(string) != "" || d.Get("vswitch_id").(string) != "" {
|
||||
ipAddress := instance.VpcAttributes.PrivateIpAddress.IpAddress[0]
|
||||
d.Set("private_ip", ipAddress)
|
||||
|
@ -414,6 +475,30 @@ func resourceAliyunInstanceDelete(d *schema.ResourceData, meta interface{}) erro
|
|||
|
||||
return nil
|
||||
}
|
||||
func buildAliyunRunInstancesArgs(d *schema.ResourceData, meta interface{}) (*ecs.RunInstanceArgs, error) {
|
||||
args := &ecs.RunInstanceArgs{
|
||||
MaxAmount: DEFAULT_INSTANCE_COUNT,
|
||||
MinAmount: DEFAULT_INSTANCE_COUNT,
|
||||
}
|
||||
|
||||
bussStr, err := json.Marshal(DefaultBusinessInfo)
|
||||
if err != nil {
|
||||
log.Printf("Failed to translate bussiness info %#v from json to string", DefaultBusinessInfo)
|
||||
}
|
||||
|
||||
args.BusinessInfo = string(bussStr)
|
||||
|
||||
subnetValue := d.Get("subnet_id").(string)
|
||||
vswitchValue := d.Get("vswitch_id").(string)
|
||||
//networkValue := d.Get("instance_network_type").(string)
|
||||
|
||||
// because runInstance is not compatible with createInstance, force NetworkType value to classic
|
||||
if subnetValue == "" && vswitchValue == "" {
|
||||
args.NetworkType = string(ClassicNet)
|
||||
}
|
||||
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func buildAliyunInstanceArgs(d *schema.ResourceData, meta interface{}) (*ecs.CreateInstanceArgs, error) {
|
||||
client := meta.(*AliyunClient)
|
||||
|
@ -421,15 +506,18 @@ func buildAliyunInstanceArgs(d *schema.ResourceData, meta interface{}) (*ecs.Cre
|
|||
args := &ecs.CreateInstanceArgs{
|
||||
RegionId: getRegion(d, meta),
|
||||
InstanceType: d.Get("instance_type").(string),
|
||||
PrivateIpAddress: d.Get("private_ip").(string),
|
||||
}
|
||||
|
||||
imageID := d.Get("image_id").(string)
|
||||
|
||||
args.ImageId = imageID
|
||||
|
||||
zoneID := d.Get("availability_zone").(string)
|
||||
systemDiskCategory := ecs.DiskCategory(d.Get("system_disk_category").(string))
|
||||
systemDiskSize := d.Get("system_disk_size").(int)
|
||||
|
||||
zoneID := d.Get("availability_zone").(string)
|
||||
// check instanceType and systemDiskCategory, when zoneID is not empty
|
||||
if zoneID != "" {
|
||||
zone, err := client.DescribeZone(zoneID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -439,8 +527,19 @@ func buildAliyunInstanceArgs(d *schema.ResourceData, meta interface{}) (*ecs.Cre
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if err := client.DiskAvailable(zone, systemDiskCategory); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
args.ZoneId = zoneID
|
||||
|
||||
}
|
||||
|
||||
args.SystemDisk = ecs.SystemDiskType{
|
||||
Category: systemDiskCategory,
|
||||
Size: systemDiskSize,
|
||||
}
|
||||
|
||||
sgs, ok := d.GetOk("security_groups")
|
||||
|
||||
if ok {
|
||||
|
@ -451,17 +550,6 @@ func buildAliyunInstanceArgs(d *schema.ResourceData, meta interface{}) (*ecs.Cre
|
|||
if err == nil {
|
||||
args.SecurityGroupId = sg0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
systemDiskCategory := ecs.DiskCategory(d.Get("system_disk_category").(string))
|
||||
|
||||
if err := client.DiskAvailable(zone, systemDiskCategory); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
args.SystemDisk = ecs.SystemDiskType{
|
||||
Category: systemDiskCategory,
|
||||
}
|
||||
|
||||
if v := d.Get("instance_name").(string); v != "" {
|
||||
|
@ -472,7 +560,7 @@ func buildAliyunInstanceArgs(d *schema.ResourceData, meta interface{}) (*ecs.Cre
|
|||
args.Description = v
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] internet_charge_type is %s", d.Get("internet_charge_type").(string))
|
||||
log.Printf("[DEBUG] SystemDisk is %d", systemDiskSize)
|
||||
if v := d.Get("internet_charge_type").(string); v != "" {
|
||||
args.InternetChargeType = common.InternetChargeType(v)
|
||||
}
|
||||
|
@ -490,7 +578,11 @@ func buildAliyunInstanceArgs(d *schema.ResourceData, meta interface{}) (*ecs.Cre
|
|||
}
|
||||
|
||||
if v := d.Get("io_optimized").(string); v != "" {
|
||||
args.IoOptimized = ecs.IoOptimized(v)
|
||||
if v == "optimized" {
|
||||
args.IoOptimized = ecs.IoOptimized("true")
|
||||
} else {
|
||||
args.IoOptimized = ecs.IoOptimized("false")
|
||||
}
|
||||
}
|
||||
|
||||
vswitchValue := d.Get("subnet_id").(string)
|
||||
|
|
|
@ -56,6 +56,7 @@ func TestAccAlicloudInstance_basic(t *testing.T) {
|
|||
"alicloud_instance.foo",
|
||||
"internet_charge_type",
|
||||
"PayByBandwidth"),
|
||||
testAccCheckSystemDiskSize("alicloud_instance.foo", 80),
|
||||
),
|
||||
},
|
||||
|
||||
|
@ -355,10 +356,6 @@ func TestAccAlicloudInstance_tags(t *testing.T) {
|
|||
Config: testAccCheckInstanceConfigTagsUpdate,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckInstanceExists("alicloud_instance.foo", &instance),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_instance.foo",
|
||||
"tags.foo",
|
||||
""),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_instance.foo",
|
||||
"tags.bar",
|
||||
|
@ -418,8 +415,8 @@ func TestAccAlicloudInstance_privateIP(t *testing.T) {
|
|||
testCheckPrivateIP := func() resource.TestCheckFunc {
|
||||
return func(*terraform.State) error {
|
||||
privateIP := instance.VpcAttributes.PrivateIpAddress.IpAddress[0]
|
||||
if privateIP != "172.16.0.229" {
|
||||
return fmt.Errorf("bad private IP: %s", privateIP)
|
||||
if privateIP == "" {
|
||||
return fmt.Errorf("can't get private IP")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -445,14 +442,14 @@ func TestAccAlicloudInstance_privateIP(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestAccAlicloudInstance_associatePublicIPAndPrivateIP(t *testing.T) {
|
||||
func TestAccAlicloudInstance_associatePublicIP(t *testing.T) {
|
||||
var instance ecs.InstanceAttributesType
|
||||
|
||||
testCheckPrivateIP := func() resource.TestCheckFunc {
|
||||
return func(*terraform.State) error {
|
||||
privateIP := instance.VpcAttributes.PrivateIpAddress.IpAddress[0]
|
||||
if privateIP != "172.16.0.229" {
|
||||
return fmt.Errorf("bad private IP: %s", privateIP)
|
||||
if privateIP == "" {
|
||||
return fmt.Errorf("can't get private IP")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -468,7 +465,7 @@ func TestAccAlicloudInstance_associatePublicIPAndPrivateIP(t *testing.T) {
|
|||
CheckDestroy: testAccCheckInstanceDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccInstanceConfigAssociatePublicIPAndPrivateIP,
|
||||
Config: testAccInstanceConfigAssociatePublicIP,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckInstanceExists("alicloud_instance.foo", &instance),
|
||||
testCheckPrivateIP(),
|
||||
|
@ -597,6 +594,36 @@ func testAccCheckInstanceDestroyWithProvider(s *terraform.State, provider *schem
|
|||
return nil
|
||||
}
|
||||
|
||||
func testAccCheckSystemDiskSize(n string, size int) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
providers := []*schema.Provider{testAccProvider}
|
||||
rs, ok := s.RootModule().Resources[n]
|
||||
|
||||
if !ok {
|
||||
return fmt.Errorf("Not found: %s", n)
|
||||
}
|
||||
|
||||
for _, provider := range providers {
|
||||
if provider.Meta() == nil {
|
||||
continue
|
||||
}
|
||||
client := provider.Meta().(*AliyunClient)
|
||||
systemDisk, err := client.QueryInstanceSystemDisk(rs.Primary.ID)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR]get system disk size error: %#v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if systemDisk.Size != size {
|
||||
return fmt.Errorf("system disk size not equal %d, the instance system size is %d",
|
||||
size, systemDisk.Size)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
const testAccInstanceConfig = `
|
||||
resource "alicloud_security_group" "tf_test_foo" {
|
||||
name = "tf_test_foo"
|
||||
|
@ -609,11 +636,10 @@ resource "alicloud_security_group" "tf_test_bar" {
|
|||
}
|
||||
|
||||
resource "alicloud_instance" "foo" {
|
||||
# cn-beijing
|
||||
availability_zone = "cn-beijing-b"
|
||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||
|
||||
system_disk_category = "cloud_ssd"
|
||||
system_disk_size = 80
|
||||
|
||||
instance_type = "ecs.n1.small"
|
||||
internet_charge_type = "PayByBandwidth"
|
||||
|
@ -628,6 +654,11 @@ resource "alicloud_instance" "foo" {
|
|||
}
|
||||
`
|
||||
const testAccInstanceConfigVPC = `
|
||||
data "alicloud_zones" "default" {
|
||||
"available_disk_category"= "cloud_efficiency"
|
||||
"available_resource_creation"= "VSwitch"
|
||||
}
|
||||
|
||||
resource "alicloud_vpc" "foo" {
|
||||
name = "tf_test_foo"
|
||||
cidr_block = "172.16.0.0/12"
|
||||
|
@ -636,7 +667,7 @@ resource "alicloud_vpc" "foo" {
|
|||
resource "alicloud_vswitch" "foo" {
|
||||
vpc_id = "${alicloud_vpc.foo.id}"
|
||||
cidr_block = "172.16.0.0/21"
|
||||
availability_zone = "cn-beijing-b"
|
||||
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group" "tf_test_foo" {
|
||||
|
@ -647,7 +678,6 @@ resource "alicloud_security_group" "tf_test_foo" {
|
|||
|
||||
resource "alicloud_instance" "foo" {
|
||||
# cn-beijing
|
||||
availability_zone = "cn-beijing-b"
|
||||
vswitch_id = "${alicloud_vswitch.foo.id}"
|
||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||
|
||||
|
@ -666,6 +696,11 @@ resource "alicloud_instance" "foo" {
|
|||
`
|
||||
|
||||
const testAccInstanceConfigUserData = `
|
||||
data "alicloud_zones" "default" {
|
||||
"available_disk_category"= "cloud_efficiency"
|
||||
"available_resource_creation"= "VSwitch"
|
||||
}
|
||||
|
||||
resource "alicloud_vpc" "foo" {
|
||||
name = "tf_test_foo"
|
||||
cidr_block = "172.16.0.0/12"
|
||||
|
@ -674,7 +709,7 @@ resource "alicloud_vpc" "foo" {
|
|||
resource "alicloud_vswitch" "foo" {
|
||||
vpc_id = "${alicloud_vpc.foo.id}"
|
||||
cidr_block = "172.16.0.0/21"
|
||||
availability_zone = "cn-beijing-b"
|
||||
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group" "tf_test_foo" {
|
||||
|
@ -685,7 +720,6 @@ resource "alicloud_security_group" "tf_test_foo" {
|
|||
|
||||
resource "alicloud_instance" "foo" {
|
||||
# cn-beijing
|
||||
availability_zone = "cn-beijing-b"
|
||||
vswitch_id = "${alicloud_vswitch.foo.id}"
|
||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||
# series II
|
||||
|
@ -727,7 +761,6 @@ resource "alicloud_security_group" "tf_test_bar" {
|
|||
resource "alicloud_instance" "foo" {
|
||||
# cn-beijing
|
||||
provider = "alicloud.beijing"
|
||||
availability_zone = "cn-beijing-b"
|
||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||
|
||||
internet_charge_type = "PayByBandwidth"
|
||||
|
@ -742,7 +775,6 @@ resource "alicloud_instance" "foo" {
|
|||
resource "alicloud_instance" "bar" {
|
||||
# cn-shanghai
|
||||
provider = "alicloud.shanghai"
|
||||
availability_zone = "cn-shanghai-b"
|
||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||
|
||||
internet_charge_type = "PayByBandwidth"
|
||||
|
@ -768,7 +800,6 @@ resource "alicloud_security_group" "tf_test_bar" {
|
|||
|
||||
resource "alicloud_instance" "foo" {
|
||||
# cn-beijing
|
||||
availability_zone = "cn-beijing-b"
|
||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||
|
||||
instance_type = "ecs.s2.large"
|
||||
|
@ -776,6 +807,7 @@ resource "alicloud_instance" "foo" {
|
|||
security_groups = ["${alicloud_security_group.tf_test_foo.id}", "${alicloud_security_group.tf_test_bar.id}"]
|
||||
instance_name = "test_foo"
|
||||
io_optimized = "optimized"
|
||||
system_disk_category = "cloud_efficiency"
|
||||
}`
|
||||
|
||||
const testAccInstanceConfig_multiSecurityGroup_add = `
|
||||
|
@ -796,7 +828,6 @@ resource "alicloud_security_group" "tf_test_add_sg" {
|
|||
|
||||
resource "alicloud_instance" "foo" {
|
||||
# cn-beijing
|
||||
availability_zone = "cn-beijing-b"
|
||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||
|
||||
instance_type = "ecs.s2.large"
|
||||
|
@ -805,6 +836,7 @@ resource "alicloud_instance" "foo" {
|
|||
"${alicloud_security_group.tf_test_add_sg.id}"]
|
||||
instance_name = "test_foo"
|
||||
io_optimized = "optimized"
|
||||
system_disk_category = "cloud_efficiency"
|
||||
}
|
||||
`
|
||||
|
||||
|
@ -814,9 +846,30 @@ resource "alicloud_security_group" "tf_test_foo" {
|
|||
description = "foo"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "http-in" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "internet"
|
||||
policy = "accept"
|
||||
port_range = "80/80"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.tf_test_foo.id}"
|
||||
cidr_ip = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "ssh-in" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "internet"
|
||||
policy = "accept"
|
||||
port_range = "22/22"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.tf_test_foo.id}"
|
||||
cidr_ip = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
resource "alicloud_instance" "foo" {
|
||||
# cn-beijing
|
||||
availability_zone = "cn-beijing-b"
|
||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||
|
||||
instance_type = "ecs.s2.large"
|
||||
|
@ -824,6 +877,7 @@ resource "alicloud_instance" "foo" {
|
|||
security_groups = ["${alicloud_security_group.tf_test_foo.id}"]
|
||||
instance_name = "test_foo"
|
||||
io_optimized = "optimized"
|
||||
system_disk_category = "cloud_efficiency"
|
||||
}
|
||||
`
|
||||
|
||||
|
@ -836,18 +890,23 @@ resource "alicloud_security_group" "tf_test_foo" {
|
|||
|
||||
resource "alicloud_instance" "foo" {
|
||||
# cn-beijing
|
||||
availability_zone = "cn-beijing-b"
|
||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||
|
||||
instance_type = "ecs.s2.large"
|
||||
internet_charge_type = "PayByBandwidth"
|
||||
security_groups = ["${alicloud_security_group.tf_test_foo.*.id}"]
|
||||
instance_name = "test_foo"
|
||||
io_optimized = "none"
|
||||
io_optimized = "optimized"
|
||||
system_disk_category = "cloud_efficiency"
|
||||
}
|
||||
`
|
||||
|
||||
const testAccInstanceNetworkInstanceSecurityGroups = `
|
||||
data "alicloud_zones" "default" {
|
||||
"available_disk_category"= "cloud_efficiency"
|
||||
"available_resource_creation"= "VSwitch"
|
||||
}
|
||||
|
||||
resource "alicloud_vpc" "foo" {
|
||||
name = "tf_test_foo"
|
||||
cidr_block = "172.16.0.0/12"
|
||||
|
@ -856,7 +915,7 @@ resource "alicloud_vpc" "foo" {
|
|||
resource "alicloud_vswitch" "foo" {
|
||||
vpc_id = "${alicloud_vpc.foo.id}"
|
||||
cidr_block = "172.16.0.0/21"
|
||||
availability_zone = "cn-beijing-b"
|
||||
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group" "tf_test_foo" {
|
||||
|
@ -867,7 +926,6 @@ resource "alicloud_security_group" "tf_test_foo" {
|
|||
|
||||
resource "alicloud_instance" "foo" {
|
||||
# cn-beijing
|
||||
availability_zone = "cn-beijing-b"
|
||||
vswitch_id = "${alicloud_vswitch.foo.id}"
|
||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||
|
||||
|
@ -892,7 +950,6 @@ resource "alicloud_security_group" "tf_test_foo" {
|
|||
|
||||
resource "alicloud_instance" "foo" {
|
||||
# cn-beijing
|
||||
availability_zone = "cn-beijing-b"
|
||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||
|
||||
# series II
|
||||
|
@ -918,7 +975,6 @@ resource "alicloud_security_group" "tf_test_foo" {
|
|||
|
||||
resource "alicloud_instance" "foo" {
|
||||
# cn-beijing
|
||||
availability_zone = "cn-beijing-b"
|
||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||
|
||||
# series II
|
||||
|
@ -941,9 +997,30 @@ resource "alicloud_security_group" "tf_test_foo" {
|
|||
description = "foo"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "http-in" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "internet"
|
||||
policy = "accept"
|
||||
port_range = "80/80"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.tf_test_foo.id}"
|
||||
cidr_ip = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "ssh-in" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "internet"
|
||||
policy = "accept"
|
||||
port_range = "22/22"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.tf_test_foo.id}"
|
||||
cidr_ip = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
resource "alicloud_instance" "foo" {
|
||||
# cn-beijing
|
||||
availability_zone = "cn-beijing-b"
|
||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||
|
||||
# series II
|
||||
|
@ -965,9 +1042,30 @@ resource "alicloud_security_group" "tf_test_foo" {
|
|||
description = "foo"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "http-in" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "internet"
|
||||
policy = "accept"
|
||||
port_range = "80/80"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.tf_test_foo.id}"
|
||||
cidr_ip = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "ssh-in" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "internet"
|
||||
policy = "accept"
|
||||
port_range = "22/22"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.tf_test_foo.id}"
|
||||
cidr_ip = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
resource "alicloud_instance" "foo" {
|
||||
# cn-beijing
|
||||
availability_zone = "cn-beijing-b"
|
||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||
|
||||
# series II
|
||||
|
@ -984,6 +1082,11 @@ resource "alicloud_instance" "foo" {
|
|||
`
|
||||
|
||||
const testAccInstanceConfigPrivateIP = `
|
||||
data "alicloud_zones" "default" {
|
||||
"available_disk_category"= "cloud_efficiency"
|
||||
"available_resource_creation"= "VSwitch"
|
||||
}
|
||||
|
||||
resource "alicloud_vpc" "foo" {
|
||||
name = "tf_test_foo"
|
||||
cidr_block = "172.16.0.0/12"
|
||||
|
@ -992,7 +1095,7 @@ resource "alicloud_vpc" "foo" {
|
|||
resource "alicloud_vswitch" "foo" {
|
||||
vpc_id = "${alicloud_vpc.foo.id}"
|
||||
cidr_block = "172.16.0.0/24"
|
||||
availability_zone = "cn-beijing-b"
|
||||
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group" "tf_test_foo" {
|
||||
|
@ -1003,11 +1106,9 @@ resource "alicloud_security_group" "tf_test_foo" {
|
|||
|
||||
resource "alicloud_instance" "foo" {
|
||||
# cn-beijing
|
||||
availability_zone = "cn-beijing-b"
|
||||
security_groups = ["${alicloud_security_group.tf_test_foo.id}"]
|
||||
|
||||
vswitch_id = "${alicloud_vswitch.foo.id}"
|
||||
private_ip = "172.16.0.229"
|
||||
|
||||
# series II
|
||||
instance_type = "ecs.n1.medium"
|
||||
|
@ -1017,7 +1118,12 @@ resource "alicloud_instance" "foo" {
|
|||
instance_name = "test_foo"
|
||||
}
|
||||
`
|
||||
const testAccInstanceConfigAssociatePublicIPAndPrivateIP = `
|
||||
const testAccInstanceConfigAssociatePublicIP = `
|
||||
data "alicloud_zones" "default" {
|
||||
"available_disk_category"= "cloud_efficiency"
|
||||
"available_resource_creation"= "VSwitch"
|
||||
}
|
||||
|
||||
resource "alicloud_vpc" "foo" {
|
||||
name = "tf_test_foo"
|
||||
cidr_block = "172.16.0.0/12"
|
||||
|
@ -1026,7 +1132,7 @@ resource "alicloud_vpc" "foo" {
|
|||
resource "alicloud_vswitch" "foo" {
|
||||
vpc_id = "${alicloud_vpc.foo.id}"
|
||||
cidr_block = "172.16.0.0/24"
|
||||
availability_zone = "cn-beijing-b"
|
||||
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group" "tf_test_foo" {
|
||||
|
@ -1037,11 +1143,9 @@ resource "alicloud_security_group" "tf_test_foo" {
|
|||
|
||||
resource "alicloud_instance" "foo" {
|
||||
# cn-beijing
|
||||
availability_zone = "cn-beijing-b"
|
||||
security_groups = ["${alicloud_security_group.tf_test_foo.id}"]
|
||||
|
||||
vswitch_id = "${alicloud_vswitch.foo.id}"
|
||||
private_ip = "172.16.0.229"
|
||||
allocate_public_ip = "true"
|
||||
internet_max_bandwidth_out = 5
|
||||
internet_charge_type = "PayByBandwidth"
|
||||
|
@ -1055,6 +1159,11 @@ resource "alicloud_instance" "foo" {
|
|||
}
|
||||
`
|
||||
const testAccVpcInstanceWithSecurityRule = `
|
||||
data "alicloud_zones" "default" {
|
||||
"available_disk_category"= "cloud_efficiency"
|
||||
"available_resource_creation"= "VSwitch"
|
||||
}
|
||||
|
||||
resource "alicloud_vpc" "foo" {
|
||||
name = "tf_test_foo"
|
||||
cidr_block = "10.1.0.0/21"
|
||||
|
@ -1063,7 +1172,7 @@ resource "alicloud_vpc" "foo" {
|
|||
resource "alicloud_vswitch" "foo" {
|
||||
vpc_id = "${alicloud_vpc.foo.id}"
|
||||
cidr_block = "10.1.1.0/24"
|
||||
availability_zone = "cn-beijing-c"
|
||||
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group" "tf_test_foo" {
|
||||
|
@ -1085,7 +1194,6 @@ resource "alicloud_security_group_rule" "ingress" {
|
|||
|
||||
resource "alicloud_instance" "foo" {
|
||||
# cn-beijing
|
||||
availability_zone = "cn-beijing-c"
|
||||
security_groups = ["${alicloud_security_group.tf_test_foo.id}"]
|
||||
|
||||
vswitch_id = "${alicloud_vswitch.foo.id}"
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
"github.com/denverdino/aliyungo/ecs"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"log"
|
||||
|
@ -71,7 +72,7 @@ func resourceAliyunNatGateway() *schema.Resource {
|
|||
func resourceAliyunNatGatewayCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AliyunClient).vpcconn
|
||||
|
||||
args := &CreateNatGatewayArgs{
|
||||
args := &ecs.CreateNatGatewayArgs{
|
||||
RegionId: getRegion(d, meta),
|
||||
VpcId: d.Get("vpc_id").(string),
|
||||
Spec: d.Get("spec").(string),
|
||||
|
@ -79,11 +80,11 @@ func resourceAliyunNatGatewayCreate(d *schema.ResourceData, meta interface{}) er
|
|||
|
||||
bandwidthPackages := d.Get("bandwidth_packages").([]interface{})
|
||||
|
||||
bandwidthPackageTypes := []BandwidthPackageType{}
|
||||
bandwidthPackageTypes := []ecs.BandwidthPackageType{}
|
||||
|
||||
for _, e := range bandwidthPackages {
|
||||
pack := e.(map[string]interface{})
|
||||
bandwidthPackage := BandwidthPackageType{
|
||||
bandwidthPackage := ecs.BandwidthPackageType{
|
||||
IpCount: pack["ip_count"].(int),
|
||||
Bandwidth: pack["bandwidth"].(int),
|
||||
}
|
||||
|
@ -106,8 +107,7 @@ func resourceAliyunNatGatewayCreate(d *schema.ResourceData, meta interface{}) er
|
|||
if v, ok := d.GetOk("description"); ok {
|
||||
args.Description = v.(string)
|
||||
}
|
||||
|
||||
resp, err := CreateNatGateway(conn, args)
|
||||
resp, err := conn.CreateNatGateway(args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("CreateNatGateway got error: %#v", err)
|
||||
}
|
||||
|
@ -142,6 +142,7 @@ func resourceAliyunNatGatewayRead(d *schema.ResourceData, meta interface{}) erro
|
|||
func resourceAliyunNatGatewayUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||
|
||||
client := meta.(*AliyunClient)
|
||||
conn := client.vpcconn
|
||||
|
||||
natGateway, err := client.DescribeNatGateway(d.Id())
|
||||
if err != nil {
|
||||
|
@ -150,7 +151,7 @@ func resourceAliyunNatGatewayUpdate(d *schema.ResourceData, meta interface{}) er
|
|||
|
||||
d.Partial(true)
|
||||
attributeUpdate := false
|
||||
args := &ModifyNatGatewayAttributeArgs{
|
||||
args := &ecs.ModifyNatGatewayAttributeArgs{
|
||||
RegionId: natGateway.RegionId,
|
||||
NatGatewayId: natGateway.NatGatewayId,
|
||||
}
|
||||
|
@ -183,28 +184,28 @@ func resourceAliyunNatGatewayUpdate(d *schema.ResourceData, meta interface{}) er
|
|||
}
|
||||
|
||||
if attributeUpdate {
|
||||
if err := ModifyNatGatewayAttribute(client.vpcconn, args); err != nil {
|
||||
if err := conn.ModifyNatGatewayAttribute(args); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange("spec") {
|
||||
d.SetPartial("spec")
|
||||
var spec NatGatewaySpec
|
||||
var spec ecs.NatGatewaySpec
|
||||
if v, ok := d.GetOk("spec"); ok {
|
||||
spec = NatGatewaySpec(v.(string))
|
||||
spec = ecs.NatGatewaySpec(v.(string))
|
||||
} else {
|
||||
// set default to small spec
|
||||
spec = NatGatewaySmallSpec
|
||||
spec = ecs.NatGatewaySmallSpec
|
||||
}
|
||||
|
||||
args := &ModifyNatGatewaySpecArgs{
|
||||
args := &ecs.ModifyNatGatewaySpecArgs{
|
||||
RegionId: natGateway.RegionId,
|
||||
NatGatewayId: natGateway.NatGatewayId,
|
||||
Spec: spec,
|
||||
}
|
||||
|
||||
err := ModifyNatGatewaySpec(client.vpcconn, args)
|
||||
err := conn.ModifyNatGatewaySpec(args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%#v %#v", err, *args)
|
||||
}
|
||||
|
@ -218,10 +219,11 @@ func resourceAliyunNatGatewayUpdate(d *schema.ResourceData, meta interface{}) er
|
|||
func resourceAliyunNatGatewayDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
|
||||
client := meta.(*AliyunClient)
|
||||
conn := client.vpcconn
|
||||
|
||||
return resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
|
||||
packages, err := DescribeBandwidthPackages(client.vpcconn, &DescribeBandwidthPackagesArgs{
|
||||
packages, err := conn.DescribeBandwidthPackages(&ecs.DescribeBandwidthPackagesArgs{
|
||||
RegionId: getRegion(d, meta),
|
||||
NatGatewayId: d.Id(),
|
||||
})
|
||||
|
@ -232,7 +234,7 @@ func resourceAliyunNatGatewayDelete(d *schema.ResourceData, meta interface{}) er
|
|||
|
||||
retry := false
|
||||
for _, pack := range packages {
|
||||
err = DeleteBandwidthPackage(client.vpcconn, &DeleteBandwidthPackageArgs{
|
||||
err = conn.DeleteBandwidthPackage(&ecs.DeleteBandwidthPackageArgs{
|
||||
RegionId: getRegion(d, meta),
|
||||
BandwidthPackageId: pack.BandwidthPackageId,
|
||||
})
|
||||
|
@ -251,12 +253,12 @@ func resourceAliyunNatGatewayDelete(d *schema.ResourceData, meta interface{}) er
|
|||
return resource.RetryableError(fmt.Errorf("Bandwidth package in use - trying again while it is deleted."))
|
||||
}
|
||||
|
||||
args := &DeleteNatGatewayArgs{
|
||||
args := &ecs.DeleteNatGatewayArgs{
|
||||
RegionId: client.Region,
|
||||
NatGatewayId: d.Id(),
|
||||
}
|
||||
|
||||
err = DeleteNatGateway(client.vpcconn, args)
|
||||
err = conn.DeleteNatGateway(args)
|
||||
if err != nil {
|
||||
er, _ := err.(*common.Error)
|
||||
if er.ErrorResponse.Code == DependencyViolationBandwidthPackages {
|
||||
|
@ -264,11 +266,11 @@ func resourceAliyunNatGatewayDelete(d *schema.ResourceData, meta interface{}) er
|
|||
}
|
||||
}
|
||||
|
||||
describeArgs := &DescribeNatGatewaysArgs{
|
||||
describeArgs := &ecs.DescribeNatGatewaysArgs{
|
||||
RegionId: client.Region,
|
||||
NatGatewayId: d.Id(),
|
||||
}
|
||||
gw, _, gwErr := DescribeNatGateways(client.vpcconn, describeArgs)
|
||||
gw, _, gwErr := conn.DescribeNatGateways(describeArgs)
|
||||
|
||||
if gwErr != nil {
|
||||
log.Printf("[ERROR] Describe NatGateways failed.")
|
||||
|
|
|
@ -3,13 +3,14 @@ package alicloud
|
|||
import (
|
||||
"fmt"
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
"github.com/denverdino/aliyungo/ecs"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAccAlicloudNatGateway_basic(t *testing.T) {
|
||||
var nat NatGatewaySetType
|
||||
var nat ecs.NatGatewaySetType
|
||||
|
||||
testCheck := func(*terraform.State) error {
|
||||
if nat.BusinessStatus != "Normal" {
|
||||
|
@ -55,7 +56,7 @@ func TestAccAlicloudNatGateway_basic(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAccAlicloudNatGateway_spec(t *testing.T) {
|
||||
var nat NatGatewaySetType
|
||||
var nat ecs.NatGatewaySetType
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() {
|
||||
|
@ -95,7 +96,7 @@ func TestAccAlicloudNatGateway_spec(t *testing.T) {
|
|||
|
||||
}
|
||||
|
||||
func testAccCheckNatGatewayExists(n string, nat *NatGatewaySetType) resource.TestCheckFunc {
|
||||
func testAccCheckNatGatewayExists(n string, nat *ecs.NatGatewaySetType) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[n]
|
||||
if !ok {
|
||||
|
@ -151,6 +152,10 @@ func testAccCheckNatGatewayDestroy(s *terraform.State) error {
|
|||
}
|
||||
|
||||
const testAccNatGatewayConfig = `
|
||||
data "alicloud_zones" "default" {
|
||||
"available_resource_creation"= "VSwitch"
|
||||
}
|
||||
|
||||
resource "alicloud_vpc" "foo" {
|
||||
name = "tf_test_foo"
|
||||
cidr_block = "172.16.0.0/12"
|
||||
|
@ -159,7 +164,7 @@ resource "alicloud_vpc" "foo" {
|
|||
resource "alicloud_vswitch" "foo" {
|
||||
vpc_id = "${alicloud_vpc.foo.id}"
|
||||
cidr_block = "172.16.0.0/21"
|
||||
availability_zone = "cn-beijing-b"
|
||||
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||
}
|
||||
|
||||
resource "alicloud_nat_gateway" "foo" {
|
||||
|
@ -169,11 +174,11 @@ resource "alicloud_nat_gateway" "foo" {
|
|||
bandwidth_packages = [{
|
||||
ip_count = 1
|
||||
bandwidth = 5
|
||||
zone = "cn-beijing-b"
|
||||
zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||
}, {
|
||||
ip_count = 2
|
||||
bandwidth = 10
|
||||
zone = "cn-beijing-b"
|
||||
zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||
}]
|
||||
depends_on = [
|
||||
"alicloud_vswitch.foo"]
|
||||
|
@ -181,6 +186,10 @@ resource "alicloud_nat_gateway" "foo" {
|
|||
`
|
||||
|
||||
const testAccNatGatewayConfigSpec = `
|
||||
data "alicloud_zones" "default" {
|
||||
"available_resource_creation"= "VSwitch"
|
||||
}
|
||||
|
||||
resource "alicloud_vpc" "foo" {
|
||||
name = "tf_test_foo"
|
||||
cidr_block = "172.16.0.0/12"
|
||||
|
@ -189,7 +198,7 @@ resource "alicloud_vpc" "foo" {
|
|||
resource "alicloud_vswitch" "foo" {
|
||||
vpc_id = "${alicloud_vpc.foo.id}"
|
||||
cidr_block = "172.16.0.0/21"
|
||||
availability_zone = "cn-beijing-b"
|
||||
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||
}
|
||||
|
||||
resource "alicloud_nat_gateway" "foo" {
|
||||
|
@ -199,11 +208,11 @@ resource "alicloud_nat_gateway" "foo" {
|
|||
bandwidth_packages = [{
|
||||
ip_count = 1
|
||||
bandwidth = 5
|
||||
zone = "cn-beijing-b"
|
||||
zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||
}, {
|
||||
ip_count = 2
|
||||
bandwidth = 10
|
||||
zone = "cn-beijing-b"
|
||||
zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||
}]
|
||||
depends_on = [
|
||||
"alicloud_vswitch.foo"]
|
||||
|
@ -211,6 +220,10 @@ resource "alicloud_nat_gateway" "foo" {
|
|||
`
|
||||
|
||||
const testAccNatGatewayConfigSpecUpgrade = `
|
||||
data "alicloud_zones" "default" {
|
||||
"available_resource_creation"= "VSwitch"
|
||||
}
|
||||
|
||||
resource "alicloud_vpc" "foo" {
|
||||
name = "tf_test_foo"
|
||||
cidr_block = "172.16.0.0/12"
|
||||
|
@ -219,7 +232,7 @@ resource "alicloud_vpc" "foo" {
|
|||
resource "alicloud_vswitch" "foo" {
|
||||
vpc_id = "${alicloud_vpc.foo.id}"
|
||||
cidr_block = "172.16.0.0/21"
|
||||
availability_zone = "cn-beijing-b"
|
||||
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||
}
|
||||
|
||||
resource "alicloud_nat_gateway" "foo" {
|
||||
|
@ -229,11 +242,11 @@ resource "alicloud_nat_gateway" "foo" {
|
|||
bandwidth_packages = [{
|
||||
ip_count = 1
|
||||
bandwidth = 5
|
||||
zone = "cn-beijing-b"
|
||||
zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||
}, {
|
||||
ip_count = 2
|
||||
bandwidth = 10
|
||||
zone = "cn-beijing-b"
|
||||
zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||
}]
|
||||
depends_on = [
|
||||
"alicloud_vswitch.foo"]
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"github.com/denverdino/aliyungo/common"
|
||||
"github.com/denverdino/aliyungo/ecs"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"time"
|
||||
)
|
||||
|
@ -145,6 +144,7 @@ func resourceAliyunSecurityGroupDelete(d *schema.ResourceData, meta interface{})
|
|||
|
||||
return resource.RetryableError(fmt.Errorf("Security group in use - trying again while it is deleted."))
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func buildAliyunSecurityGroupArgs(d *schema.ResourceData, meta interface{}) (*ecs.CreateSecurityGroupArgs, error) {
|
||||
|
|
|
@ -34,6 +34,7 @@ func resourceAliyunSecurityGroupRule() *schema.Resource {
|
|||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Computed: true,
|
||||
ValidateFunc: validateSecurityRuleNicType,
|
||||
},
|
||||
|
||||
|
@ -67,7 +68,6 @@ func resourceAliyunSecurityGroupRule() *schema.Resource {
|
|||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Default: "0.0.0.0/0",
|
||||
},
|
||||
|
||||
"source_security_group_id": &schema.Schema{
|
||||
|
@ -86,15 +86,17 @@ func resourceAliyunSecurityGroupRule() *schema.Resource {
|
|||
}
|
||||
|
||||
func resourceAliyunSecurityGroupRuleCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AliyunClient).ecsconn
|
||||
client := meta.(*AliyunClient)
|
||||
conn := client.ecsconn
|
||||
|
||||
ruleType := d.Get("type").(string)
|
||||
direction := d.Get("type").(string)
|
||||
sgId := d.Get("security_group_id").(string)
|
||||
ptl := d.Get("ip_protocol").(string)
|
||||
port := d.Get("port_range").(string)
|
||||
nicType := d.Get("nic_type").(string)
|
||||
|
||||
var autherr error
|
||||
switch GroupRuleDirection(ruleType) {
|
||||
switch GroupRuleDirection(direction) {
|
||||
case GroupRuleIngress:
|
||||
args, err := buildAliyunSecurityIngressArgs(d, meta)
|
||||
if err != nil {
|
||||
|
@ -114,10 +116,11 @@ func resourceAliyunSecurityGroupRuleCreate(d *schema.ResourceData, meta interfac
|
|||
if autherr != nil {
|
||||
return fmt.Errorf(
|
||||
"Error authorizing security group rule type %s: %s",
|
||||
ruleType, autherr)
|
||||
direction, autherr)
|
||||
}
|
||||
|
||||
d.SetId(sgId + ":" + ruleType + ":" + ptl + ":" + port)
|
||||
d.SetId(sgId + ":" + direction + ":" + ptl + ":" + port + ":" + nicType)
|
||||
|
||||
return resourceAliyunSecurityGroupRuleRead(d, meta)
|
||||
}
|
||||
|
||||
|
@ -125,10 +128,11 @@ func resourceAliyunSecurityGroupRuleRead(d *schema.ResourceData, meta interface{
|
|||
client := meta.(*AliyunClient)
|
||||
parts := strings.Split(d.Id(), ":")
|
||||
sgId := parts[0]
|
||||
types := parts[1]
|
||||
direction := parts[1]
|
||||
ip_protocol := parts[2]
|
||||
port_range := parts[3]
|
||||
rule, err := client.DescribeSecurityGroupRule(sgId, types, ip_protocol, port_range)
|
||||
nic_type := parts[4]
|
||||
rule, err := client.DescribeSecurityGroupRule(sgId, direction, nic_type, ip_protocol, port_range)
|
||||
|
||||
if err != nil {
|
||||
if notFoundError(err) {
|
||||
|
@ -137,7 +141,7 @@ func resourceAliyunSecurityGroupRuleRead(d *schema.ResourceData, meta interface{
|
|||
}
|
||||
return fmt.Errorf("Error SecurityGroup rule: %#v", err)
|
||||
}
|
||||
log.Printf("[WARN]sg %s, type %s, protocol %s, port %s, rule %#v", sgId, types, ip_protocol, port_range, rule)
|
||||
log.Printf("[WARN]sg %s, type %s, protocol %s, port %s, rule %#v", sgId, direction, ip_protocol, port_range, rule)
|
||||
d.Set("type", rule.Direction)
|
||||
d.Set("ip_protocol", strings.ToLower(string(rule.IpProtocol)))
|
||||
d.Set("nic_type", rule.NicType)
|
||||
|
@ -146,7 +150,7 @@ func resourceAliyunSecurityGroupRuleRead(d *schema.ResourceData, meta interface{
|
|||
d.Set("priority", rule.Priority)
|
||||
d.Set("security_group_id", sgId)
|
||||
//support source and desc by type
|
||||
if GroupRuleDirection(types) == GroupRuleIngress {
|
||||
if GroupRuleDirection(direction) == GroupRuleIngress {
|
||||
d.Set("cidr_ip", rule.SourceCidrIp)
|
||||
d.Set("source_security_group_id", rule.SourceGroupId)
|
||||
d.Set("source_group_owner_account", rule.SourceGroupOwnerAccount)
|
||||
|
@ -161,8 +165,10 @@ func resourceAliyunSecurityGroupRuleRead(d *schema.ResourceData, meta interface{
|
|||
|
||||
func resourceAliyunSecurityGroupRuleDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
client := meta.(*AliyunClient)
|
||||
args, err := buildAliyunSecurityIngressArgs(d, meta)
|
||||
ruleType := d.Get("type").(string)
|
||||
|
||||
if GroupRuleDirection(ruleType) == GroupRuleIngress {
|
||||
args, err := buildAliyunSecurityIngressArgs(d, meta)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -172,6 +178,28 @@ func resourceAliyunSecurityGroupRuleDelete(d *schema.ResourceData, meta interfac
|
|||
return client.RevokeSecurityGroup(revokeArgs)
|
||||
}
|
||||
|
||||
args, err := buildAliyunSecurityEgressArgs(d, meta)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
revokeArgs := &ecs.RevokeSecurityGroupEgressArgs{
|
||||
AuthorizeSecurityGroupEgressArgs: *args,
|
||||
}
|
||||
return client.RevokeSecurityGroupEgress(revokeArgs)
|
||||
|
||||
}
|
||||
|
||||
func checkCidrAndSourceGroupId(cidrIp, sourceGroupId string) error {
|
||||
if cidrIp == "" && sourceGroupId == "" {
|
||||
return fmt.Errorf("Either cidr_ip or source_security_group_id is required.")
|
||||
}
|
||||
|
||||
if cidrIp != "" && sourceGroupId != "" {
|
||||
return fmt.Errorf("You should set only one value of cidr_ip or source_security_group_id.")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func buildAliyunSecurityIngressArgs(d *schema.ResourceData, meta interface{}) (*ecs.AuthorizeSecurityGroupArgs, error) {
|
||||
conn := meta.(*AliyunClient).ecsconn
|
||||
|
||||
|
@ -199,12 +227,17 @@ func buildAliyunSecurityIngressArgs(d *schema.ResourceData, meta interface{}) (*
|
|||
args.NicType = ecs.NicType(v)
|
||||
}
|
||||
|
||||
if v := d.Get("cidr_ip").(string); v != "" {
|
||||
args.SourceCidrIp = v
|
||||
cidrIp := d.Get("cidr_ip").(string)
|
||||
sourceGroupId := d.Get("source_security_group_id").(string)
|
||||
if err := checkCidrAndSourceGroupId(cidrIp, sourceGroupId); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cidrIp != "" {
|
||||
args.SourceCidrIp = cidrIp
|
||||
}
|
||||
|
||||
if v := d.Get("source_security_group_id").(string); v != "" {
|
||||
args.SourceGroupId = v
|
||||
if sourceGroupId != "" {
|
||||
args.SourceGroupId = sourceGroupId
|
||||
}
|
||||
|
||||
if v := d.Get("source_group_owner_account").(string); v != "" {
|
||||
|
@ -255,12 +288,17 @@ func buildAliyunSecurityEgressArgs(d *schema.ResourceData, meta interface{}) (*e
|
|||
args.NicType = ecs.NicType(v)
|
||||
}
|
||||
|
||||
if v := d.Get("cidr_ip").(string); v != "" {
|
||||
args.DestCidrIp = v
|
||||
cidrIp := d.Get("cidr_ip").(string)
|
||||
sourceGroupId := d.Get("source_security_group_id").(string)
|
||||
if err := checkCidrAndSourceGroupId(cidrIp, sourceGroupId); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cidrIp != "" {
|
||||
args.DestCidrIp = cidrIp
|
||||
}
|
||||
|
||||
if v := d.Get("source_security_group_id").(string); v != "" {
|
||||
args.DestGroupId = v
|
||||
if sourceGroupId != "" {
|
||||
args.DestGroupId = sourceGroupId
|
||||
}
|
||||
|
||||
if v := d.Get("source_group_owner_account").(string); v != "" {
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
"log"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
@ -81,6 +82,39 @@ func TestAccAlicloudSecurityGroupRule_Egress(t *testing.T) {
|
|||
|
||||
}
|
||||
|
||||
func TestAccAlicloudSecurityGroupRule_EgressDefaultNicType(t *testing.T) {
|
||||
var pt ecs.PermissionType
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() {
|
||||
testAccPreCheck(t)
|
||||
},
|
||||
|
||||
// module name
|
||||
IDRefreshName: "alicloud_security_group_rule.egress",
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckSecurityGroupRuleDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccSecurityGroupRuleEgress_emptyNicType,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckSecurityGroupRuleExists(
|
||||
"alicloud_security_group_rule.egress", &pt),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_security_group_rule.egress",
|
||||
"port_range",
|
||||
"80/80"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_security_group_rule.egress",
|
||||
"nic_type",
|
||||
"internet"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestAccAlicloudSecurityGroupRule_Vpc_Ingress(t *testing.T) {
|
||||
var pt ecs.PermissionType
|
||||
|
||||
|
@ -114,6 +148,80 @@ func TestAccAlicloudSecurityGroupRule_Vpc_Ingress(t *testing.T) {
|
|||
|
||||
}
|
||||
|
||||
func TestAccAlicloudSecurityGroupRule_MissParameterSourceCidrIp(t *testing.T) {
|
||||
var pt ecs.PermissionType
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() {
|
||||
testAccPreCheck(t)
|
||||
},
|
||||
|
||||
// module name
|
||||
IDRefreshName: "alicloud_security_group_rule.egress",
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckSecurityGroupRuleDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccSecurityGroupRule_missingSourceCidrIp,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckSecurityGroupRuleExists(
|
||||
"alicloud_security_group_rule.egress", &pt),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_security_group_rule.egress",
|
||||
"port_range",
|
||||
"80/80"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_security_group_rule.egress",
|
||||
"nic_type",
|
||||
"internet"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_security_group_rule.egress",
|
||||
"ip_protocol",
|
||||
"udp"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestAccAlicloudSecurityGroupRule_SourceSecurityGroup(t *testing.T) {
|
||||
var pt ecs.PermissionType
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() {
|
||||
testAccPreCheck(t)
|
||||
},
|
||||
|
||||
// module name
|
||||
IDRefreshName: "alicloud_security_group_rule.ingress",
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckSecurityGroupRuleDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccSecurityGroupRuleSourceSecurityGroup,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckSecurityGroupRuleExists(
|
||||
"alicloud_security_group_rule.ingress", &pt),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_security_group_rule.ingress",
|
||||
"port_range",
|
||||
"3306/3306"),
|
||||
resource.TestMatchResourceAttr(
|
||||
"alicloud_security_group_rule.ingress",
|
||||
"source_security_group_id",
|
||||
regexp.MustCompile("^sg-[a-zA-Z0-9_]+")),
|
||||
resource.TestCheckResourceAttr(
|
||||
"alicloud_security_group_rule.ingress",
|
||||
"cidr_ip",
|
||||
""),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func testAccCheckSecurityGroupRuleExists(n string, m *ecs.PermissionType) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[n]
|
||||
|
@ -128,7 +236,8 @@ func testAccCheckSecurityGroupRuleExists(n string, m *ecs.PermissionType) resour
|
|||
client := testAccProvider.Meta().(*AliyunClient)
|
||||
log.Printf("[WARN]get sg rule %s", rs.Primary.ID)
|
||||
parts := strings.Split(rs.Primary.ID, ":")
|
||||
rule, err := client.DescribeSecurityGroupRule(parts[0], parts[1], parts[2], parts[3])
|
||||
// securityGroupId, direction, nicType, ipProtocol, portRange
|
||||
rule, err := client.DescribeSecurityGroupRule(parts[0], parts[1], parts[4], parts[2], parts[3])
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -152,7 +261,7 @@ func testAccCheckSecurityGroupRuleDestroy(s *terraform.State) error {
|
|||
}
|
||||
|
||||
parts := strings.Split(rs.Primary.ID, ":")
|
||||
rule, err := client.DescribeSecurityGroupRule(parts[0], parts[1], parts[2], parts[3])
|
||||
rule, err := client.DescribeSecurityGroupRule(parts[0], parts[1], parts[4], parts[2], parts[3])
|
||||
|
||||
if rule != nil {
|
||||
return fmt.Errorf("Error SecurityGroup Rule still exist")
|
||||
|
@ -210,6 +319,23 @@ resource "alicloud_security_group_rule" "egress" {
|
|||
|
||||
`
|
||||
|
||||
const testAccSecurityGroupRuleEgress_emptyNicType = `
|
||||
resource "alicloud_security_group" "foo" {
|
||||
name = "sg_foo"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "egress" {
|
||||
type = "egress"
|
||||
ip_protocol = "udp"
|
||||
policy = "accept"
|
||||
port_range = "80/80"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.foo.id}"
|
||||
cidr_ip = "10.159.6.18/12"
|
||||
}
|
||||
|
||||
`
|
||||
|
||||
const testAccSecurityGroupRuleVpcIngress = `
|
||||
resource "alicloud_security_group" "foo" {
|
||||
vpc_id = "${alicloud_vpc.vpc.id}"
|
||||
|
@ -231,6 +357,22 @@ resource "alicloud_security_group_rule" "ingress" {
|
|||
cidr_ip = "10.159.6.18/12"
|
||||
}
|
||||
|
||||
`
|
||||
const testAccSecurityGroupRule_missingSourceCidrIp = `
|
||||
resource "alicloud_security_group" "foo" {
|
||||
name = "sg_foo"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "egress" {
|
||||
security_group_id = "${alicloud_security_group.foo.id}"
|
||||
type = "egress"
|
||||
cidr_ip= "0.0.0.0/0"
|
||||
policy = "accept"
|
||||
ip_protocol= "udp"
|
||||
port_range= "80/80"
|
||||
priority= 1
|
||||
}
|
||||
|
||||
`
|
||||
|
||||
const testAccSecurityGroupRuleMultiIngress = `
|
||||
|
@ -260,4 +402,27 @@ resource "alicloud_security_group_rule" "ingress2" {
|
|||
cidr_ip = "127.0.1.18/16"
|
||||
}
|
||||
|
||||
`
|
||||
|
||||
const testAccSecurityGroupRuleSourceSecurityGroup = `
|
||||
resource "alicloud_security_group" "foo" {
|
||||
name = "sg_foo"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group" "bar" {
|
||||
name = "sg_bar"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "ingress" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "intranet"
|
||||
policy = "accept"
|
||||
port_range = "3306/3306"
|
||||
priority = 50
|
||||
security_group_id = "${alicloud_security_group.bar.id}"
|
||||
source_security_group_id = "${alicloud_security_group.foo.id}"
|
||||
}
|
||||
|
||||
|
||||
`
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"errors"
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
"github.com/denverdino/aliyungo/slb"
|
||||
"github.com/hashicorp/terraform/helper/hashcode"
|
||||
|
@ -83,40 +84,124 @@ func resourceAliyunSlb() *schema.Resource {
|
|||
ValidateFunc: validateSlbListenerBandwidth,
|
||||
Required: true,
|
||||
},
|
||||
//http
|
||||
"scheduler": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
ValidateFunc: validateSlbListenerScheduler,
|
||||
Optional: true,
|
||||
Default: "wrr",
|
||||
Default: slb.WRRScheduler,
|
||||
},
|
||||
|
||||
//http & https
|
||||
"sticky_session": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
ValidateFunc: validateSlbListenerStickySession,
|
||||
ValidateFunc: validateAllowedStringValue([]string{
|
||||
string(slb.OnFlag),
|
||||
string(slb.OffFlag)}),
|
||||
Optional: true,
|
||||
Default: slb.OffFlag,
|
||||
},
|
||||
//http & https
|
||||
"sticky_session_type": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
ValidateFunc: validateSlbListenerStickySessionType,
|
||||
ValidateFunc: validateAllowedStringValue([]string{
|
||||
string(slb.InsertStickySessionType),
|
||||
string(slb.ServerStickySessionType)}),
|
||||
Optional: true,
|
||||
},
|
||||
//http & https
|
||||
"cookie_timeout": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
ValidateFunc: validateSlbListenerCookieTimeout,
|
||||
Optional: true,
|
||||
},
|
||||
//http & https
|
||||
"cookie": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
ValidateFunc: validateSlbListenerCookie,
|
||||
Optional: true,
|
||||
},
|
||||
"PersistenceTimeout": &schema.Schema{
|
||||
//tcp & udp
|
||||
"persistence_timeout": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
ValidateFunc: validateSlbListenerPersistenceTimeout,
|
||||
Optional: true,
|
||||
Default: 0,
|
||||
},
|
||||
//http & https
|
||||
"health_check": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
ValidateFunc: validateAllowedStringValue([]string{
|
||||
string(slb.OnFlag),
|
||||
string(slb.OffFlag)}),
|
||||
Optional: true,
|
||||
Default: slb.OffFlag,
|
||||
},
|
||||
//tcp
|
||||
"health_check_type": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
ValidateFunc: validateAllowedStringValue([]string{
|
||||
string(slb.TCPHealthCheckType),
|
||||
string(slb.HTTPHealthCheckType)}),
|
||||
Optional: true,
|
||||
Default: slb.TCPHealthCheckType,
|
||||
},
|
||||
//http & https & tcp
|
||||
"health_check_domain": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
ValidateFunc: validateSlbListenerHealthCheckDomain,
|
||||
Optional: true,
|
||||
},
|
||||
//http & https & tcp
|
||||
"health_check_uri": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
ValidateFunc: validateSlbListenerHealthCheckUri,
|
||||
Optional: true,
|
||||
},
|
||||
"health_check_connect_port": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
ValidateFunc: validateSlbListenerHealthCheckConnectPort,
|
||||
Optional: true,
|
||||
},
|
||||
"healthy_threshold": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
ValidateFunc: validateIntegerInRange(1, 10),
|
||||
Optional: true,
|
||||
},
|
||||
"unhealthy_threshold": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
ValidateFunc: validateIntegerInRange(1, 10),
|
||||
Optional: true,
|
||||
},
|
||||
|
||||
"health_check_timeout": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
ValidateFunc: validateIntegerInRange(1, 50),
|
||||
Optional: true,
|
||||
},
|
||||
"health_check_interval": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
ValidateFunc: validateIntegerInRange(1, 5),
|
||||
Optional: true,
|
||||
},
|
||||
//http & https & tcp
|
||||
"health_check_http_code": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
ValidateFunc: validateAllowedSplitStringValue([]string{
|
||||
string(slb.HTTP_2XX),
|
||||
string(slb.HTTP_3XX),
|
||||
string(slb.HTTP_4XX),
|
||||
string(slb.HTTP_5XX)}, ","),
|
||||
Optional: true,
|
||||
},
|
||||
//https
|
||||
"ssl_certificate_id": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
//https
|
||||
//"ca_certificate_id": &schema.Schema{
|
||||
// Type: schema.TypeString,
|
||||
// Optional: true,
|
||||
//},
|
||||
},
|
||||
},
|
||||
Set: resourceAliyunSlbListenerHash,
|
||||
|
@ -349,44 +434,53 @@ func resourceAliyunSlbListenerHash(v interface{}) int {
|
|||
}
|
||||
|
||||
func createListener(conn *slb.Client, loadBalancerId string, listener *Listener) error {
|
||||
|
||||
errTypeJudge := func(err error) error {
|
||||
if err != nil {
|
||||
if listenerType, ok := err.(*ListenerErr); ok {
|
||||
if listenerType.ErrType == HealthCheckErrType {
|
||||
return fmt.Errorf("When the HealthCheck is %s, then related HealthCheck parameter "+
|
||||
"must have.", slb.OnFlag)
|
||||
} else if listenerType.ErrType == StickySessionErrType {
|
||||
return fmt.Errorf("When the StickySession is %s, then StickySessionType parameter "+
|
||||
"must have.", slb.OnFlag)
|
||||
} else if listenerType.ErrType == CookieTimeOutErrType {
|
||||
return fmt.Errorf("When the StickySession is %s and StickySessionType is %s, "+
|
||||
"then CookieTimeout parameter must have.", slb.OnFlag, slb.InsertStickySessionType)
|
||||
} else if listenerType.ErrType == CookieErrType {
|
||||
return fmt.Errorf("When the StickySession is %s and StickySessionType is %s, "+
|
||||
"then Cookie parameter must have.", slb.OnFlag, slb.ServerStickySessionType)
|
||||
}
|
||||
return fmt.Errorf("slb listener check errtype not found.")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if listener.Protocol == strings.ToLower("tcp") {
|
||||
args := &slb.CreateLoadBalancerTCPListenerArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
ListenerPort: listener.LoadBalancerPort,
|
||||
BackendServerPort: listener.InstancePort,
|
||||
Bandwidth: listener.Bandwidth,
|
||||
}
|
||||
if err := conn.CreateLoadBalancerTCPListener(args); err != nil {
|
||||
|
||||
args := getTcpListenerArgs(loadBalancerId, listener)
|
||||
|
||||
if err := conn.CreateLoadBalancerTCPListener(&args); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if listener.Protocol == strings.ToLower("http") {
|
||||
args, argsErr := getHttpListenerArgs(loadBalancerId, listener)
|
||||
if paramErr := errTypeJudge(argsErr); paramErr != nil {
|
||||
return paramErr
|
||||
}
|
||||
|
||||
if listener.Protocol == strings.ToLower("http") {
|
||||
args := &slb.CreateLoadBalancerHTTPListenerArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
ListenerPort: listener.LoadBalancerPort,
|
||||
BackendServerPort: listener.InstancePort,
|
||||
Bandwidth: listener.Bandwidth,
|
||||
StickySession: slb.OffFlag,
|
||||
HealthCheck: slb.OffFlag,
|
||||
}
|
||||
|
||||
if err := conn.CreateLoadBalancerHTTPListener(args); err != nil {
|
||||
if err := conn.CreateLoadBalancerHTTPListener(&args); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if listener.Protocol == strings.ToLower("https") {
|
||||
listenerType, err := getHttpListenerType(loadBalancerId, listener)
|
||||
if paramErr := errTypeJudge(err); paramErr != nil {
|
||||
return paramErr
|
||||
}
|
||||
|
||||
if listener.Protocol == strings.ToLower("https") {
|
||||
args := &slb.CreateLoadBalancerHTTPSListenerArgs{
|
||||
|
||||
HTTPListenerType: slb.HTTPListenerType{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
ListenerPort: listener.LoadBalancerPort,
|
||||
BackendServerPort: listener.InstancePort,
|
||||
Bandwidth: listener.Bandwidth,
|
||||
StickySession: slb.OffFlag,
|
||||
HealthCheck: slb.OffFlag,
|
||||
},
|
||||
HTTPListenerType: listenerType,
|
||||
}
|
||||
if listener.SSLCertificateId == "" {
|
||||
return fmt.Errorf("Server Certificated Id cann't be null")
|
||||
|
@ -397,17 +491,10 @@ func createListener(conn *slb.Client, loadBalancerId string, listener *Listener)
|
|||
if err := conn.CreateLoadBalancerHTTPSListener(args); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else if listener.Protocol == strings.ToLower("udp") {
|
||||
args := getUdpListenerArgs(loadBalancerId, listener)
|
||||
|
||||
if listener.Protocol == strings.ToLower("udp") {
|
||||
args := &slb.CreateLoadBalancerUDPListenerArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
ListenerPort: listener.LoadBalancerPort,
|
||||
BackendServerPort: listener.InstancePort,
|
||||
Bandwidth: listener.Bandwidth,
|
||||
}
|
||||
|
||||
if err := conn.CreateLoadBalancerUDPListener(args); err != nil {
|
||||
if err := conn.CreateLoadBalancerUDPListener(&args); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -418,3 +505,102 @@ func createListener(conn *slb.Client, loadBalancerId string, listener *Listener)
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getTcpListenerArgs(loadBalancerId string, listener *Listener) slb.CreateLoadBalancerTCPListenerArgs {
|
||||
args := slb.CreateLoadBalancerTCPListenerArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
ListenerPort: listener.LoadBalancerPort,
|
||||
BackendServerPort: listener.InstancePort,
|
||||
Bandwidth: listener.Bandwidth,
|
||||
Scheduler: listener.Scheduler,
|
||||
PersistenceTimeout: listener.PersistenceTimeout,
|
||||
HealthCheckType: listener.HealthCheckType,
|
||||
HealthCheckDomain: listener.HealthCheckDomain,
|
||||
HealthCheckURI: listener.HealthCheckURI,
|
||||
HealthCheckConnectPort: listener.HealthCheckConnectPort,
|
||||
HealthyThreshold: listener.HealthyThreshold,
|
||||
UnhealthyThreshold: listener.UnhealthyThreshold,
|
||||
HealthCheckConnectTimeout: listener.HealthCheckTimeout,
|
||||
HealthCheckInterval: listener.HealthCheckInterval,
|
||||
HealthCheckHttpCode: listener.HealthCheckHttpCode,
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
func getUdpListenerArgs(loadBalancerId string, listener *Listener) slb.CreateLoadBalancerUDPListenerArgs {
|
||||
args := slb.CreateLoadBalancerUDPListenerArgs{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
ListenerPort: listener.LoadBalancerPort,
|
||||
BackendServerPort: listener.InstancePort,
|
||||
Bandwidth: listener.Bandwidth,
|
||||
PersistenceTimeout: listener.PersistenceTimeout,
|
||||
HealthCheckConnectTimeout: listener.HealthCheckTimeout,
|
||||
HealthCheckInterval: listener.HealthCheckInterval,
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
func getHttpListenerType(loadBalancerId string, listener *Listener) (listenType slb.HTTPListenerType, err error) {
|
||||
|
||||
if listener.HealthCheck == slb.OnFlag {
|
||||
if listener.HealthCheckURI == "" || listener.HealthCheckDomain == "" || listener.HealthCheckConnectPort == 0 ||
|
||||
listener.HealthyThreshold == 0 || listener.UnhealthyThreshold == 0 || listener.HealthCheckTimeout == 0 ||
|
||||
listener.HealthCheckHttpCode == "" || listener.HealthCheckInterval == 0 {
|
||||
|
||||
errMsg := errors.New("err: HealthCheck empty.")
|
||||
return listenType, &ListenerErr{HealthCheckErrType, errMsg}
|
||||
}
|
||||
}
|
||||
|
||||
if listener.StickySession == slb.OnFlag {
|
||||
if listener.StickySessionType == "" {
|
||||
errMsg := errors.New("err: stickySession empty.")
|
||||
return listenType, &ListenerErr{StickySessionErrType, errMsg}
|
||||
}
|
||||
|
||||
if listener.StickySessionType == slb.InsertStickySessionType {
|
||||
if listener.CookieTimeout == 0 {
|
||||
errMsg := errors.New("err: cookieTimeout empty.")
|
||||
return listenType, &ListenerErr{CookieTimeOutErrType, errMsg}
|
||||
}
|
||||
} else if listener.StickySessionType == slb.ServerStickySessionType {
|
||||
if listener.Cookie == "" {
|
||||
errMsg := errors.New("err: cookie empty.")
|
||||
return listenType, &ListenerErr{CookieErrType, errMsg}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
httpListenertType := slb.HTTPListenerType{
|
||||
LoadBalancerId: loadBalancerId,
|
||||
ListenerPort: listener.LoadBalancerPort,
|
||||
BackendServerPort: listener.InstancePort,
|
||||
Bandwidth: listener.Bandwidth,
|
||||
Scheduler: listener.Scheduler,
|
||||
HealthCheck: listener.HealthCheck,
|
||||
StickySession: listener.StickySession,
|
||||
StickySessionType: listener.StickySessionType,
|
||||
CookieTimeout: listener.CookieTimeout,
|
||||
Cookie: listener.Cookie,
|
||||
HealthCheckDomain: listener.HealthCheckDomain,
|
||||
HealthCheckURI: listener.HealthCheckURI,
|
||||
HealthCheckConnectPort: listener.HealthCheckConnectPort,
|
||||
HealthyThreshold: listener.HealthyThreshold,
|
||||
UnhealthyThreshold: listener.UnhealthyThreshold,
|
||||
HealthCheckTimeout: listener.HealthCheckTimeout,
|
||||
HealthCheckInterval: listener.HealthCheckInterval,
|
||||
HealthCheckHttpCode: listener.HealthCheckHttpCode,
|
||||
}
|
||||
|
||||
return httpListenertType, err
|
||||
}
|
||||
|
||||
func getHttpListenerArgs(loadBalancerId string, listener *Listener) (listenType slb.CreateLoadBalancerHTTPListenerArgs, err error) {
|
||||
httpListenerType, err := getHttpListenerType(loadBalancerId, listener)
|
||||
if err != nil {
|
||||
return listenType, err
|
||||
}
|
||||
|
||||
httpArgs := slb.CreateLoadBalancerHTTPListenerArgs(httpListenerType)
|
||||
return httpArgs, err
|
||||
}
|
||||
|
|
|
@ -79,9 +79,30 @@ resource "alicloud_security_group" "foo" {
|
|||
description = "foo"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "http-in" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "internet"
|
||||
policy = "accept"
|
||||
port_range = "80/80"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.foo.id}"
|
||||
cidr_ip = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "ssh-in" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "internet"
|
||||
policy = "accept"
|
||||
port_range = "22/22"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.foo.id}"
|
||||
cidr_ip = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
resource "alicloud_instance" "foo" {
|
||||
# cn-beijing
|
||||
availability_zone = "cn-beijing-b"
|
||||
image_id = "ubuntu_140405_64_40G_cloudinit_20161115.vhd"
|
||||
|
||||
# series II
|
||||
|
|
|
@ -85,7 +85,7 @@ func TestAccAlicloudSlb_listener(t *testing.T) {
|
|||
testListener := func() resource.TestCheckFunc {
|
||||
return func(*terraform.State) error {
|
||||
listenerPorts := slb.ListenerPorts.ListenerPort[0]
|
||||
if listenerPorts != 161 {
|
||||
if listenerPorts != 2001 {
|
||||
return fmt.Errorf("bad loadbalancer listener: %#v", listenerPorts)
|
||||
}
|
||||
|
||||
|
@ -260,21 +260,49 @@ resource "alicloud_slb" "listener" {
|
|||
"lb_port" = "21"
|
||||
"lb_protocol" = "tcp"
|
||||
"bandwidth" = 1
|
||||
"persistence_timeout" = 500
|
||||
"health_check_type" = "http"
|
||||
},{
|
||||
"instance_port" = "8000"
|
||||
"lb_port" = "80"
|
||||
"lb_protocol" = "http"
|
||||
"sticky_session" = "on"
|
||||
"sticky_session_type" = "insert"
|
||||
"cookie_timeout" = 800
|
||||
"bandwidth" = 1
|
||||
},{
|
||||
"instance_port" = "1611"
|
||||
"lb_port" = "161"
|
||||
"instance_port" = "8001"
|
||||
"lb_port" = "81"
|
||||
"lb_protocol" = "http"
|
||||
"sticky_session" = "on"
|
||||
"sticky_session_type" = "server"
|
||||
"cookie" = "testslblistenercookie"
|
||||
"cookie_timeout" = 1800
|
||||
"health_check" = "on"
|
||||
"health_check_domain" = "$_ip"
|
||||
"health_check_uri" = "/console"
|
||||
"health_check_connect_port" = 20
|
||||
"healthy_threshold" = 8
|
||||
"unhealthy_threshold" = 8
|
||||
"health_check_timeout" = 8
|
||||
"health_check_interval" = 4
|
||||
"health_check_http_code" = "http_2xx"
|
||||
"bandwidth" = 1
|
||||
},{
|
||||
"instance_port" = "2001"
|
||||
"lb_port" = "2001"
|
||||
"lb_protocol" = "udp"
|
||||
"bandwidth" = 1
|
||||
"persistence_timeout" = 700
|
||||
}]
|
||||
}
|
||||
`
|
||||
|
||||
const testAccSlb4Vpc = `
|
||||
data "alicloud_zones" "default" {
|
||||
"available_resource_creation"= "VSwitch"
|
||||
}
|
||||
|
||||
resource "alicloud_vpc" "foo" {
|
||||
name = "tf_test_foo"
|
||||
cidr_block = "172.16.0.0/12"
|
||||
|
@ -283,7 +311,7 @@ resource "alicloud_vpc" "foo" {
|
|||
resource "alicloud_vswitch" "foo" {
|
||||
vpc_id = "${alicloud_vpc.foo.id}"
|
||||
cidr_block = "172.16.0.0/21"
|
||||
availability_zone = "cn-beijing-b"
|
||||
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||
}
|
||||
|
||||
resource "alicloud_slb" "vpc" {
|
||||
|
|
|
@ -124,6 +124,10 @@ func testAccCheckRouteEntryDestroy(s *terraform.State) error {
|
|||
}
|
||||
|
||||
const testAccRouteEntryConfig = `
|
||||
data "alicloud_zones" "default" {
|
||||
"available_resource_creation"= "VSwitch"
|
||||
}
|
||||
|
||||
resource "alicloud_vpc" "foo" {
|
||||
name = "tf_test_foo"
|
||||
cidr_block = "10.1.0.0/21"
|
||||
|
@ -132,7 +136,7 @@ resource "alicloud_vpc" "foo" {
|
|||
resource "alicloud_vswitch" "foo" {
|
||||
vpc_id = "${alicloud_vpc.foo.id}"
|
||||
cidr_block = "10.1.1.0/24"
|
||||
availability_zone = "cn-beijing-c"
|
||||
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||
}
|
||||
|
||||
resource "alicloud_route_entry" "foo" {
|
||||
|
@ -162,7 +166,6 @@ resource "alicloud_security_group_rule" "ingress" {
|
|||
|
||||
resource "alicloud_instance" "foo" {
|
||||
# cn-beijing
|
||||
availability_zone = "cn-beijing-c"
|
||||
security_groups = ["${alicloud_security_group.tf_test_foo.id}"]
|
||||
|
||||
vswitch_id = "${alicloud_vswitch.foo.id}"
|
||||
|
|
|
@ -92,6 +92,10 @@ func testAccCheckVswitchDestroy(s *terraform.State) error {
|
|||
}
|
||||
|
||||
const testAccVswitchConfig = `
|
||||
data "alicloud_zones" "default" {
|
||||
"available_resource_creation"= "VSwitch"
|
||||
}
|
||||
|
||||
resource "alicloud_vpc" "foo" {
|
||||
name = "tf_test_foo"
|
||||
cidr_block = "172.16.0.0/12"
|
||||
|
@ -100,6 +104,6 @@ resource "alicloud_vpc" "foo" {
|
|||
resource "alicloud_vswitch" "foo" {
|
||||
vpc_id = "${alicloud_vpc.foo.id}"
|
||||
cidr_block = "172.16.0.0/21"
|
||||
availability_zone = "cn-beijing-b"
|
||||
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||
}
|
||||
`
|
||||
|
|
|
@ -84,6 +84,24 @@ func (client *AliyunClient) DescribeZone(zoneID string) (*ecs.ZoneType, error) {
|
|||
return zone, nil
|
||||
}
|
||||
|
||||
// return multiIZ list of current region
|
||||
func (client *AliyunClient) DescribeMultiIZByRegion() (izs []string, err error) {
|
||||
resp, err := client.rdsconn.DescribeRegions()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error to list regions not found")
|
||||
}
|
||||
regions := resp.Regions.RDSRegion
|
||||
|
||||
zoneIds := []string{}
|
||||
for _, r := range regions {
|
||||
if r.RegionId == string(client.Region) && strings.Contains(r.ZoneId, MULTI_IZ_SYMBOL) {
|
||||
zoneIds = append(zoneIds, r.ZoneId)
|
||||
}
|
||||
}
|
||||
|
||||
return zoneIds, nil
|
||||
}
|
||||
|
||||
func (client *AliyunClient) QueryInstancesByIds(ids []string) (instances []ecs.InstanceAttributesType, err error) {
|
||||
idsStr, jerr := json.Marshal(ids)
|
||||
if jerr != nil {
|
||||
|
@ -119,6 +137,23 @@ func (client *AliyunClient) QueryInstancesById(id string) (instance *ecs.Instanc
|
|||
return &instances[0], nil
|
||||
}
|
||||
|
||||
func (client *AliyunClient) QueryInstanceSystemDisk(id string) (disk *ecs.DiskItemType, err error) {
|
||||
args := ecs.DescribeDisksArgs{
|
||||
RegionId: client.Region,
|
||||
InstanceId: string(id),
|
||||
DiskType: ecs.DiskTypeAllSystem,
|
||||
}
|
||||
disks, _, err := client.ecsconn.DescribeDisks(&args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(disks) == 0 {
|
||||
return nil, common.GetClientErrorFromString(SystemDiskNotFound)
|
||||
}
|
||||
|
||||
return &disks[0], nil
|
||||
}
|
||||
|
||||
// ResourceAvailable check resource available for zone
|
||||
func (client *AliyunClient) ResourceAvailable(zone *ecs.ZoneType, resourceType ecs.ResourceType) error {
|
||||
available := false
|
||||
|
@ -186,15 +221,26 @@ func (client *AliyunClient) DescribeSecurity(securityGroupId string) (*ecs.Descr
|
|||
return client.ecsconn.DescribeSecurityGroupAttribute(args)
|
||||
}
|
||||
|
||||
func (client *AliyunClient) DescribeSecurityGroupRule(securityGroupId, types, ip_protocol, port_range string) (*ecs.PermissionType, error) {
|
||||
func (client *AliyunClient) DescribeSecurityByAttr(securityGroupId, direction, nicType string) (*ecs.DescribeSecurityGroupAttributeResponse, error) {
|
||||
|
||||
sg, err := client.DescribeSecurity(securityGroupId)
|
||||
args := &ecs.DescribeSecurityGroupAttributeArgs{
|
||||
RegionId: client.Region,
|
||||
SecurityGroupId: securityGroupId,
|
||||
Direction: direction,
|
||||
NicType: ecs.NicType(nicType),
|
||||
}
|
||||
|
||||
return client.ecsconn.DescribeSecurityGroupAttribute(args)
|
||||
}
|
||||
|
||||
func (client *AliyunClient) DescribeSecurityGroupRule(securityGroupId, direction, nicType, ipProtocol, portRange string) (*ecs.PermissionType, error) {
|
||||
sg, err := client.DescribeSecurityByAttr(securityGroupId, direction, nicType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, p := range sg.Permissions.Permission {
|
||||
if strings.ToLower(string(p.IpProtocol)) == ip_protocol && p.PortRange == port_range {
|
||||
if strings.ToLower(string(p.IpProtocol)) == ipProtocol && p.PortRange == portRange {
|
||||
return &p, nil
|
||||
}
|
||||
}
|
||||
|
@ -203,6 +249,11 @@ func (client *AliyunClient) DescribeSecurityGroupRule(securityGroupId, types, ip
|
|||
}
|
||||
|
||||
func (client *AliyunClient) RevokeSecurityGroup(args *ecs.RevokeSecurityGroupArgs) error {
|
||||
//todo: handle the specal err
|
||||
//when the rule is not exist, api will return success(200)
|
||||
return client.ecsconn.RevokeSecurityGroup(args)
|
||||
}
|
||||
|
||||
func (client *AliyunClient) RevokeSecurityGroupEgress(args *ecs.RevokeSecurityGroupEgressArgs) error {
|
||||
//when the rule is not exist, api will return success(200)
|
||||
return client.ecsconn.RevokeSecurityGroupEgress(args)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,278 @@
|
|||
package alicloud
|
||||
|
||||
import (
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
"github.com/denverdino/aliyungo/rds"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// when getInstance is empty, then throw InstanceNotfound error
|
||||
func (client *AliyunClient) DescribeDBInstanceById(id string) (instance *rds.DBInstanceAttribute, err error) {
|
||||
arrtArgs := rds.DescribeDBInstancesArgs{
|
||||
DBInstanceId: id,
|
||||
}
|
||||
resp, err := client.rdsconn.DescribeDBInstanceAttribute(&arrtArgs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
attr := resp.Items.DBInstanceAttribute
|
||||
|
||||
if len(attr) <= 0 {
|
||||
return nil, common.GetClientErrorFromString(InstanceNotfound)
|
||||
}
|
||||
|
||||
return &attr[0], nil
|
||||
}
|
||||
|
||||
func (client *AliyunClient) CreateAccountByInfo(instanceId, username, pwd string) error {
|
||||
conn := client.rdsconn
|
||||
args := rds.CreateAccountArgs{
|
||||
DBInstanceId: instanceId,
|
||||
AccountName: username,
|
||||
AccountPassword: pwd,
|
||||
}
|
||||
|
||||
if _, err := conn.CreateAccount(&args); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := conn.WaitForAccount(instanceId, username, rds.Available, 200); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (client *AliyunClient) CreateDatabaseByInfo(instanceId, dbName, charset, desp string) error {
|
||||
conn := client.rdsconn
|
||||
args := rds.CreateDatabaseArgs{
|
||||
DBInstanceId: instanceId,
|
||||
DBName: dbName,
|
||||
CharacterSetName: charset,
|
||||
DBDescription: desp,
|
||||
}
|
||||
_, err := conn.CreateDatabase(&args)
|
||||
return err
|
||||
}
|
||||
|
||||
func (client *AliyunClient) DescribeDatabaseByName(instanceId, dbName string) (ds []rds.Database, err error) {
|
||||
conn := client.rdsconn
|
||||
args := rds.DescribeDatabasesArgs{
|
||||
DBInstanceId: instanceId,
|
||||
DBName: dbName,
|
||||
}
|
||||
|
||||
resp, err := conn.DescribeDatabases(&args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp.Databases.Database, nil
|
||||
}
|
||||
|
||||
func (client *AliyunClient) GrantDBPrivilege2Account(instanceId, username, dbName string) error {
|
||||
conn := client.rdsconn
|
||||
pargs := rds.GrantAccountPrivilegeArgs{
|
||||
DBInstanceId: instanceId,
|
||||
AccountName: username,
|
||||
DBName: dbName,
|
||||
AccountPrivilege: rds.ReadWrite,
|
||||
}
|
||||
if _, err := conn.GrantAccountPrivilege(&pargs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := conn.WaitForAccountPrivilege(instanceId, username, dbName, rds.ReadWrite, 200); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (client *AliyunClient) AllocateDBPublicConnection(instanceId, port string) error {
|
||||
conn := client.rdsconn
|
||||
args := rds.AllocateInstancePublicConnectionArgs{
|
||||
DBInstanceId: instanceId,
|
||||
ConnectionStringPrefix: instanceId + "o",
|
||||
Port: port,
|
||||
}
|
||||
|
||||
if _, err := conn.AllocateInstancePublicConnection(&args); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := conn.WaitForPublicConnection(instanceId, 600); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (client *AliyunClient) ConfigDBBackup(instanceId, backupTime, backupPeriod string, retentionPeriod int) error {
|
||||
bargs := rds.BackupPolicy{
|
||||
PreferredBackupTime: backupTime,
|
||||
PreferredBackupPeriod: backupPeriod,
|
||||
BackupRetentionPeriod: retentionPeriod,
|
||||
}
|
||||
args := rds.ModifyBackupPolicyArgs{
|
||||
DBInstanceId: instanceId,
|
||||
BackupPolicy: bargs,
|
||||
}
|
||||
|
||||
if _, err := client.rdsconn.ModifyBackupPolicy(&args); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := client.rdsconn.WaitForInstance(instanceId, rds.Running, 600); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (client *AliyunClient) ModifyDBSecurityIps(instanceId, ips string) error {
|
||||
sargs := rds.DBInstanceIPArray{
|
||||
SecurityIps: ips,
|
||||
}
|
||||
|
||||
args := rds.ModifySecurityIpsArgs{
|
||||
DBInstanceId: instanceId,
|
||||
DBInstanceIPArray: sargs,
|
||||
}
|
||||
|
||||
if _, err := client.rdsconn.ModifySecurityIps(&args); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := client.rdsconn.WaitForInstance(instanceId, rds.Running, 600); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (client *AliyunClient) DescribeDBSecurityIps(instanceId string) (ips []rds.DBInstanceIPList, err error) {
|
||||
args := rds.DescribeDBInstanceIPsArgs{
|
||||
DBInstanceId: instanceId,
|
||||
}
|
||||
|
||||
resp, err := client.rdsconn.DescribeDBInstanceIPs(&args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.Items.DBInstanceIPArray, nil
|
||||
}
|
||||
|
||||
func (client *AliyunClient) GetSecurityIps(instanceId string) ([]string, error) {
|
||||
arr, err := client.DescribeDBSecurityIps(instanceId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ips := ""
|
||||
for i, ip := range arr {
|
||||
if i == 0 {
|
||||
ips += ip.SecurityIPList
|
||||
} else {
|
||||
ips += COMMA_SEPARATED + ip.SecurityIPList
|
||||
}
|
||||
}
|
||||
return strings.Split(ips, COMMA_SEPARATED), nil
|
||||
}
|
||||
|
||||
func (client *AliyunClient) ModifyDBClassStorage(instanceId, class, storage string) error {
|
||||
conn := client.rdsconn
|
||||
args := rds.ModifyDBInstanceSpecArgs{
|
||||
DBInstanceId: instanceId,
|
||||
PayType: rds.Postpaid,
|
||||
DBInstanceClass: class,
|
||||
DBInstanceStorage: storage,
|
||||
}
|
||||
|
||||
if _, err := conn.ModifyDBInstanceSpec(&args); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := conn.WaitForInstance(instanceId, rds.Running, 600); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// turn period to TimeType
|
||||
func TransformPeriod2Time(period int, chargeType string) (ut int, tt common.TimeType) {
|
||||
if chargeType == string(rds.Postpaid) {
|
||||
return 1, common.Day
|
||||
}
|
||||
|
||||
if period >= 1 && period <= 9 {
|
||||
return period, common.Month
|
||||
}
|
||||
|
||||
if period == 12 {
|
||||
return 1, common.Year
|
||||
}
|
||||
|
||||
if period == 24 {
|
||||
return 2, common.Year
|
||||
}
|
||||
return 0, common.Day
|
||||
|
||||
}
|
||||
|
||||
// turn TimeType to Period
|
||||
func TransformTime2Period(ut int, tt common.TimeType) (period int) {
|
||||
if tt == common.Year {
|
||||
return 12 * ut
|
||||
}
|
||||
|
||||
return ut
|
||||
|
||||
}
|
||||
|
||||
// Flattens an array of databases into a []map[string]interface{}
|
||||
func flattenDatabaseMappings(list []rds.Database) []map[string]interface{} {
|
||||
result := make([]map[string]interface{}, 0, len(list))
|
||||
for _, i := range list {
|
||||
l := map[string]interface{}{
|
||||
"db_name": i.DBName,
|
||||
"character_set_name": i.CharacterSetName,
|
||||
"db_description": i.DBDescription,
|
||||
}
|
||||
result = append(result, l)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func flattenDBBackup(list []rds.BackupPolicy) []map[string]interface{} {
|
||||
result := make([]map[string]interface{}, 0, len(list))
|
||||
for _, i := range list {
|
||||
l := map[string]interface{}{
|
||||
"preferred_backup_period": i.PreferredBackupPeriod,
|
||||
"preferred_backup_time": i.PreferredBackupTime,
|
||||
"backup_retention_period": i.LogBackupRetentionPeriod,
|
||||
}
|
||||
result = append(result, l)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func flattenDBSecurityIPs(list []rds.DBInstanceIPList) []map[string]interface{} {
|
||||
result := make([]map[string]interface{}, 0, len(list))
|
||||
for _, i := range list {
|
||||
l := map[string]interface{}{
|
||||
"security_ips": i.SecurityIPList,
|
||||
}
|
||||
result = append(result, l)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Flattens an array of databases connection into a []map[string]interface{}
|
||||
func flattenDBConnections(list []rds.DBInstanceNetInfo) []map[string]interface{} {
|
||||
result := make([]map[string]interface{}, 0, len(list))
|
||||
for _, i := range list {
|
||||
l := map[string]interface{}{
|
||||
"connection_string": i.ConnectionString,
|
||||
"ip_type": i.IPType,
|
||||
"ip_address": i.IPAddress,
|
||||
}
|
||||
result = append(result, l)
|
||||
}
|
||||
return result
|
||||
}
|
|
@ -24,14 +24,14 @@ func (client *AliyunClient) DescribeEipAddress(allocationId string) (*ecs.EipAdd
|
|||
return &eips[0], nil
|
||||
}
|
||||
|
||||
func (client *AliyunClient) DescribeNatGateway(natGatewayId string) (*NatGatewaySetType, error) {
|
||||
func (client *AliyunClient) DescribeNatGateway(natGatewayId string) (*ecs.NatGatewaySetType, error) {
|
||||
|
||||
args := &DescribeNatGatewaysArgs{
|
||||
args := &ecs.DescribeNatGatewaysArgs{
|
||||
RegionId: client.Region,
|
||||
NatGatewayId: natGatewayId,
|
||||
}
|
||||
|
||||
natGateways, _, err := DescribeNatGateways(client.ecsconn, args)
|
||||
natGateways, _, err := client.vpcconn.DescribeNatGateways(args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -132,3 +132,23 @@ func (client *AliyunClient) QueryRouteEntry(routeTableId, cidrBlock, nextHopType
|
|||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (client *AliyunClient) GetVpcIdByVSwitchId(vswitchId string) (vpcId string, err error) {
|
||||
|
||||
vs, _, err := client.ecsconn.DescribeVpcs(&ecs.DescribeVpcsArgs{
|
||||
RegionId: client.Region,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
for _, v := range vs {
|
||||
for _, sw := range v.VSwitchIds.VSwitchId {
|
||||
if sw == vswitchId {
|
||||
return v.VpcId, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "", &common.Error{ErrorResponse: common.ErrorResponse{Message: Notfound}}
|
||||
}
|
||||
|
|
|
@ -2,17 +2,27 @@ package alicloud
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
"github.com/denverdino/aliyungo/ecs"
|
||||
"github.com/hashicorp/terraform/helper/validation"
|
||||
"github.com/denverdino/aliyungo/slb"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// common
|
||||
func validateInstancePort(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.IntBetween(1, 65535)(v, k)
|
||||
value := v.(int)
|
||||
if value < 1 || value > 65535 {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must be a valid instance port between 1 and 65535",
|
||||
k))
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func validateInstanceProtocol(v interface{}, k string) (ws []string, errors []error) {
|
||||
|
@ -28,11 +38,12 @@ func validateInstanceProtocol(v interface{}, k string) (ws []string, errors []er
|
|||
|
||||
// ecs
|
||||
func validateDiskCategory(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.StringInSlice([]string{
|
||||
string(ecs.DiskCategoryCloud),
|
||||
string(ecs.DiskCategoryCloudEfficiency),
|
||||
string(ecs.DiskCategoryCloudSSD),
|
||||
}, false)(v, k)
|
||||
category := ecs.DiskCategory(v.(string))
|
||||
if category != ecs.DiskCategoryCloud && category != ecs.DiskCategoryCloudEfficiency && category != ecs.DiskCategoryCloudSSD {
|
||||
errors = append(errors, fmt.Errorf("%s must be one of %s %s %s", k, ecs.DiskCategoryCloud, ecs.DiskCategoryCloudEfficiency, ecs.DiskCategoryCloudSSD))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func validateInstanceName(v interface{}, k string) (ws []string, errors []error) {
|
||||
|
@ -49,7 +60,12 @@ func validateInstanceName(v interface{}, k string) (ws []string, errors []error)
|
|||
}
|
||||
|
||||
func validateInstanceDescription(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.StringLenBetween(2, 256)(v, k)
|
||||
value := v.(string)
|
||||
if len(value) < 2 || len(value) > 256 {
|
||||
errors = append(errors, fmt.Errorf("%q cannot be longer than 256 characters", k))
|
||||
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func validateDiskName(v interface{}, k string) (ws []string, errors []error) {
|
||||
|
@ -71,7 +87,12 @@ func validateDiskName(v interface{}, k string) (ws []string, errors []error) {
|
|||
}
|
||||
|
||||
func validateDiskDescription(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.StringLenBetween(2, 128)(v, k)
|
||||
value := v.(string)
|
||||
if len(value) < 2 || len(value) > 256 {
|
||||
errors = append(errors, fmt.Errorf("%q cannot be longer than 256 characters", k))
|
||||
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//security group
|
||||
|
@ -89,114 +110,225 @@ func validateSecurityGroupName(v interface{}, k string) (ws []string, errors []e
|
|||
}
|
||||
|
||||
func validateSecurityGroupDescription(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.StringLenBetween(2, 256)(v, k)
|
||||
value := v.(string)
|
||||
if len(value) < 2 || len(value) > 256 {
|
||||
errors = append(errors, fmt.Errorf("%q cannot be longer than 256 characters", k))
|
||||
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func validateSecurityRuleType(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.StringInSlice([]string{
|
||||
string(GroupRuleIngress),
|
||||
string(GroupRuleEgress),
|
||||
}, false)(v, k)
|
||||
rt := GroupRuleDirection(v.(string))
|
||||
if rt != GroupRuleIngress && rt != GroupRuleEgress {
|
||||
errors = append(errors, fmt.Errorf("%s must be one of %s %s", k, GroupRuleIngress, GroupRuleEgress))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func validateSecurityRuleIpProtocol(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.StringInSlice([]string{
|
||||
string(GroupRuleTcp),
|
||||
string(GroupRuleUdp),
|
||||
string(GroupRuleIcmp),
|
||||
string(GroupRuleGre),
|
||||
string(GroupRuleAll),
|
||||
}, false)(v, k)
|
||||
pt := GroupRuleIpProtocol(v.(string))
|
||||
if pt != GroupRuleTcp && pt != GroupRuleUdp && pt != GroupRuleIcmp && pt != GroupRuleGre && pt != GroupRuleAll {
|
||||
errors = append(errors, fmt.Errorf("%s must be one of %s %s %s %s %s", k,
|
||||
GroupRuleTcp, GroupRuleUdp, GroupRuleIcmp, GroupRuleGre, GroupRuleAll))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func validateSecurityRuleNicType(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.StringInSlice([]string{
|
||||
string(GroupRuleInternet),
|
||||
string(GroupRuleIntranet),
|
||||
}, false)(v, k)
|
||||
pt := GroupRuleNicType(v.(string))
|
||||
if pt != GroupRuleInternet && pt != GroupRuleIntranet {
|
||||
errors = append(errors, fmt.Errorf("%s must be one of %s %s", k, GroupRuleInternet, GroupRuleIntranet))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func validateSecurityRulePolicy(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.StringInSlice([]string{
|
||||
string(GroupRulePolicyAccept),
|
||||
string(GroupRulePolicyDrop),
|
||||
}, false)(v, k)
|
||||
pt := GroupRulePolicy(v.(string))
|
||||
if pt != GroupRulePolicyAccept && pt != GroupRulePolicyDrop {
|
||||
errors = append(errors, fmt.Errorf("%s must be one of %s %s", k, GroupRulePolicyAccept, GroupRulePolicyDrop))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func validateSecurityPriority(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.IntBetween(1, 100)(v, k)
|
||||
value := v.(int)
|
||||
if value < 1 || value > 100 {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must be a valid authorization policy priority between 1 and 100",
|
||||
k))
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// validateCIDRNetworkAddress ensures that the string value is a valid CIDR that
|
||||
// represents a network address - it adds an error otherwise
|
||||
func validateCIDRNetworkAddress(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.CIDRNetwork(0, 32)(v, k)
|
||||
value := v.(string)
|
||||
_, ipnet, err := net.ParseCIDR(value)
|
||||
if err != nil {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must contain a valid CIDR, got error parsing: %s", k, err))
|
||||
return
|
||||
}
|
||||
|
||||
if ipnet == nil || value != ipnet.String() {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must contain a valid network CIDR, expected %q, got %q",
|
||||
k, ipnet, value))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func validateRouteEntryNextHopType(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.StringInSlice([]string{
|
||||
string(ecs.NextHopIntance),
|
||||
string(ecs.NextHopTunnel),
|
||||
}, false)(v, k)
|
||||
nht := ecs.NextHopType(v.(string))
|
||||
if nht != ecs.NextHopIntance && nht != ecs.NextHopTunnel {
|
||||
errors = append(errors, fmt.Errorf("%s must be one of %s %s", k,
|
||||
ecs.NextHopIntance, ecs.NextHopTunnel))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func validateSwitchCIDRNetworkAddress(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.CIDRNetwork(16, 29)(v, k)
|
||||
value := v.(string)
|
||||
_, ipnet, err := net.ParseCIDR(value)
|
||||
if err != nil {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must contain a valid CIDR, got error parsing: %s", k, err))
|
||||
return
|
||||
}
|
||||
|
||||
if ipnet == nil || value != ipnet.String() {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must contain a valid network CIDR, expected %q, got %q",
|
||||
k, ipnet, value))
|
||||
return
|
||||
}
|
||||
|
||||
mark, _ := strconv.Atoi(strings.Split(ipnet.String(), "/")[1])
|
||||
if mark < 16 || mark > 29 {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must contain a network CIDR which mark between 16 and 29",
|
||||
k))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// validateIoOptimized ensures that the string value is a valid IoOptimized that
|
||||
// represents a IoOptimized - it adds an error otherwise
|
||||
func validateIoOptimized(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.StringInSlice([]string{
|
||||
"",
|
||||
string(ecs.IoOptimizedNone),
|
||||
string(ecs.IoOptimizedOptimized),
|
||||
}, false)(v, k)
|
||||
if value := v.(string); value != "" {
|
||||
ioOptimized := ecs.IoOptimized(value)
|
||||
if ioOptimized != ecs.IoOptimizedNone &&
|
||||
ioOptimized != ecs.IoOptimizedOptimized {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must contain a valid IoOptimized, expected %s or %s, got %q",
|
||||
k, ecs.IoOptimizedNone, ecs.IoOptimizedOptimized, ioOptimized))
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// validateInstanceNetworkType ensures that the string value is a classic or vpc
|
||||
func validateInstanceNetworkType(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.StringInSlice([]string{
|
||||
"",
|
||||
string(ClassicNet),
|
||||
string(VpcNet),
|
||||
}, false)(v, k)
|
||||
if value := v.(string); value != "" {
|
||||
network := InstanceNetWork(value)
|
||||
if network != ClassicNet &&
|
||||
network != VpcNet {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must contain a valid InstanceNetworkType, expected %s or %s, go %q",
|
||||
k, ClassicNet, VpcNet, network))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func validateInstanceChargeType(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.StringInSlice([]string{
|
||||
"",
|
||||
string(common.PrePaid),
|
||||
string(common.PostPaid),
|
||||
}, false)(v, k)
|
||||
if value := v.(string); value != "" {
|
||||
chargeType := common.InstanceChargeType(value)
|
||||
if chargeType != common.PrePaid &&
|
||||
chargeType != common.PostPaid {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must contain a valid InstanceChargeType, expected %s or %s, got %q",
|
||||
k, common.PrePaid, common.PostPaid, chargeType))
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func validateInternetChargeType(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.StringInSlice([]string{
|
||||
"",
|
||||
string(common.PayByBandwidth),
|
||||
string(common.PayByTraffic),
|
||||
}, false)(v, k)
|
||||
if value := v.(string); value != "" {
|
||||
chargeType := common.InternetChargeType(value)
|
||||
if chargeType != common.PayByBandwidth &&
|
||||
chargeType != common.PayByTraffic {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must contain a valid InstanceChargeType, expected %s or %s, got %q",
|
||||
k, common.PayByBandwidth, common.PayByTraffic, chargeType))
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func validateInternetMaxBandWidthOut(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.IntBetween(1, 100)(v, k)
|
||||
value := v.(int)
|
||||
if value < 1 || value > 100 {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must be a valid internet bandwidth out between 1 and 1000",
|
||||
k))
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SLB
|
||||
func validateSlbName(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.StringLenBetween(0, 80)(v, k)
|
||||
if value := v.(string); value != "" {
|
||||
if len(value) < 1 || len(value) > 80 {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must be a valid load balancer name characters between 1 and 80",
|
||||
k))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func validateSlbInternetChargeType(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.StringInSlice([]string{
|
||||
"paybybandwidth",
|
||||
"paybytraffic",
|
||||
}, false)(v, k)
|
||||
if value := v.(string); value != "" {
|
||||
chargeType := common.InternetChargeType(value)
|
||||
|
||||
if chargeType != "paybybandwidth" &&
|
||||
chargeType != "paybytraffic" {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must contain a valid InstanceChargeType, expected %s or %s, got %q",
|
||||
k, "paybybandwidth", "paybytraffic", value))
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func validateSlbBandwidth(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.IntBetween(1, 1000)(v, k)
|
||||
value := v.(int)
|
||||
if value < 1 || value > 1000 {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must be a valid load balancer bandwidth between 1 and 1000",
|
||||
k))
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func validateSlbListenerBandwidth(v interface{}, k string) (ws []string, errors []error) {
|
||||
|
@ -211,23 +343,180 @@ func validateSlbListenerBandwidth(v interface{}, k string) (ws []string, errors
|
|||
}
|
||||
|
||||
func validateSlbListenerScheduler(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.StringInSlice([]string{"wrr", "wlc"}, false)(v, k)
|
||||
if value := v.(string); value != "" {
|
||||
scheduler := slb.SchedulerType(value)
|
||||
|
||||
if scheduler != "wrr" && scheduler != "wlc" {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must contain a valid SchedulerType, expected %s or %s, got %q",
|
||||
k, "wrr", "wlc", value))
|
||||
}
|
||||
}
|
||||
|
||||
func validateSlbListenerStickySession(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.StringInSlice([]string{"", "on", "off"}, false)(v, k)
|
||||
}
|
||||
|
||||
func validateSlbListenerStickySessionType(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.StringInSlice([]string{"", "insert", "server"}, false)(v, k)
|
||||
return
|
||||
}
|
||||
|
||||
func validateSlbListenerCookie(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.StringInSlice([]string{"", "insert", "server"}, false)(v, k)
|
||||
if value := v.(string); value != "" {
|
||||
if len(value) < 1 || len(value) > 200 {
|
||||
errors = append(errors, fmt.Errorf("%q cannot be longer than 200 characters", k))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func validateSlbListenerCookieTimeout(v interface{}, k string) (ws []string, errors []error) {
|
||||
value := v.(int)
|
||||
if value < 0 || value > 86400 {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must be a valid load balancer cookie timeout between 0 and 86400",
|
||||
k))
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func validateSlbListenerPersistenceTimeout(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.IntBetween(0, 86400)(v, k)
|
||||
value := v.(int)
|
||||
if value < 0 || value > 3600 {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must be a valid load balancer persistence timeout between 0 and 86400",
|
||||
k))
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func validateSlbListenerHealthCheckDomain(v interface{}, k string) (ws []string, errors []error) {
|
||||
if value := v.(string); value != "" {
|
||||
//the len add "$_ip",so to max is 84
|
||||
if len(value) < 1 || len(value) > 84 {
|
||||
errors = append(errors, fmt.Errorf("%q cannot be longer than 84 characters", k))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func validateSlbListenerHealthCheckUri(v interface{}, k string) (ws []string, errors []error) {
|
||||
if value := v.(string); value != "" {
|
||||
if len(value) < 1 || len(value) > 80 {
|
||||
errors = append(errors, fmt.Errorf("%q cannot be longer than 80 characters", k))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func validateSlbListenerHealthCheckConnectPort(v interface{}, k string) (ws []string, errors []error) {
|
||||
value := v.(int)
|
||||
if value < 1 || value > 65535 {
|
||||
if value != -520 {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must be a valid load balancer health check connect port between 1 and 65535 or -520",
|
||||
k))
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func validateDBBackupPeriod(v interface{}, k string) (ws []string, errors []error) {
|
||||
days := []string{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}
|
||||
value := v.(string)
|
||||
exist := false
|
||||
for _, d := range days {
|
||||
if value == d {
|
||||
exist = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !exist {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must contain a valid backup period value should in array %#v, got %q",
|
||||
k, days, value))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func validateAllowedStringValue(ss []string) schema.SchemaValidateFunc {
|
||||
return func(v interface{}, k string) (ws []string, errors []error) {
|
||||
value := v.(string)
|
||||
existed := false
|
||||
for _, s := range ss {
|
||||
if s == value {
|
||||
existed = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !existed {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must contain a valid string value should in array %#v, got %q",
|
||||
k, ss, value))
|
||||
}
|
||||
return
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func validateAllowedSplitStringValue(ss []string, splitStr string) schema.SchemaValidateFunc {
|
||||
return func(v interface{}, k string) (ws []string, errors []error) {
|
||||
value := v.(string)
|
||||
existed := false
|
||||
tsList := strings.Split(value, splitStr)
|
||||
|
||||
for _, ts := range tsList {
|
||||
existed = false
|
||||
for _, s := range ss {
|
||||
if ts == s {
|
||||
existed = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if !existed {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must contain a valid string value should in %#v, got %q",
|
||||
k, ss, value))
|
||||
}
|
||||
return
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func validateAllowedIntValue(is []int) schema.SchemaValidateFunc {
|
||||
return func(v interface{}, k string) (ws []string, errors []error) {
|
||||
value := v.(int)
|
||||
existed := false
|
||||
for _, i := range is {
|
||||
if i == value {
|
||||
existed = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !existed {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must contain a valid int value should in array %#v, got %q",
|
||||
k, is, value))
|
||||
}
|
||||
return
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func validateIntegerInRange(min, max int) schema.SchemaValidateFunc {
|
||||
return func(v interface{}, k string) (ws []string, errors []error) {
|
||||
value := v.(int)
|
||||
if value < min {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q cannot be lower than %d: %d", k, min, value))
|
||||
}
|
||||
if value > max {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q cannot be higher than %d: %d", k, max, value))
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
//data source validate func
|
||||
|
@ -244,14 +533,19 @@ func validateNameRegex(v interface{}, k string) (ws []string, errors []error) {
|
|||
}
|
||||
|
||||
func validateImageOwners(v interface{}, k string) (ws []string, errors []error) {
|
||||
return validation.StringInSlice([]string{
|
||||
"",
|
||||
string(ecs.ImageOwnerSystem),
|
||||
string(ecs.ImageOwnerSelf),
|
||||
string(ecs.ImageOwnerOthers),
|
||||
string(ecs.ImageOwnerMarketplace),
|
||||
string(ecs.ImageOwnerDefault),
|
||||
}, false)(v, k)
|
||||
if value := v.(string); value != "" {
|
||||
owners := ecs.ImageOwnerAlias(value)
|
||||
if owners != ecs.ImageOwnerSystem &&
|
||||
owners != ecs.ImageOwnerSelf &&
|
||||
owners != ecs.ImageOwnerOthers &&
|
||||
owners != ecs.ImageOwnerMarketplace &&
|
||||
owners != ecs.ImageOwnerDefault {
|
||||
errors = append(errors, fmt.Errorf(
|
||||
"%q must contain a valid Image owner , expected %s, %s, %s, %s or %s, got %q",
|
||||
k, ecs.ImageOwnerSystem, ecs.ImageOwnerSelf, ecs.ImageOwnerOthers, ecs.ImageOwnerMarketplace, ecs.ImageOwnerDefault, owners))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func validateRegion(v interface{}, k string) (ws []string, errors []error) {
|
||||
|
|
|
@ -427,3 +427,76 @@ func TestValidateSlbListenerBandwidth(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateAllowedStringValue(t *testing.T) {
|
||||
exceptValues := []string{"aliyun", "alicloud", "alibaba"}
|
||||
validValues := []string{"aliyun"}
|
||||
for _, v := range validValues {
|
||||
_, errors := validateAllowedStringValue(exceptValues)(v, "allowvalue")
|
||||
if len(errors) != 0 {
|
||||
t.Fatalf("%q should be a valid value in %#v: %q", v, exceptValues, errors)
|
||||
}
|
||||
}
|
||||
|
||||
invalidValues := []string{"ali", "alidata", "terraform"}
|
||||
for _, v := range invalidValues {
|
||||
_, errors := validateAllowedStringValue(exceptValues)(v, "allowvalue")
|
||||
if len(errors) == 0 {
|
||||
t.Fatalf("%q should be an invalid value", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateAllowedStringSplitValue(t *testing.T) {
|
||||
exceptValues := []string{"aliyun", "alicloud", "alibaba"}
|
||||
validValues := "aliyun,alicloud"
|
||||
_, errors := validateAllowedSplitStringValue(exceptValues, ",")(validValues, "allowvalue")
|
||||
if len(errors) != 0 {
|
||||
t.Fatalf("%q should be a valid value in %#v: %q", validValues, exceptValues, errors)
|
||||
}
|
||||
|
||||
invalidValues := "ali,alidata"
|
||||
_, invalidErr := validateAllowedSplitStringValue(exceptValues, ",")(invalidValues, "allowvalue")
|
||||
if len(invalidErr) == 0 {
|
||||
t.Fatalf("%q should be an invalid value", invalidValues)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateAllowedIntValue(t *testing.T) {
|
||||
exceptValues := []int{1, 3, 5, 6}
|
||||
validValues := []int{1, 3, 5, 6}
|
||||
for _, v := range validValues {
|
||||
_, errors := validateAllowedIntValue(exceptValues)(v, "allowvalue")
|
||||
if len(errors) != 0 {
|
||||
t.Fatalf("%q should be a valid value in %#v: %q", v, exceptValues, errors)
|
||||
}
|
||||
}
|
||||
|
||||
invalidValues := []int{0, 7, 10}
|
||||
for _, v := range invalidValues {
|
||||
_, errors := validateAllowedIntValue(exceptValues)(v, "allowvalue")
|
||||
if len(errors) == 0 {
|
||||
t.Fatalf("%q should be an invalid value", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateIntegerInRange(t *testing.T) {
|
||||
validIntegers := []int{-259, 0, 1, 5, 999}
|
||||
min := -259
|
||||
max := 999
|
||||
for _, v := range validIntegers {
|
||||
_, errors := validateIntegerInRange(min, max)(v, "name")
|
||||
if len(errors) != 0 {
|
||||
t.Fatalf("%q should be an integer in range (%d, %d): %q", v, min, max, errors)
|
||||
}
|
||||
}
|
||||
|
||||
invalidIntegers := []int{-260, -99999, 1000, 25678}
|
||||
for _, v := range invalidIntegers {
|
||||
_, errors := validateIntegerInRange(min, max)(v, "name")
|
||||
if len(errors) == 0 {
|
||||
t.Fatalf("%q should be an integer outside range (%d, %d)", v, min, max)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,39 @@ resource "alicloud_security_group" "group" {
|
|||
description = "New security group"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "http-in" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "internet"
|
||||
policy = "accept"
|
||||
port_range = "80/80"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.group.id}"
|
||||
cidr_ip = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "https-in" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "internet"
|
||||
policy = "accept"
|
||||
port_range = "443/443"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.group.id}"
|
||||
cidr_ip = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "ssh-in" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "internet"
|
||||
policy = "accept"
|
||||
port_range = "22/22"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.group.id}"
|
||||
cidr_ip = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
|
||||
resource "alicloud_disk" "disk" {
|
||||
availability_zone = "${var.availability_zones}"
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
### Configure NAT instance Example
|
||||
|
||||
In the Virtual Private Cloud(VPC) environment, to enable multiple back-end intranet hosts to provide services externally with a limited number of EIPs, map the ports on the EIP-bound host to the back-end intranet hosts.
|
||||
|
||||
### Get up and running
|
||||
|
||||
* Planning phase
|
||||
|
||||
terraform plan
|
||||
|
||||
* Apply phase
|
||||
|
||||
terraform apply
|
||||
|
||||
Get the outputs:
|
||||
+ nat_instance_eip_address = 123.56.19.238
|
||||
+ nat_instance_private_ip = 10.1.1.57
|
||||
+ worker_instance_private_ip = 10.1.1.56
|
||||
|
||||
* Apply phase
|
||||
|
||||
+ login the vm: ssh root@123.56.19.238|Test123456
|
||||
+ Run the "iptables -t nat -nvL" command to check the result
|
||||
|
||||
| prot | in | source | destination | |
|
||||
| ---- | -- | ----------- | -------------- | ------------------------ |
|
||||
| tcp | * | 0.0.0.0/0 | 10.1.1.57 | tcp dpt:80 to:10.1.1.56
|
||||
| all | * | 10.1.1.0/24 | 0.0.0.0/0 | to:10.1.1.57
|
||||
|
||||
|
||||
* Destroy
|
||||
|
||||
terraform destroy
|
|
@ -0,0 +1,98 @@
|
|||
resource "alicloud_vpc" "main" {
|
||||
cidr_block = "${var.vpc_cidr}"
|
||||
}
|
||||
|
||||
resource "alicloud_vswitch" "main" {
|
||||
vpc_id = "${alicloud_vpc.main.id}"
|
||||
cidr_block = "${var.vswitch_cidr}"
|
||||
availability_zone = "${var.zone}"
|
||||
depends_on = ["alicloud_vpc.main"]
|
||||
}
|
||||
|
||||
resource "alicloud_route_entry" "entry" {
|
||||
router_id = "${alicloud_vpc.main.router_id}"
|
||||
route_table_id = "${alicloud_vpc.main.router_table_id}"
|
||||
destination_cidrblock = "0.0.0.0/0"
|
||||
nexthop_type = "Instance"
|
||||
nexthop_id = "${alicloud_instance.nat.id}"
|
||||
}
|
||||
|
||||
resource "alicloud_instance" "nat" {
|
||||
image_id = "${var.image}"
|
||||
instance_type = "${var.instance_nat_type}"
|
||||
availability_zone = "${var.zone}"
|
||||
security_groups = ["${alicloud_security_group.group.id}"]
|
||||
vswitch_id = "${alicloud_vswitch.main.id}"
|
||||
instance_name = "nat"
|
||||
io_optimized = "optimized"
|
||||
system_disk_category = "cloud_efficiency"
|
||||
password= "${var.instance_pwd}"
|
||||
|
||||
depends_on = ["alicloud_instance.worker"]
|
||||
user_data = "${data.template_file.shell.rendered}"
|
||||
|
||||
tags {
|
||||
Name = "ecs-nat"
|
||||
}
|
||||
}
|
||||
|
||||
data "template_file" "shell" {
|
||||
template = "${file("userdata.sh")}"
|
||||
|
||||
vars {
|
||||
worker_private_ip = "${alicloud_instance.worker.private_ip}"
|
||||
vswitch_cidr = "${var.vswitch_cidr}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "alicloud_instance" "worker" {
|
||||
image_id = "${var.image}"
|
||||
instance_type = "${var.instance_worker_type}"
|
||||
availability_zone = "${var.zone}"
|
||||
security_groups = ["${alicloud_security_group.group.id}"]
|
||||
vswitch_id = "${alicloud_vswitch.main.id}"
|
||||
instance_name = "worker"
|
||||
io_optimized = "optimized"
|
||||
system_disk_category = "cloud_efficiency"
|
||||
password= "${var.instance_pwd}"
|
||||
|
||||
tags {
|
||||
Name = "ecs-worker"
|
||||
}
|
||||
}
|
||||
|
||||
resource "alicloud_eip" "eip" {
|
||||
}
|
||||
|
||||
resource "alicloud_eip_association" "attach" {
|
||||
allocation_id = "${alicloud_eip.eip.id}"
|
||||
instance_id = "${alicloud_instance.nat.id}"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group" "group" {
|
||||
name = "terraform-test-group"
|
||||
description = "New security group"
|
||||
vpc_id = "${alicloud_vpc.main.id}"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "allow_in" {
|
||||
security_group_id = "${alicloud_security_group.group.id}"
|
||||
type = "ingress"
|
||||
cidr_ip= "0.0.0.0/0"
|
||||
policy = "accept"
|
||||
ip_protocol= "all"
|
||||
nic_type= "intranet"
|
||||
port_range= "-1/-1"
|
||||
priority= 1
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "allow_out" {
|
||||
security_group_id = "${alicloud_security_group.group.id}"
|
||||
type = "egress"
|
||||
cidr_ip= "0.0.0.0/0"
|
||||
policy = "accept"
|
||||
ip_protocol= "all"
|
||||
nic_type= "intranet"
|
||||
port_range= "-1/-1"
|
||||
priority= 1
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
output "nat_instance_id" {
|
||||
value = "${alicloud_instance.nat.id}"
|
||||
}
|
||||
|
||||
output "nat_instance_private_ip" {
|
||||
value = "${alicloud_instance.nat.private_ip}"
|
||||
}
|
||||
|
||||
output "nat_instance_eip_address" {
|
||||
value = "${alicloud_eip.eip.ip_address}"
|
||||
}
|
||||
|
||||
output "worker_instance_id" {
|
||||
value = "${alicloud_instance.worker.id}"
|
||||
}
|
||||
|
||||
output "worker_instance_private_ip" {
|
||||
value = "${alicloud_instance.worker.private_ip}"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/sh
|
||||
|
||||
PostRouting=${vswitch_cidr}
|
||||
SourceRouting=`ifconfig eth0|grep inet|awk '{print $2}'|tr -d 'addr:'`
|
||||
echo ${worker_private_ip}>> /etc/sysctl.conf
|
||||
echo 'net.ipv4.ip_forward=1'>> /etc/sysctl.conf
|
||||
sysctl -p
|
||||
iptables -t nat -I POSTROUTING -s $PostRouting -j SNAT --to-source $SourceRouting
|
||||
iptables -t nat -I PREROUTING -d $SourceRouting -p tcp --dport 80 -j DNAT --to ${worker_private_ip}
|
|
@ -0,0 +1,27 @@
|
|||
variable "vpc_cidr" {
|
||||
default = "10.1.0.0/21"
|
||||
}
|
||||
|
||||
variable "vswitch_cidr" {
|
||||
default = "10.1.1.0/24"
|
||||
}
|
||||
|
||||
variable "zone" {
|
||||
default = "cn-beijing-c"
|
||||
}
|
||||
|
||||
variable "image" {
|
||||
default = "ubuntu_140405_64_40G_cloudinit_20161115.vhd"
|
||||
}
|
||||
|
||||
variable "instance_nat_type" {
|
||||
default = "ecs.n1.small"
|
||||
}
|
||||
|
||||
variable "instance_worker_type" {
|
||||
default = "ecs.s2.large"
|
||||
}
|
||||
|
||||
variable "instance_pwd" {
|
||||
default = "Test123456"
|
||||
}
|
|
@ -3,33 +3,59 @@ resource "alicloud_security_group" "group" {
|
|||
description = "New security group"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "http-in" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "internet"
|
||||
policy = "accept"
|
||||
port_range = "80/80"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.group.id}"
|
||||
cidr_ip = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "https-in" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "internet"
|
||||
policy = "accept"
|
||||
port_range = "443/443"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.group.id}"
|
||||
cidr_ip = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "ssh-in" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "internet"
|
||||
policy = "accept"
|
||||
port_range = "22/22"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.group.id}"
|
||||
cidr_ip = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
resource "alicloud_instance" "instance" {
|
||||
instance_name = "${var.short_name}-${var.role}-${format(var.count_format, count.index+1)}"
|
||||
host_name = "${var.short_name}-${var.role}-${format(var.count_format, count.index+1)}"
|
||||
image_id = "${var.image_id}"
|
||||
instance_type = "${var.ecs_type}"
|
||||
count = "${var.count}"
|
||||
availability_zone = "${var.availability_zones}"
|
||||
security_groups = ["${alicloud_security_group.group.*.id}"]
|
||||
|
||||
internet_charge_type = "${var.internet_charge_type}"
|
||||
internet_max_bandwidth_out = "${var.internet_max_bandwidth_out}"
|
||||
|
||||
io_optimized = "${var.io_optimized}"
|
||||
|
||||
password = "${var.ecs_password}"
|
||||
|
||||
allocate_public_ip = "${var.allocate_public_ip}"
|
||||
|
||||
availability_zone = ""
|
||||
instance_charge_type = "PostPaid"
|
||||
system_disk_category = "cloud_efficiency"
|
||||
|
||||
|
||||
tags {
|
||||
role = "${var.role}"
|
||||
dc = "${var.datacenter}"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
resource "alicloud_slb" "instance" {
|
||||
|
|
|
@ -16,6 +16,16 @@ resource "alicloud_security_group" "sg" {
|
|||
vpc_id = "${alicloud_vpc.default.id}"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "allow_ssh" {
|
||||
security_group_id = "${alicloud_security_group.sg.id}"
|
||||
type = "ingress"
|
||||
cidr_ip= "0.0.0.0/0"
|
||||
policy = "accept"
|
||||
ip_protocol= "tcp"
|
||||
port_range= "22/22"
|
||||
priority= 1
|
||||
}
|
||||
|
||||
resource "alicloud_instance" "website" {
|
||||
# cn-beijing
|
||||
availability_zone = "${var.zone}"
|
||||
|
@ -31,7 +41,8 @@ resource "alicloud_instance" "website" {
|
|||
internet_max_bandwidth_out = 5
|
||||
allocate_public_ip = true
|
||||
security_groups = ["${alicloud_security_group.sg.id}"]
|
||||
instance_name = "test_foo"
|
||||
instance_name = "tf_website"
|
||||
password= "${var.password}"
|
||||
|
||||
user_data = "${file("userdata.sh")}"
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
output "hostname" {
|
||||
value = "${alicloud_instance.website.instance_name}"
|
||||
}
|
||||
|
||||
output "ecs_id" {
|
||||
value = "${alicloud_instance.website.id}"
|
||||
}
|
||||
|
||||
output "ecs_public_ip" {
|
||||
value = "${alicloud_instance.website.public_ip}"
|
||||
}
|
|
@ -10,6 +10,10 @@ variable "zone" {
|
|||
default = "cn-beijing-b"
|
||||
}
|
||||
|
||||
variable "password" {
|
||||
default = "Test123456"
|
||||
}
|
||||
|
||||
variable "image" {
|
||||
default = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||
}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
provider "alicloud" {
|
||||
region = "${var.region}"
|
||||
}
|
||||
|
||||
module "vpc" {
|
||||
availability_zones = "${var.availability_zones}"
|
||||
|
@ -21,14 +18,12 @@ module "control-nodes" {
|
|||
role = "control"
|
||||
datacenter = "${var.datacenter}"
|
||||
ecs_type = "${var.control_ecs_type}"
|
||||
ecs_password = "${var.ecs_password}"
|
||||
disk_size = "${var.control_disk_size}"
|
||||
ssh_username = "${var.ssh_username}"
|
||||
short_name = "${var.short_name}"
|
||||
availability_zones = "${module.vpc.availability_zones}"
|
||||
security_groups = ["${module.security-groups.control_security_group}"]
|
||||
vswitch_id = "${module.vpc.vswitch_ids}"
|
||||
internet_charge_type = "${var.internet_charge_type}"
|
||||
}
|
||||
|
||||
module "edge-nodes" {
|
||||
|
@ -37,13 +32,11 @@ module "edge-nodes" {
|
|||
role = "edge"
|
||||
datacenter = "${var.datacenter}"
|
||||
ecs_type = "${var.edge_ecs_type}"
|
||||
ecs_password = "${var.ecs_password}"
|
||||
ssh_username = "${var.ssh_username}"
|
||||
short_name = "${var.short_name}"
|
||||
availability_zones = "${module.vpc.availability_zones}"
|
||||
security_groups = ["${module.security-groups.worker_security_group}"]
|
||||
vswitch_id = "${module.vpc.vswitch_ids}"
|
||||
internet_charge_type = "${var.internet_charge_type}"
|
||||
}
|
||||
|
||||
module "worker-nodes" {
|
||||
|
@ -52,11 +45,9 @@ module "worker-nodes" {
|
|||
role = "worker"
|
||||
datacenter = "${var.datacenter}"
|
||||
ecs_type = "${var.worker_ecs_type}"
|
||||
ecs_password = "${var.ecs_password}"
|
||||
ssh_username = "${var.ssh_username}"
|
||||
short_name = "${var.short_name}"
|
||||
availability_zones = "${module.vpc.availability_zones}"
|
||||
security_groups = ["${module.security-groups.worker_security_group}"]
|
||||
vswitch_id = "${module.vpc.vswitch_ids}"
|
||||
internet_charge_type = "${var.internet_charge_type}"
|
||||
}
|
|
@ -50,10 +50,6 @@ variable "availability_zones" {
|
|||
default = "cn-beijing-c"
|
||||
}
|
||||
|
||||
variable "internet_charge_type" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "datacenter" {
|
||||
default = "beijing"
|
||||
}
|
|
@ -18,6 +18,7 @@ variable "short_name" {
|
|||
variable "ecs_type" {
|
||||
}
|
||||
variable "ecs_password" {
|
||||
default = "Test12345"
|
||||
}
|
||||
variable "availability_zones" {
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ data "alicloud_instance_types" "1c2g" {
|
|||
}
|
||||
|
||||
data "alicloud_zones" "default" {
|
||||
"available_instance_type"= "${data.alicloud_instance_types.4c8g.instance_types.0.id}"
|
||||
"available_instance_type"= "${data.alicloud_instance_types.1c2g.instance_types.0.id}"
|
||||
"available_disk_category"= "${var.disk_category}"
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,39 @@ resource "alicloud_security_group" "group" {
|
|||
description = "New security group"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "http-in" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "internet"
|
||||
policy = "accept"
|
||||
port_range = "80/80"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.group.id}"
|
||||
cidr_ip = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "https-in" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "internet"
|
||||
policy = "accept"
|
||||
port_range = "443/443"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.group.id}"
|
||||
cidr_ip = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "ssh-in" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "internet"
|
||||
policy = "accept"
|
||||
port_range = "22/22"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.group.id}"
|
||||
cidr_ip = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
resource "alicloud_instance" "instance" {
|
||||
instance_name = "${var.short_name}-${var.role}-${format(var.count_format, count.index+1)}"
|
||||
host_name = "${var.short_name}-${var.role}-${format(var.count_format, count.index+1)}"
|
||||
|
|
|
@ -1,11 +1,39 @@
|
|||
data "alicloud_instance_types" "instance_type" {
|
||||
instance_type_family = "ecs.n1"
|
||||
cpu_core_count = "1"
|
||||
memory_size = "2"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group" "group" {
|
||||
name = "${var.short_name}"
|
||||
description = "New security group"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "allow_http_80" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "${var.nic_type}"
|
||||
policy = "accept"
|
||||
port_range = "80/80"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.group.id}"
|
||||
cidr_ip = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
|
||||
resource "alicloud_security_group_rule" "allow_https_443" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "${var.nic_type}"
|
||||
policy = "accept"
|
||||
port_range = "443/443"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.group.id}"
|
||||
cidr_ip = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
resource "alicloud_disk" "disk" {
|
||||
availability_zone = "${var.availability_zones}"
|
||||
availability_zone = "${alicloud_instance.instance.0.availability_zone}"
|
||||
category = "${var.disk_category}"
|
||||
size = "${var.disk_size}"
|
||||
count = "${var.count}"
|
||||
|
@ -15,7 +43,7 @@ resource "alicloud_instance" "instance" {
|
|||
instance_name = "${var.short_name}-${var.role}-${format(var.count_format, count.index+1)}"
|
||||
host_name = "${var.short_name}-${var.role}-${format(var.count_format, count.index+1)}"
|
||||
image_id = "${var.image_id}"
|
||||
instance_type = "${var.ecs_type}"
|
||||
instance_type = "${data.alicloud_instance_types.instance_type.instance_types.0.id}"
|
||||
count = "${var.count}"
|
||||
availability_zone = "${var.availability_zones}"
|
||||
security_groups = ["${alicloud_security_group.group.*.id}"]
|
||||
|
@ -46,4 +74,3 @@ resource "alicloud_disk_attachment" "instance-attachment" {
|
|||
instance_id = "${element(alicloud_instance.instance.*.id, count.index)}"
|
||||
device_name = "${var.device_name}"
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,10 @@ variable "image_id" {
|
|||
default = "ubuntu_140405_64_40G_cloudinit_20161115.vhd"
|
||||
}
|
||||
|
||||
variable "availability_zones" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "role" {
|
||||
default = "work"
|
||||
}
|
||||
|
@ -23,9 +27,6 @@ variable "ecs_type" {
|
|||
variable "ecs_password" {
|
||||
default = "Test12345"
|
||||
}
|
||||
variable "availability_zones" {
|
||||
default = "cn-beijing-b"
|
||||
}
|
||||
variable "allocate_public_ip" {
|
||||
default = true
|
||||
}
|
||||
|
@ -41,7 +42,7 @@ variable "io_optimized" {
|
|||
}
|
||||
|
||||
variable "disk_category" {
|
||||
default = "cloud_ssd"
|
||||
default = "cloud_efficiency"
|
||||
}
|
||||
variable "disk_size" {
|
||||
default = "40"
|
||||
|
@ -49,3 +50,7 @@ variable "disk_size" {
|
|||
variable "device_name" {
|
||||
default = "/dev/xvdb"
|
||||
}
|
||||
|
||||
variable "nic_type" {
|
||||
default = "internet"
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
### RDS Example
|
||||
|
||||
The example launches RDS instance, database, account and grant the database readwrite privilege to the account.
|
||||
|
||||
### Get up and running
|
||||
|
||||
* Planning phase
|
||||
|
||||
terraform plan
|
||||
|
||||
* Apply phase
|
||||
|
||||
terraform apply
|
||||
|
||||
* Destroy
|
||||
|
||||
terraform destroy
|
|
@ -0,0 +1,17 @@
|
|||
|
||||
resource "alicloud_db_instance" "dc" {
|
||||
engine = "${var.engine}"
|
||||
engine_version = "${var.engine_version}"
|
||||
db_instance_class = "${var.instance_class}"
|
||||
db_instance_storage = "${var.storage}"
|
||||
db_instance_net_type = "${var.net_type}"
|
||||
|
||||
master_user_name = "${var.user_name}"
|
||||
master_user_password = "${var.password}"
|
||||
|
||||
db_mappings = [{
|
||||
db_name = "${var.database_name}"
|
||||
character_set_name = "${var.database_character}"
|
||||
db_description = "tf"
|
||||
}]
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
output "port" {
|
||||
value = "${alicloud_db_instance.dc.port}"
|
||||
}
|
||||
|
||||
output "connections" {
|
||||
value = "${alicloud_db_instance.dc.connections}"
|
||||
}
|
||||
|
||||
output "security_ips" {
|
||||
value = "${alicloud_db_instance.dc.security_ips}"
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
variable "engine" {
|
||||
default = "MySQL"
|
||||
}
|
||||
variable "engine_version" {
|
||||
default = "5.6"
|
||||
}
|
||||
variable "instance_class" {
|
||||
default = "rds.mysql.t1.small"
|
||||
}
|
||||
variable "storage" {
|
||||
default = "10"
|
||||
}
|
||||
variable "net_type" {
|
||||
default = "Intranet"
|
||||
}
|
||||
|
||||
variable "user_name" {
|
||||
default = "tf_tester"
|
||||
}
|
||||
variable "password" {
|
||||
default = "Test12345"
|
||||
}
|
||||
|
||||
variable "database_name" {
|
||||
default = "bookstore"
|
||||
}
|
||||
variable "database_character" {
|
||||
default = "utf8"
|
||||
}
|
|
@ -2,12 +2,23 @@ resource "alicloud_security_group" "default" {
|
|||
name = "${var.security_group_name}"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "allow_all_tcp" {
|
||||
resource "alicloud_security_group_rule" "http-in" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "${var.nic_type}"
|
||||
nic_type = "internet"
|
||||
policy = "accept"
|
||||
port_range = "1/65535"
|
||||
port_range = "80/80"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.default.id}"
|
||||
cidr_ip = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "ssh-in" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "internet"
|
||||
policy = "accept"
|
||||
port_range = "22/22"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.default.id}"
|
||||
cidr_ip = "0.0.0.0/0"
|
||||
|
|
Binary file not shown.
|
@ -5,21 +5,50 @@ resource "alicloud_slb" "instance" {
|
|||
|
||||
listener = [
|
||||
{
|
||||
"instance_port" = "2111"
|
||||
"lb_port" = "21"
|
||||
"instance_port" = "22"
|
||||
"lb_port" = "22"
|
||||
"lb_protocol" = "tcp"
|
||||
"bandwidth" = "5"
|
||||
"bandwidth" = "10"
|
||||
"health_check_type" = "http"
|
||||
"persistence_timeout" = 3600
|
||||
"healthy_threshold" = 8
|
||||
"unhealthy_threshold" = 8
|
||||
"health_check_timeout" = 8
|
||||
"health_check_interval" = 5
|
||||
"health_check_http_code" = "http_2xx,http_3xx"
|
||||
"health_check_timeout" = 8
|
||||
},
|
||||
|
||||
{
|
||||
"instance_port" = "8000"
|
||||
"instance_port" = "2001"
|
||||
"lb_port" = "2001"
|
||||
"lb_protocol" = "udp"
|
||||
"bandwidth" = "10"
|
||||
"persistence_timeout" = 3600
|
||||
"healthy_threshold" = 8
|
||||
"unhealthy_threshold" = 8
|
||||
"health_check_timeout" = 8
|
||||
"health_check_interval" = 4
|
||||
"health_check_timeout" = 8
|
||||
},
|
||||
|
||||
{
|
||||
"instance_port" = "80"
|
||||
"lb_port" = "80"
|
||||
"lb_protocol" = "http"
|
||||
"bandwidth" = "5"
|
||||
},
|
||||
{
|
||||
"instance_port" = "1611"
|
||||
"lb_port" = "161"
|
||||
"lb_protocol" = "udp"
|
||||
"bandwidth" = "5"
|
||||
"sticky_session" = "on"
|
||||
"sticky_session_type" = "server"
|
||||
"cookie" = "testslblistenercookie"
|
||||
"cookie_timeout" = 86400
|
||||
"health_check" = "on"
|
||||
"health_check_domain" = "$_ip"
|
||||
"health_check_uri" = "/console"
|
||||
"health_check_connect_port" = 20
|
||||
"healthy_threshold" = 8
|
||||
"unhealthy_threshold" = 8
|
||||
"health_check_timeout" = 8
|
||||
"health_check_interval" = 5
|
||||
"health_check_http_code" = "http_2xx,http_3xx"
|
||||
"bandwidth" = 10
|
||||
}]
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ resource "alicloud_security_group" "sg" {
|
|||
vpc_id = "${alicloud_vpc.default.id}"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "ssh" {
|
||||
resource "alicloud_security_group_rule" "ssh-in" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "intranet"
|
||||
|
@ -34,6 +34,28 @@ resource "alicloud_security_group_rule" "ssh" {
|
|||
cidr_ip = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "http-in" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "internet"
|
||||
policy = "accept"
|
||||
port_range = "80/80"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.sg.id}"
|
||||
cidr_ip = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
resource "alicloud_security_group_rule" "https-in" {
|
||||
type = "ingress"
|
||||
ip_protocol = "tcp"
|
||||
nic_type = "internet"
|
||||
policy = "accept"
|
||||
port_range = "443/443"
|
||||
priority = 1
|
||||
security_group_id = "${alicloud_security_group.sg.id}"
|
||||
cidr_ip = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
resource "alicloud_instance" "snat" {
|
||||
# cn-beijing
|
||||
availability_zone = "${var.zone_id}"
|
||||
|
|
|
@ -7,8 +7,8 @@ import (
|
|||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/denverdino/aliyungo/util"
|
||||
)
|
||||
|
@ -21,6 +21,9 @@ type Client struct {
|
|||
httpClient *http.Client
|
||||
endpoint string
|
||||
version string
|
||||
serviceCode string
|
||||
regionID Region
|
||||
businessInfo string
|
||||
}
|
||||
|
||||
// NewClient creates a new instance of ECS client
|
||||
|
@ -33,6 +36,26 @@ func (client *Client) Init(endpoint, version, accessKeyId, accessKeySecret strin
|
|||
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
|
||||
|
@ -43,6 +66,15 @@ 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
|
||||
|
@ -58,6 +90,15 @@ 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
|
||||
}
|
||||
}
|
||||
|
||||
// Invoke sends the raw HTTP request for ECS services
|
||||
func (client *Client) Invoke(action string, args interface{}, response interface{}) error {
|
||||
|
||||
|
@ -80,7 +121,7 @@ func (client *Client) Invoke(action string, args interface{}, response interface
|
|||
}
|
||||
|
||||
// TODO move to util and add build val flag
|
||||
httpReq.Header.Set("X-SDK-Client", `AliyunGO/`+Version)
|
||||
httpReq.Header.Set("X-SDK-Client", `AliyunGO/`+Version+client.businessInfo)
|
||||
|
||||
t0 := time.Now()
|
||||
httpResp, err := client.httpClient.Do(httpReq)
|
||||
|
@ -128,7 +169,8 @@ func (client *Client) Invoke(action string, args interface{}, response interface
|
|||
|
||||
// Invoke sends the raw HTTP request for ECS services
|
||||
//改进了一下上面那个方法,可以使用各种Http方法
|
||||
func (client *Client) InvokeByAnyMethod(method, action string, args interface{}, response interface{}) error {
|
||||
//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)
|
||||
|
@ -140,17 +182,18 @@ func (client *Client) InvokeByAnyMethod(method, action string, args interface{},
|
|||
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 + "?" + data.Encode()
|
||||
requestURL := client.endpoint + path + "?" + data.Encode()
|
||||
//fmt.Println(requestURL)
|
||||
httpReq, err = http.NewRequest(method, requestURL, nil)
|
||||
} else {
|
||||
httpReq, err = http.NewRequest(method, client.endpoint, strings.NewReader(data.Encode()))
|
||||
//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")
|
||||
}
|
||||
|
||||
|
@ -159,7 +202,7 @@ func (client *Client) InvokeByAnyMethod(method, action string, args interface{},
|
|||
}
|
||||
|
||||
// TODO move to util and add build val flag
|
||||
httpReq.Header.Set("X-SDK-Client", `AliyunGO/` + Version)
|
||||
httpReq.Header.Set("X-SDK-Client", `AliyunGO/`+Version+client.businessInfo)
|
||||
|
||||
t0 := time.Now()
|
||||
httpResp, err := client.httpClient.Do(httpReq)
|
||||
|
|
|
@ -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 ""
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -10,18 +10,23 @@ const (
|
|||
Beijing = Region("cn-beijing")
|
||||
Hongkong = Region("cn-hongkong")
|
||||
Shenzhen = Region("cn-shenzhen")
|
||||
USWest1 = Region("us-west-1")
|
||||
USEast1 = Region("us-east-1")
|
||||
APSouthEast1 = Region("ap-southeast-1")
|
||||
Shanghai = Region("cn-shanghai")
|
||||
MEEast1 = Region("me-east-1")
|
||||
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,
|
||||
Hangzhou, Qingdao, Beijing, Shenzhen, Hongkong, Shanghai, Zhangjiakou,
|
||||
USWest1, USEast1,
|
||||
APNorthEast1, APSouthEast1, APSouthEast2,
|
||||
MEEast1,
|
||||
|
|
|
@ -13,3 +13,77 @@ 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"`
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package ecs
|
||||
|
||||
import (
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
"os"
|
||||
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
)
|
||||
|
||||
// Interval for checking status in WaitForXXX method
|
||||
|
@ -19,6 +20,12 @@ const (
|
|||
// ECSDefaultEndpoint is the default API endpoint of ECS services
|
||||
ECSDefaultEndpoint = "https://ecs-cn-hangzhou.aliyuncs.com"
|
||||
ECSAPIVersion = "2014-05-26"
|
||||
|
||||
ECSServiceCode = "ecs"
|
||||
|
||||
VPCDefaultEndpoint = "https://vpc.aliyuncs.com"
|
||||
VPCAPIVersion = "2016-04-28"
|
||||
VPCServiceCode = "vpc"
|
||||
)
|
||||
|
||||
// NewClient creates a new instance of ECS client
|
||||
|
@ -30,8 +37,38 @@ func NewClient(accessKeyId, accessKeySecret string) *Client {
|
|||
return NewClientWithEndpoint(endpoint, accessKeyId, accessKeySecret)
|
||||
}
|
||||
|
||||
func NewECSClient(accessKeyId, accessKeySecret string, regionID common.Region) *Client {
|
||||
endpoint := os.Getenv("ECS_ENDPOINT")
|
||||
if endpoint == "" {
|
||||
endpoint = ECSDefaultEndpoint
|
||||
}
|
||||
|
||||
return NewClientWithRegion(endpoint, accessKeyId, accessKeySecret, regionID)
|
||||
}
|
||||
|
||||
func NewClientWithRegion(endpoint string, accessKeyId, accessKeySecret string, regionID common.Region) *Client {
|
||||
client := &Client{}
|
||||
client.NewInit(endpoint, ECSAPIVersion, accessKeyId, accessKeySecret, ECSServiceCode, regionID)
|
||||
return client
|
||||
}
|
||||
|
||||
func NewClientWithEndpoint(endpoint string, accessKeyId, accessKeySecret string) *Client {
|
||||
client := &Client{}
|
||||
client.Init(endpoint, ECSAPIVersion, accessKeyId, accessKeySecret)
|
||||
return client
|
||||
}
|
||||
|
||||
func NewVPCClient(accessKeyId, accessKeySecret string, regionID common.Region) *Client {
|
||||
endpoint := os.Getenv("VPC_ENDPOINT")
|
||||
if endpoint == "" {
|
||||
endpoint = VPCDefaultEndpoint
|
||||
}
|
||||
|
||||
return NewVPCClientWithRegion(endpoint, accessKeyId, accessKeySecret, regionID)
|
||||
}
|
||||
|
||||
func NewVPCClientWithRegion(endpoint string, accessKeyId, accessKeySecret string, regionID common.Region) *Client {
|
||||
client := &Client{}
|
||||
client.NewInit(endpoint, VPCAPIVersion, accessKeyId, accessKeySecret, VPCServiceCode, regionID)
|
||||
return client
|
||||
}
|
||||
|
|
|
@ -65,6 +65,10 @@ type DiskDeviceMapping struct {
|
|||
//Why Size Field is string-type.
|
||||
Size string
|
||||
Device string
|
||||
//For import images
|
||||
Format string
|
||||
OSSBucket string
|
||||
OSSObject string
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -112,6 +116,7 @@ func (client *Client) DescribeImages(args *DescribeImagesArgs) (images []ImageTy
|
|||
type CreateImageArgs struct {
|
||||
RegionId common.Region
|
||||
SnapshotId string
|
||||
InstanceId string
|
||||
ImageName string
|
||||
ImageVersion string
|
||||
Description string
|
||||
|
@ -227,6 +232,38 @@ func (client *Client) CopyImage(args *CopyImageArgs) (string, error) {
|
|||
return response.ImageId, nil
|
||||
}
|
||||
|
||||
|
||||
// ImportImageArgs repsents arguements to import image from oss
|
||||
type ImportImageArgs struct {
|
||||
RegionId common.Region
|
||||
ImageName string
|
||||
ImageVersion string
|
||||
Description string
|
||||
ClientToken string
|
||||
Architecture string
|
||||
OSType string
|
||||
Platform string
|
||||
DiskDeviceMappings struct {
|
||||
DiskDeviceMapping []DiskDeviceMapping
|
||||
}
|
||||
}
|
||||
|
||||
func (client *Client) ImportImage(args *ImportImageArgs) (string, error) {
|
||||
response := &CopyImageResponse{}
|
||||
err := client.Invoke("ImportImage", args, &response)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return response.ImageId, nil
|
||||
}
|
||||
|
||||
type ImportImageResponse struct {
|
||||
common.Response
|
||||
RegionId common.Region
|
||||
ImageId string
|
||||
ImportTaskId string
|
||||
}
|
||||
|
||||
// Default timeout value for WaitForImageReady method
|
||||
const ImageDefaultTimeout = 120
|
||||
|
||||
|
|
|
@ -15,12 +15,14 @@ type InstanceStatus string
|
|||
|
||||
// Constants of InstanceStatus
|
||||
const (
|
||||
Creating = InstanceStatus("Creating")
|
||||
Creating = InstanceStatus("Creating") // For backward compatability
|
||||
Pending = InstanceStatus("Pending")
|
||||
Running = InstanceStatus("Running")
|
||||
Starting = InstanceStatus("Starting")
|
||||
|
||||
Stopped = InstanceStatus("Stopped")
|
||||
Stopping = InstanceStatus("Stopping")
|
||||
Deleted = InstanceStatus("Deleted")
|
||||
)
|
||||
|
||||
type LockReason string
|
||||
|
@ -279,6 +281,7 @@ type ModifyInstanceAttributeArgs struct {
|
|||
Description string
|
||||
Password string
|
||||
HostName string
|
||||
UserData string
|
||||
}
|
||||
|
||||
type ModifyInstanceAttributeResponse struct {
|
||||
|
@ -323,6 +326,38 @@ func (client *Client) WaitForInstance(instanceId string, status InstanceStatus,
|
|||
return nil
|
||||
}
|
||||
|
||||
// WaitForInstance waits for instance to given status
|
||||
// when instance.NotFound wait until timeout
|
||||
func (client *Client) WaitForInstanceAsyn(instanceId string, status InstanceStatus, timeout int) error {
|
||||
if timeout <= 0 {
|
||||
timeout = InstanceDefaultTimeout
|
||||
}
|
||||
for {
|
||||
instance, err := client.DescribeInstanceAttribute(instanceId)
|
||||
if err != nil {
|
||||
e, _ := err.(*common.Error)
|
||||
if e.ErrorResponse.Code != "InvalidInstanceId.NotFound" {
|
||||
return err
|
||||
}
|
||||
time.Sleep(DefaultWaitForInterval * time.Second)
|
||||
continue
|
||||
}
|
||||
if instance.Status == status {
|
||||
//TODO
|
||||
//Sleep one more time for timing issues
|
||||
time.Sleep(DefaultWaitForInterval * time.Second)
|
||||
break
|
||||
}
|
||||
timeout = timeout - DefaultWaitForInterval
|
||||
if timeout <= 0 {
|
||||
return common.GetClientErrorFromString("Timeout")
|
||||
}
|
||||
time.Sleep(DefaultWaitForInterval * time.Second)
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DescribeInstanceVncUrlArgs struct {
|
||||
RegionId common.Region
|
||||
InstanceId string
|
||||
|
@ -510,6 +545,43 @@ func (client *Client) CreateInstance(args *CreateInstanceArgs) (instanceId strin
|
|||
return response.InstanceId, err
|
||||
}
|
||||
|
||||
type RunInstanceArgs struct {
|
||||
CreateInstanceArgs
|
||||
MinAmount int
|
||||
MaxAmount int
|
||||
AutoReleaseTime string
|
||||
NetworkType string
|
||||
InnerIpAddress string
|
||||
BusinessInfo string
|
||||
}
|
||||
|
||||
type RunInstanceResponse struct {
|
||||
common.Response
|
||||
InstanceIdSets InstanceIdSets
|
||||
}
|
||||
|
||||
type InstanceIdSets struct {
|
||||
InstanceIdSet []string
|
||||
}
|
||||
|
||||
type BusinessInfo struct {
|
||||
Pack string `json:"pack,omitempty"`
|
||||
ActivityId string `json:"activityId,omitempty"`
|
||||
}
|
||||
|
||||
func (client *Client) RunInstances(args *RunInstanceArgs) (instanceIdSet []string, err error) {
|
||||
if args.UserData != "" {
|
||||
// Encode to base64 string
|
||||
args.UserData = base64.StdEncoding.EncodeToString([]byte(args.UserData))
|
||||
}
|
||||
response := RunInstanceResponse{}
|
||||
err = client.Invoke("RunInstances", args, &response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response.InstanceIdSets.InstanceIdSet, err
|
||||
}
|
||||
|
||||
type SecurityGroupArgs struct {
|
||||
InstanceId string
|
||||
SecurityGroupId string
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package alicloud
|
||||
package ecs
|
||||
|
||||
import (
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
"github.com/denverdino/aliyungo/ecs"
|
||||
)
|
||||
|
||||
type BandwidthPackageType struct {
|
||||
|
@ -25,6 +24,10 @@ type ForwardTableIdType struct {
|
|||
ForwardTableId []string
|
||||
}
|
||||
|
||||
type SnatTableIdType struct {
|
||||
SnatTableId []string
|
||||
}
|
||||
|
||||
type BandwidthPackageIdType struct {
|
||||
BandwidthPackageId []string
|
||||
}
|
||||
|
@ -39,7 +42,7 @@ type CreateNatGatewayResponse struct {
|
|||
// CreateNatGateway creates Virtual Private Cloud
|
||||
//
|
||||
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/vpc&createvpc
|
||||
func CreateNatGateway(client *ecs.Client, args *CreateNatGatewayArgs) (resp *CreateNatGatewayResponse, err error) {
|
||||
func (client *Client) CreateNatGateway(args *CreateNatGatewayArgs) (resp *CreateNatGatewayResponse, err error) {
|
||||
response := CreateNatGatewayResponse{}
|
||||
err = client.Invoke("CreateNatGateway", args, &response)
|
||||
if err != nil {
|
||||
|
@ -53,6 +56,7 @@ type NatGatewaySetType struct {
|
|||
Description string
|
||||
BandwidthPackageIds BandwidthPackageIdType
|
||||
ForwardTableIds ForwardTableIdType
|
||||
SnatTableIds SnatTableIdType
|
||||
InstanceChargeType string
|
||||
Name string
|
||||
NatGatewayId string
|
||||
|
@ -77,7 +81,7 @@ type DescribeNatGatewaysArgs struct {
|
|||
common.Pagination
|
||||
}
|
||||
|
||||
func DescribeNatGateways(client *ecs.Client, args *DescribeNatGatewaysArgs) (natGateways []NatGatewaySetType,
|
||||
func (client *Client) DescribeNatGateways(args *DescribeNatGatewaysArgs) (natGateways []NatGatewaySetType,
|
||||
pagination *common.PaginationResult, err error) {
|
||||
|
||||
args.Validate()
|
||||
|
@ -103,7 +107,7 @@ type ModifyNatGatewayAttributeResponse struct {
|
|||
common.Response
|
||||
}
|
||||
|
||||
func ModifyNatGatewayAttribute(client *ecs.Client, args *ModifyNatGatewayAttributeArgs) error {
|
||||
func (client *Client) ModifyNatGatewayAttribute(args *ModifyNatGatewayAttributeArgs) error {
|
||||
response := ModifyNatGatewayAttributeResponse{}
|
||||
return client.Invoke("ModifyNatGatewayAttribute", args, &response)
|
||||
}
|
||||
|
@ -114,7 +118,7 @@ type ModifyNatGatewaySpecArgs struct {
|
|||
Spec NatGatewaySpec
|
||||
}
|
||||
|
||||
func ModifyNatGatewaySpec(client *ecs.Client, args *ModifyNatGatewaySpecArgs) error {
|
||||
func (client *Client) ModifyNatGatewaySpec(args *ModifyNatGatewaySpecArgs) error {
|
||||
response := ModifyNatGatewayAttributeResponse{}
|
||||
return client.Invoke("ModifyNatGatewaySpec", args, &response)
|
||||
}
|
||||
|
@ -128,7 +132,7 @@ type DeleteNatGatewayResponse struct {
|
|||
common.Response
|
||||
}
|
||||
|
||||
func DeleteNatGateway(client *ecs.Client, args *DeleteNatGatewayArgs) error {
|
||||
func (client *Client) DeleteNatGateway(args *DeleteNatGatewayArgs) error {
|
||||
response := DeleteNatGatewayResponse{}
|
||||
err := client.Invoke("DeleteNatGateway", args, &response)
|
||||
return err
|
||||
|
@ -140,10 +144,20 @@ type DescribeBandwidthPackagesArgs struct {
|
|||
NatGatewayId string
|
||||
}
|
||||
|
||||
type PublicIpAddresseType struct {
|
||||
AllocationId string
|
||||
IpAddress string
|
||||
}
|
||||
|
||||
type DescribeBandwidthPackageType struct {
|
||||
Bandwidth string
|
||||
BandwidthPackageId string
|
||||
IpCount string
|
||||
PublicIpAddresses struct {
|
||||
PublicIpAddresse []PublicIpAddresseType
|
||||
}
|
||||
|
||||
ZoneId string
|
||||
}
|
||||
|
||||
type DescribeBandwidthPackagesResponse struct {
|
||||
|
@ -153,12 +167,14 @@ type DescribeBandwidthPackagesResponse struct {
|
|||
}
|
||||
}
|
||||
|
||||
func DescribeBandwidthPackages(client *ecs.Client, args *DescribeBandwidthPackagesArgs) ([]DescribeBandwidthPackageType, error) {
|
||||
func (client *Client) DescribeBandwidthPackages(args *DescribeBandwidthPackagesArgs) ([]DescribeBandwidthPackageType, error) {
|
||||
response := &DescribeBandwidthPackagesResponse{}
|
||||
|
||||
err := client.Invoke("DescribeBandwidthPackages", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return response.BandwidthPackages.BandwidthPackage, err
|
||||
}
|
||||
|
||||
|
@ -171,20 +187,12 @@ type DeleteBandwidthPackageResponse struct {
|
|||
common.Response
|
||||
}
|
||||
|
||||
func DeleteBandwidthPackage(client *ecs.Client, args *DeleteBandwidthPackageArgs) error {
|
||||
func (client *Client) DeleteBandwidthPackage(args *DeleteBandwidthPackageArgs) error {
|
||||
response := DeleteBandwidthPackageResponse{}
|
||||
err := client.Invoke("DeleteBandwidthPackage", args, &response)
|
||||
return err
|
||||
}
|
||||
|
||||
type DescribeSnatTableEntriesArgs struct {
|
||||
RegionId common.Region
|
||||
}
|
||||
|
||||
func DescribeSnatTableEntries(client *ecs.Client, args *DescribeSnatTableEntriesArgs) {
|
||||
|
||||
}
|
||||
|
||||
type NatGatewaySpec string
|
||||
|
||||
const (
|
|
@ -33,6 +33,7 @@ type DescribeSecurityGroupAttributeArgs struct {
|
|||
SecurityGroupId string
|
||||
RegionId common.Region
|
||||
NicType NicType //enum for internet (default) |intranet
|
||||
Direction string // enum ingress egress
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
package ecs
|
||||
|
||||
import "github.com/denverdino/aliyungo/common"
|
||||
|
||||
type CreateSnatEntryArgs struct {
|
||||
RegionId common.Region
|
||||
SnatTableId string
|
||||
SourceVSwitchId string
|
||||
SnatIp string
|
||||
}
|
||||
|
||||
type CreateSnatEntryResponse struct {
|
||||
common.Response
|
||||
SnatEntryId string
|
||||
}
|
||||
|
||||
type SnatEntrySetType struct {
|
||||
RegionId common.Region
|
||||
SnatEntryId string
|
||||
SnatIp string
|
||||
SnatTableId string
|
||||
SourceCIDR string
|
||||
SourceVSwitchId string
|
||||
Status string
|
||||
}
|
||||
|
||||
type DescribeSnatTableEntriesArgs struct {
|
||||
RegionId common.Region
|
||||
SnatTableId string
|
||||
common.Pagination
|
||||
}
|
||||
|
||||
type DescribeSnatTableEntriesResponse struct {
|
||||
common.Response
|
||||
common.PaginationResult
|
||||
SnatTableEntries struct {
|
||||
SnatTableEntry []SnatEntrySetType
|
||||
}
|
||||
}
|
||||
|
||||
type ModifySnatEntryArgs struct {
|
||||
RegionId common.Region
|
||||
SnatTableId string
|
||||
SnatEntryId string
|
||||
SnatIp string
|
||||
}
|
||||
|
||||
type ModifySnatEntryResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
type DeleteSnatEntryArgs struct {
|
||||
RegionId common.Region
|
||||
SnatTableId string
|
||||
SnatEntryId string
|
||||
}
|
||||
|
||||
type DeleteSnatEntryResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
func (client *Client) CreateSnatEntry(args *CreateSnatEntryArgs) (resp *CreateSnatEntryResponse, err error) {
|
||||
response := CreateSnatEntryResponse{}
|
||||
err = client.Invoke("CreateSnatEntry", args, &response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &response, err
|
||||
}
|
||||
|
||||
func (client *Client) DescribeSnatTableEntries(args *DescribeSnatTableEntriesArgs) (snatTableEntries []SnatEntrySetType,
|
||||
pagination *common.PaginationResult, err error) {
|
||||
|
||||
args.Validate()
|
||||
response := DescribeSnatTableEntriesResponse{}
|
||||
|
||||
err = client.Invoke("DescribeSnatTableEntries", args, &response)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return response.SnatTableEntries.SnatTableEntry, &response.PaginationResult, nil
|
||||
}
|
||||
|
||||
func (client *Client) ModifySnatEntry(args *ModifySnatEntryArgs) error {
|
||||
response := ModifySnatEntryResponse{}
|
||||
return client.Invoke("ModifySnatEntry", args, &response)
|
||||
}
|
||||
|
||||
func (client *Client) DeleteSnatEntry(args *DeleteSnatEntryArgs) error {
|
||||
response := DeleteSnatEntryResponse{}
|
||||
err := client.Invoke("DeleteSnatEntry", args, &response)
|
||||
return err
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package rds
|
||||
|
||||
import (
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
|
||||
"os"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
common.Client
|
||||
}
|
||||
|
||||
const (
|
||||
// ECSDefaultEndpoint is the default API endpoint of RDS services
|
||||
RDSDefaultEndpoint = "https://rds.aliyuncs.com"
|
||||
RDSAPIVersion = "2014-08-15"
|
||||
RDSServiceCode = "rds"
|
||||
)
|
||||
|
||||
// NewClient creates a new instance of RDS client
|
||||
func NewClient(accessKeyId, accessKeySecret string) *Client {
|
||||
endpoint := os.Getenv("RDS_ENDPOINT")
|
||||
if endpoint == "" {
|
||||
endpoint = RDSDefaultEndpoint
|
||||
}
|
||||
return NewClientWithEndpoint(endpoint, accessKeyId, accessKeySecret)
|
||||
}
|
||||
|
||||
func NewClientWithEndpoint(endpoint string, accessKeyId, accessKeySecret string) *Client {
|
||||
client := &Client{}
|
||||
client.Init(endpoint, RDSAPIVersion, accessKeyId, accessKeySecret)
|
||||
return client
|
||||
}
|
||||
|
||||
func NewRDSClient(accessKeyId, accessKeySecret string, regionID common.Region) *Client {
|
||||
endpoint := os.Getenv("RDS_ENDPOINT")
|
||||
if endpoint == "" {
|
||||
endpoint = RDSDefaultEndpoint
|
||||
}
|
||||
|
||||
return NewClientWithRegion(endpoint, accessKeyId, accessKeySecret, regionID)
|
||||
}
|
||||
|
||||
func NewClientWithRegion(endpoint string, accessKeyId, accessKeySecret string, regionID common.Region) *Client {
|
||||
client := &Client{}
|
||||
client.NewInit(endpoint, RDSAPIVersion, accessKeyId, accessKeySecret, RDSServiceCode, regionID)
|
||||
return client
|
||||
}
|
|
@ -0,0 +1,843 @@
|
|||
package rds
|
||||
|
||||
import (
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
"time"
|
||||
)
|
||||
|
||||
type DBInstanceIPArray struct {
|
||||
SecurityIps string
|
||||
DBInstanceIPArrayName string
|
||||
DBInstanceIPArrayAttribute string
|
||||
}
|
||||
|
||||
// ref: https://help.aliyun.com/document_detail/26242.html
|
||||
type ModifySecurityIpsArgs struct {
|
||||
DBInstanceId string
|
||||
DBInstanceIPArray
|
||||
}
|
||||
|
||||
func (client *Client) ModifySecurityIps(args *ModifySecurityIpsArgs) (resp common.Response, err error) {
|
||||
response := common.Response{}
|
||||
err = client.Invoke("ModifySecurityIps", args, &response)
|
||||
return response, err
|
||||
}
|
||||
|
||||
type DescribeDBInstanceIPsArgs struct {
|
||||
DBInstanceId string
|
||||
}
|
||||
|
||||
type DBInstanceIPList struct {
|
||||
DBInstanceIPArrayName string
|
||||
DBInstanceIPArrayAttribute string
|
||||
SecurityIPList string
|
||||
}
|
||||
|
||||
type DescribeDBInstanceIPsResponse struct {
|
||||
common.Response
|
||||
Items struct {
|
||||
DBInstanceIPArray []DBInstanceIPList
|
||||
}
|
||||
}
|
||||
|
||||
// DescribeDBInstanceIPArrayList describe security ips
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/26241.html?spm=5176.doc26242.6.715.d9pxvr
|
||||
func (client *Client) DescribeDBInstanceIPs(args *DescribeDBInstanceIPsArgs) (resp *DescribeDBInstanceIPsResponse, err error) {
|
||||
response := DescribeDBInstanceIPsResponse{}
|
||||
err = client.Invoke("DescribeDBInstanceIPArrayList", args, &response)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
// InstanceStatus represents instance status
|
||||
type InstanceStatus string
|
||||
|
||||
// Constants of InstanceStatus
|
||||
const (
|
||||
Creating = InstanceStatus("Creating") // For backward compatability
|
||||
Running = InstanceStatus("Running")
|
||||
Deleting = InstanceStatus("Deleting")
|
||||
Rebooting = InstanceStatus("Rebooting")
|
||||
|
||||
Restoring = InstanceStatus("Restoring")
|
||||
Importing = InstanceStatus("Importing")
|
||||
DBInstanceNetTypeChanging = InstanceStatus("DBInstanceNetTypeChanging")
|
||||
)
|
||||
|
||||
type DBPayType string
|
||||
|
||||
const (
|
||||
Prepaid = DBPayType("Prepaid")
|
||||
Postpaid = DBPayType("Postpaid")
|
||||
)
|
||||
|
||||
type CommodityCode string
|
||||
|
||||
const (
|
||||
Rds = CommodityCode("rds")
|
||||
Bards = CommodityCode("bards")
|
||||
Rords = CommodityCode("rords")
|
||||
)
|
||||
|
||||
type Engine string
|
||||
|
||||
const (
|
||||
MySQL = Engine("MySQL")
|
||||
SQLServer = Engine("SQLServer")
|
||||
PPAS = Engine("PPAS")
|
||||
PG = Engine("PG")
|
||||
)
|
||||
|
||||
type ConnectionMode string
|
||||
|
||||
const (
|
||||
Performance = ConnectionMode("Performance")
|
||||
Safty = ConnectionMode("Safty")
|
||||
)
|
||||
|
||||
// default resource value for create order
|
||||
const DefaultResource = "buy"
|
||||
|
||||
type CreateOrderArgs struct {
|
||||
CommodityCode CommodityCode
|
||||
RegionId common.Region
|
||||
ZoneId string
|
||||
Engine Engine
|
||||
EngineVersion string
|
||||
PayType DBPayType
|
||||
DBInstanceClass string
|
||||
DBInstanceStorage int
|
||||
DBInstanceNetType common.NetType
|
||||
InstanceNetworkType common.NetworkType
|
||||
VPCId string
|
||||
VSwitchId string
|
||||
UsedTime int
|
||||
TimeType common.TimeType
|
||||
Quantity int
|
||||
InstanceUsedType string
|
||||
Resource string
|
||||
AutoPay string
|
||||
AutoRenew string
|
||||
BackupId string
|
||||
RestoreTime string
|
||||
SecurityIPList string
|
||||
BusinessInfo string
|
||||
}
|
||||
|
||||
type CreateOrderResponse struct {
|
||||
common.Response
|
||||
DBInstanceId string
|
||||
OrderId int
|
||||
}
|
||||
|
||||
// CreateOrder create db instance order
|
||||
// you can read doc at http://docs.alibaba-inc.com/pages/viewpage.action?pageId=259349053
|
||||
func (client *Client) CreateOrder(args *CreateOrderArgs) (resp CreateOrderResponse, err error) {
|
||||
response := CreateOrderResponse{}
|
||||
err = client.Invoke("CreateOrder", args, &response)
|
||||
return response, err
|
||||
}
|
||||
|
||||
type DescribeDBInstancesArgs struct {
|
||||
DBInstanceId string
|
||||
}
|
||||
|
||||
type DescribeDBInstanceAttributeResponse struct {
|
||||
common.Response
|
||||
Items struct {
|
||||
DBInstanceAttribute []DBInstanceAttribute
|
||||
}
|
||||
}
|
||||
|
||||
type DBInstanceAttribute struct {
|
||||
DBInstanceId string
|
||||
PayType DBPayType
|
||||
DBInstanceType string
|
||||
InstanceNetworkType string
|
||||
ConnectionMode string
|
||||
RegionId string
|
||||
ZoneId string
|
||||
ConnectionString string
|
||||
Port string
|
||||
Engine Engine
|
||||
EngineVersion string
|
||||
DBInstanceClass string
|
||||
DBInstanceMemory int64
|
||||
DBInstanceStorage int
|
||||
DBInstanceNetType string
|
||||
DBInstanceStatus InstanceStatus
|
||||
DBInstanceDescription string
|
||||
LockMode string
|
||||
LockReason string
|
||||
DBMaxQuantity int
|
||||
AccountMaxQuantity int
|
||||
CreationTime string
|
||||
ExpireTime string
|
||||
MaintainTime string
|
||||
AvailabilityValue string
|
||||
MaxIOPS int
|
||||
MaxConnections int
|
||||
MasterInstanceId string
|
||||
IncrementSourceDBInstanceId string
|
||||
GuardDBInstanceId string
|
||||
TempDBInstanceId string
|
||||
ReadOnlyDBInstanceIds ReadOnlyDBInstanceIds
|
||||
SecurityIPList string
|
||||
}
|
||||
|
||||
type ReadOnlyDBInstanceIds struct {
|
||||
ReadOnlyDBInstanceId []string
|
||||
}
|
||||
|
||||
// DescribeDBInstanceAttribute describes db instance
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/26231.html?spm=5176.doc26228.6.702.uhzm31
|
||||
func (client *Client) DescribeDBInstanceAttribute(args *DescribeDBInstancesArgs) (resp *DescribeDBInstanceAttributeResponse, err error) {
|
||||
|
||||
response := DescribeDBInstanceAttributeResponse{}
|
||||
|
||||
err = client.Invoke("DescribeDBInstanceAttribute", args, &response)
|
||||
|
||||
if err == nil {
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
type DescribeDatabasesArgs struct {
|
||||
DBInstanceId string
|
||||
DBName string
|
||||
DBStatus InstanceStatus
|
||||
}
|
||||
|
||||
type DescribeDatabasesResponse struct {
|
||||
common.Response
|
||||
Databases struct {
|
||||
Database []Database
|
||||
}
|
||||
}
|
||||
|
||||
type Database struct {
|
||||
DBName string
|
||||
DBInstanceId string
|
||||
Engine string
|
||||
DBStatus InstanceStatus
|
||||
CharacterSetName InstanceStatus
|
||||
DBDescription InstanceStatus
|
||||
Account InstanceStatus
|
||||
AccountPrivilege InstanceStatus
|
||||
Accounts struct {
|
||||
AccountPrivilegeInfo []AccountPrivilegeInfo
|
||||
}
|
||||
}
|
||||
|
||||
type AccountPrivilegeInfo struct {
|
||||
Account string
|
||||
AccountPrivilege string
|
||||
}
|
||||
|
||||
// DescribeDatabases describes db database
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/26260.html?spm=5176.doc26258.6.732.gCx1a3
|
||||
func (client *Client) DescribeDatabases(args *DescribeDatabasesArgs) (resp *DescribeDatabasesResponse, err error) {
|
||||
|
||||
response := DescribeDatabasesResponse{}
|
||||
|
||||
err = client.Invoke("DescribeDatabases", args, &response)
|
||||
|
||||
if err == nil {
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
type DescribeAccountsArgs struct {
|
||||
DBInstanceId string
|
||||
AccountName string
|
||||
}
|
||||
|
||||
type DescribeAccountsResponse struct {
|
||||
common.Response
|
||||
Accounts struct {
|
||||
DBInstanceAccount []DBInstanceAccount
|
||||
}
|
||||
}
|
||||
|
||||
type DBInstanceAccount struct {
|
||||
DBInstanceId string
|
||||
AccountName string
|
||||
AccountStatus AccountStatus
|
||||
AccountDescription string
|
||||
DatabasePrivileges struct {
|
||||
DatabasePrivilege []DatabasePrivilege
|
||||
}
|
||||
}
|
||||
|
||||
type AccountStatus string
|
||||
|
||||
const (
|
||||
Unavailable = AccountStatus("Unavailable")
|
||||
Available = AccountStatus("Available")
|
||||
)
|
||||
|
||||
type DatabasePrivilege struct {
|
||||
DBName string
|
||||
AccountPrivilege AccountPrivilege
|
||||
}
|
||||
|
||||
// DescribeAccounts describes db accounts
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/26265.html?spm=5176.doc26266.6.739.UjtjaI
|
||||
func (client *Client) DescribeAccounts(args *DescribeAccountsArgs) (resp *DescribeAccountsResponse, err error) {
|
||||
|
||||
response := DescribeAccountsResponse{}
|
||||
|
||||
err = client.Invoke("DescribeAccounts", args, &response)
|
||||
|
||||
if err == nil {
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Default timeout value for WaitForInstance method
|
||||
const InstanceDefaultTimeout = 120
|
||||
const DefaultWaitForInterval = 10
|
||||
|
||||
// WaitForInstance waits for instance to given status
|
||||
func (client *Client) WaitForInstance(instanceId string, status InstanceStatus, timeout int) error {
|
||||
if timeout <= 0 {
|
||||
timeout = InstanceDefaultTimeout
|
||||
}
|
||||
for {
|
||||
args := DescribeDBInstancesArgs{
|
||||
DBInstanceId: instanceId,
|
||||
}
|
||||
|
||||
resp, err := client.DescribeDBInstanceAttribute(&args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if timeout <= 0 {
|
||||
return common.GetClientErrorFromString("Timeout")
|
||||
}
|
||||
|
||||
timeout = timeout - DefaultWaitForInterval
|
||||
time.Sleep(DefaultWaitForInterval * time.Second)
|
||||
|
||||
if len(resp.Items.DBInstanceAttribute) < 1 {
|
||||
continue
|
||||
}
|
||||
instance := resp.Items.DBInstanceAttribute[0]
|
||||
if instance.DBInstanceStatus == status {
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (client *Client) WaitForAllDatabase(instanceId string, databaseNames []string, status InstanceStatus, timeout int) error {
|
||||
if timeout <= 0 {
|
||||
timeout = InstanceDefaultTimeout
|
||||
}
|
||||
for {
|
||||
args := DescribeDatabasesArgs{
|
||||
DBInstanceId: instanceId,
|
||||
}
|
||||
|
||||
resp, err := client.DescribeDatabases(&args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if timeout <= 0 {
|
||||
return common.GetClientErrorFromString("Timeout")
|
||||
}
|
||||
|
||||
timeout = timeout - DefaultWaitForInterval
|
||||
time.Sleep(DefaultWaitForInterval * time.Second)
|
||||
|
||||
ready := 0
|
||||
|
||||
for _, nm := range databaseNames {
|
||||
for _, db := range resp.Databases.Database {
|
||||
if db.DBName == nm {
|
||||
if db.DBStatus == status {
|
||||
ready++
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ready == len(databaseNames) {
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (client *Client) WaitForAccount(instanceId string, accountName string, status AccountStatus, timeout int) error {
|
||||
if timeout <= 0 {
|
||||
timeout = InstanceDefaultTimeout
|
||||
}
|
||||
for {
|
||||
args := DescribeAccountsArgs{
|
||||
DBInstanceId: instanceId,
|
||||
AccountName: accountName,
|
||||
}
|
||||
|
||||
resp, err := client.DescribeAccounts(&args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
accs := resp.Accounts.DBInstanceAccount
|
||||
|
||||
if timeout <= 0 {
|
||||
return common.GetClientErrorFromString("Timeout")
|
||||
}
|
||||
|
||||
timeout = timeout - DefaultWaitForInterval
|
||||
time.Sleep(DefaultWaitForInterval * time.Second)
|
||||
|
||||
if len(accs) < 1 {
|
||||
continue
|
||||
}
|
||||
|
||||
acc := accs[0]
|
||||
|
||||
if acc.AccountStatus == status {
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (client *Client) WaitForPublicConnection(instanceId string, timeout int) error {
|
||||
if timeout <= 0 {
|
||||
timeout = InstanceDefaultTimeout
|
||||
}
|
||||
for {
|
||||
args := DescribeDBInstanceNetInfoArgs{
|
||||
DBInstanceId: instanceId,
|
||||
}
|
||||
|
||||
resp, err := client.DescribeDBInstanceNetInfo(&args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if timeout <= 0 {
|
||||
return common.GetClientErrorFromString("Timeout")
|
||||
}
|
||||
|
||||
timeout = timeout - DefaultWaitForInterval
|
||||
time.Sleep(DefaultWaitForInterval * time.Second)
|
||||
|
||||
ready := false
|
||||
for _, info := range resp.DBInstanceNetInfos.DBInstanceNetInfo {
|
||||
if info.IPType == Public {
|
||||
ready = true
|
||||
}
|
||||
}
|
||||
|
||||
if ready {
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (client *Client) WaitForAccountPrivilege(instanceId, accountName, dbName string, privilege AccountPrivilege, timeout int) error {
|
||||
if timeout <= 0 {
|
||||
timeout = InstanceDefaultTimeout
|
||||
}
|
||||
for {
|
||||
args := DescribeAccountsArgs{
|
||||
DBInstanceId: instanceId,
|
||||
AccountName: accountName,
|
||||
}
|
||||
|
||||
resp, err := client.DescribeAccounts(&args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
accs := resp.Accounts.DBInstanceAccount
|
||||
|
||||
if timeout <= 0 {
|
||||
return common.GetClientErrorFromString("Timeout")
|
||||
}
|
||||
|
||||
timeout = timeout - DefaultWaitForInterval
|
||||
time.Sleep(DefaultWaitForInterval * time.Second)
|
||||
|
||||
if len(accs) < 1 {
|
||||
continue
|
||||
}
|
||||
|
||||
acc := accs[0]
|
||||
|
||||
ready := false
|
||||
for _, dp := range acc.DatabasePrivileges.DatabasePrivilege {
|
||||
if dp.DBName == dbName && dp.AccountPrivilege == privilege {
|
||||
ready = true
|
||||
}
|
||||
}
|
||||
|
||||
if ready {
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DeleteDBInstanceArgs struct {
|
||||
DBInstanceId string
|
||||
}
|
||||
|
||||
type DeleteDBInstanceResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
// DeleteInstance deletes db instance
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/26229.html?spm=5176.doc26315.6.700.7SmyAT
|
||||
func (client *Client) DeleteInstance(instanceId string) error {
|
||||
args := DeleteDBInstanceArgs{DBInstanceId: instanceId}
|
||||
response := DeleteDBInstanceResponse{}
|
||||
err := client.Invoke("DeleteDBInstance", &args, &response)
|
||||
return err
|
||||
}
|
||||
|
||||
type DeleteDatabaseArgs struct {
|
||||
DBInstanceId string
|
||||
DBName string
|
||||
}
|
||||
|
||||
type DeleteDatabaseResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
// DeleteInstance deletes database
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/26259.html?spm=5176.doc26260.6.731.Abjwne
|
||||
func (client *Client) DeleteDatabase(instanceId, dbName string) error {
|
||||
args := DeleteDatabaseArgs{
|
||||
DBInstanceId: instanceId,
|
||||
DBName: dbName,
|
||||
}
|
||||
response := DeleteDatabaseResponse{}
|
||||
err := client.Invoke("DeleteDatabase", &args, &response)
|
||||
return err
|
||||
}
|
||||
|
||||
type DescribeRegionsArgs struct {
|
||||
}
|
||||
|
||||
type DescribeRegionsResponse struct {
|
||||
Regions struct {
|
||||
RDSRegion []RDSRegion
|
||||
}
|
||||
}
|
||||
|
||||
type RDSRegion struct {
|
||||
RegionId string
|
||||
ZoneId string
|
||||
}
|
||||
|
||||
// DescribeRegions describe rds regions
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/26243.html?spm=5176.doc26244.6.715.OSNUa8
|
||||
func (client *Client) DescribeRegions() (resp *DescribeRegionsResponse, err error) {
|
||||
args := DescribeRegionsArgs{}
|
||||
response := DescribeRegionsResponse{}
|
||||
err = client.Invoke("DescribeRegions", &args, &response)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
type CreateDatabaseResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
type CreateDatabaseArgs struct {
|
||||
DBInstanceId string
|
||||
DBName string
|
||||
CharacterSetName string
|
||||
DBDescription string
|
||||
}
|
||||
|
||||
// CreateDatabase create rds database
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/26243.html?spm=5176.doc26244.6.715.OSNUa8
|
||||
func (client *Client) CreateDatabase(args *CreateDatabaseArgs) (resp *CreateDatabaseResponse, err error) {
|
||||
response := CreateDatabaseResponse{}
|
||||
err = client.Invoke("CreateDatabase", args, &response)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
type CreateAccountResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
type AccountType struct {
|
||||
Normal string
|
||||
Super string
|
||||
}
|
||||
|
||||
type CreateAccountArgs struct {
|
||||
DBInstanceId string
|
||||
AccountName string
|
||||
AccountPassword string
|
||||
AccountType AccountType
|
||||
AccountDescription string
|
||||
}
|
||||
|
||||
// CreateAccount create rds account
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/26263.html?spm=5176.doc26240.6.736.ZDihok
|
||||
func (client *Client) CreateAccount(args *CreateAccountArgs) (resp *CreateAccountResponse, err error) {
|
||||
response := CreateAccountResponse{}
|
||||
err = client.Invoke("CreateAccount", args, &response)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
type DeleteAccountResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
type DeleteAccountArgs struct {
|
||||
DBInstanceId string
|
||||
AccountName string
|
||||
}
|
||||
|
||||
// DeleteAccount delete account
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/26264.html?spm=5176.doc26269.6.737.CvlZp6
|
||||
func (client *Client) DeleteAccount(instanceId, accountName string) (resp *DeleteAccountResponse, err error) {
|
||||
args := DeleteAccountArgs{
|
||||
DBInstanceId: instanceId,
|
||||
AccountName: accountName,
|
||||
}
|
||||
|
||||
response := DeleteAccountResponse{}
|
||||
err = client.Invoke("DeleteAccount", &args, &response)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
type GrantAccountPrivilegeResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
type GrantAccountPrivilegeArgs struct {
|
||||
DBInstanceId string
|
||||
AccountName string
|
||||
DBName string
|
||||
AccountPrivilege AccountPrivilege
|
||||
}
|
||||
|
||||
type AccountPrivilege string
|
||||
|
||||
const (
|
||||
ReadOnly = AccountPrivilege("ReadOnly")
|
||||
ReadWrite = AccountPrivilege("ReadWrite")
|
||||
)
|
||||
|
||||
// GrantAccountPrivilege grant database privilege to account
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/26266.html?spm=5176.doc26264.6.739.o2y01n
|
||||
func (client *Client) GrantAccountPrivilege(args *GrantAccountPrivilegeArgs) (resp *GrantAccountPrivilegeResponse, err error) {
|
||||
response := GrantAccountPrivilegeResponse{}
|
||||
err = client.Invoke("GrantAccountPrivilege", args, &response)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
type AllocateInstancePublicConnectionResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
type AllocateInstancePublicConnectionArgs struct {
|
||||
DBInstanceId string
|
||||
ConnectionStringPrefix string
|
||||
Port string
|
||||
}
|
||||
|
||||
// AllocateInstancePublicConnection allocate public connection
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/26234.html?spm=5176.doc26265.6.708.PdsJnL
|
||||
func (client *Client) AllocateInstancePublicConnection(args *AllocateInstancePublicConnectionArgs) (resp *AllocateInstancePublicConnectionResponse, err error) {
|
||||
response := AllocateInstancePublicConnectionResponse{}
|
||||
err = client.Invoke("AllocateInstancePublicConnection", args, &response)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
type DescribeDBInstanceNetInfoArgs struct {
|
||||
DBInstanceId string
|
||||
}
|
||||
|
||||
type DescribeDBInstanceNetInfoResponse struct {
|
||||
common.Response
|
||||
InstanceNetworkType string
|
||||
DBInstanceNetInfos struct {
|
||||
DBInstanceNetInfo []DBInstanceNetInfo
|
||||
}
|
||||
}
|
||||
|
||||
type DBInstanceNetInfo struct {
|
||||
ConnectionString string
|
||||
IPAddress string
|
||||
Port string
|
||||
VPCId string
|
||||
VSwitchId string
|
||||
IPType IPType
|
||||
}
|
||||
|
||||
type IPType string
|
||||
|
||||
const (
|
||||
Inner = IPType("Inner")
|
||||
Private = IPType("Private")
|
||||
Public = IPType("Public")
|
||||
)
|
||||
|
||||
// DescribeDBInstanceNetInfo describe rds net info
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/26237.html?spm=5176.doc26234.6.711.vHOktx
|
||||
func (client *Client) DescribeDBInstanceNetInfo(args *DescribeDBInstanceNetInfoArgs) (resp *DescribeDBInstanceNetInfoResponse, err error) {
|
||||
response := DescribeDBInstanceNetInfoResponse{}
|
||||
err = client.Invoke("DescribeDBInstanceNetInfo", args, &response)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
type BackupPolicy struct {
|
||||
PreferredBackupTime string // HH:mmZ - HH:mm Z
|
||||
PreferredBackupPeriod string // Monday - Sunday
|
||||
BackupRetentionPeriod int // 7 - 730
|
||||
BackupLog string // enum Enable | Disabled
|
||||
LogBackupRetentionPeriod string
|
||||
}
|
||||
|
||||
type ModifyBackupPolicyArgs struct {
|
||||
DBInstanceId string
|
||||
BackupPolicy
|
||||
}
|
||||
|
||||
type ModifyBackupPolicyResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
// ModifyBackupPolicy modify backup policy
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/26276.html?spm=5176.doc26250.6.751.KOew21
|
||||
func (client *Client) ModifyBackupPolicy(args *ModifyBackupPolicyArgs) (resp *ModifyBackupPolicyResponse, err error) {
|
||||
response := ModifyBackupPolicyResponse{}
|
||||
err = client.Invoke("ModifyBackupPolicy", args, &response)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
type DescribeBackupPolicyArgs struct {
|
||||
DBInstanceId string
|
||||
}
|
||||
|
||||
type DescribeBackupPolicyResponse struct {
|
||||
common.Response
|
||||
BackupPolicy
|
||||
}
|
||||
|
||||
// DescribeBackupPolicy describe backup policy
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/26275.html?spm=5176.doc26276.6.750.CUqjDn
|
||||
func (client *Client) DescribeBackupPolicy(args *DescribeBackupPolicyArgs) (resp *DescribeBackupPolicyResponse, err error) {
|
||||
response := DescribeBackupPolicyResponse{}
|
||||
err = client.Invoke("DescribeBackupPolicy", args, &response)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
type ModifyDBInstanceSpecArgs struct {
|
||||
DBInstanceId string
|
||||
PayType DBPayType
|
||||
DBInstanceClass string
|
||||
DBInstanceStorage string
|
||||
}
|
||||
|
||||
type ModifyDBInstanceSpecResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
// ModifyDBInstanceSpec modify db instance spec
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/26233.html?spm=5176.doc26258.6.707.2QOLrM
|
||||
func (client *Client) ModifyDBInstanceSpec(args *ModifyDBInstanceSpecArgs) (resp *ModifyDBInstanceSpecResponse, err error) {
|
||||
response := ModifyDBInstanceSpecResponse{}
|
||||
err = client.Invoke("ModifyDBInstanceSpec", args, &response)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
var WEEK_ENUM = []string{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}
|
||||
|
||||
var BACKUP_TIME = []string{
|
||||
"00:00Z-01:00Z", "01:00Z-02:00Z", "02:00Z-03:00Z", "03:00Z-04:00Z", "04:00Z-05:00Z",
|
||||
"05:00Z-06:00Z", "06:00Z-07:00Z", "07:00Z-08:00Z", "08:00Z-09:00Z", "09:00Z-10:00Z",
|
||||
"10:00Z-11:00Z", "11:00Z-12:00Z", "12:00Z-13:00Z", "13:00Z-14:00Z", "14:00Z-15:00Z",
|
||||
"15:00Z-16:00Z", "16:00Z-17:00Z", "17:00Z-18:00Z", "18:00Z-19:00Z", "19:00Z-20:00Z",
|
||||
"20:00Z-21:00Z", "21:00Z-22:00Z", "22:00Z-23:00Z", "23:00Z-24:00Z",
|
||||
}
|
||||
|
||||
var CHARACTER_SET_NAME = []string{
|
||||
"utf8", "gbk", "latin1", "utf8mb4",
|
||||
"Chinese_PRC_CI_AS", "Chinese_PRC_CS_AS", "SQL_Latin1_General_CP1_CI_AS", "SQL_Latin1_General_CP1_CS_AS", "Chinese_PRC_BIN",
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package rds
|
||||
|
||||
import (
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
"github.com/denverdino/aliyungo/util"
|
||||
)
|
||||
|
||||
type DescribeDBInstancePerformanceArgs struct {
|
||||
DBInstanceId string
|
||||
key string
|
||||
StartTime string
|
||||
EndTime string
|
||||
}
|
||||
|
||||
type PerformanceValueType struct {
|
||||
Value string
|
||||
Date util.ISO6801Time
|
||||
}
|
||||
|
||||
type PerformanceKeyType struct {
|
||||
Key string
|
||||
Unit string
|
||||
ValueFormat string
|
||||
Values struct {
|
||||
PerformanceValue []PerformanceValueType
|
||||
}
|
||||
}
|
||||
|
||||
type DescribeDBInstancePerformanceResponse struct {
|
||||
common.Response
|
||||
DBInstanceId string
|
||||
Engine string
|
||||
StartTime util.ISO6801Time
|
||||
EndTime util.ISO6801Time
|
||||
PerformanceKeys struct {
|
||||
PerformanceKey []PerformanceKeyType
|
||||
}
|
||||
}
|
||||
|
||||
func (client *DescribeDBInstancePerformanceArgs) Setkey(key string) {
|
||||
client.key = key
|
||||
}
|
||||
|
||||
func (client *Client) DescribeDBInstancePerformance(args *DescribeDBInstancePerformanceArgs) (resp DescribeDBInstancePerformanceResponse, err error) {
|
||||
|
||||
response := DescribeDBInstancePerformanceResponse{}
|
||||
err = client.Invoke("DescribeDBInstancePerformance", args, &response)
|
||||
return response, err
|
||||
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
package slb
|
||||
|
||||
import (
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
"os"
|
||||
|
||||
"github.com/denverdino/aliyungo/common"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
|
@ -13,6 +14,8 @@ const (
|
|||
// SLBDefaultEndpoint is the default API endpoint of SLB services
|
||||
SLBDefaultEndpoint = "https://slb.aliyuncs.com"
|
||||
SLBAPIVersion = "2014-05-15"
|
||||
|
||||
SLBServiceCode = "slb"
|
||||
)
|
||||
|
||||
// NewClient creates a new instance of ECS client
|
||||
|
@ -29,3 +32,18 @@ func NewClientWithEndpoint(endpoint string, accessKeyId, accessKeySecret string)
|
|||
client.Init(endpoint, SLBAPIVersion, accessKeyId, accessKeySecret)
|
||||
return client
|
||||
}
|
||||
|
||||
func NewSLBClient(accessKeyId, accessKeySecret string, regionID common.Region) *Client {
|
||||
endpoint := os.Getenv("SLB_ENDPOINT")
|
||||
if endpoint == "" {
|
||||
endpoint = SLBDefaultEndpoint
|
||||
}
|
||||
|
||||
return NewClientWithRegion(endpoint, accessKeyId, accessKeySecret, regionID)
|
||||
}
|
||||
|
||||
func NewClientWithRegion(endpoint string, accessKeyId, accessKeySecret string, regionID common.Region) *Client {
|
||||
client := &Client{}
|
||||
client.NewInit(endpoint, SLBAPIVersion, accessKeyId, accessKeySecret, SLBServiceCode, regionID)
|
||||
return client
|
||||
}
|
||||
|
|
|
@ -150,7 +150,7 @@ type TCPListenerType struct {
|
|||
HealthCheckConnectPort int
|
||||
HealthyThreshold int
|
||||
UnhealthyThreshold int
|
||||
HealthCheckTimeout int
|
||||
HealthCheckConnectTimeout int
|
||||
HealthCheckInterval int
|
||||
HealthCheckHttpCode HealthCheckHttpCodeType
|
||||
VServerGroupId string
|
||||
|
@ -177,7 +177,7 @@ type UDPListenerType struct {
|
|||
HealthCheckConnectPort int
|
||||
HealthyThreshold int
|
||||
UnhealthyThreshold int
|
||||
HealthCheckTimeout int
|
||||
HealthCheckConnectTimeout int
|
||||
HealthCheckInterval int
|
||||
VServerGroupId string
|
||||
}
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
package slb
|
||||
|
||||
import "github.com/denverdino/aliyungo/common"
|
||||
|
||||
type CreateRulesResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
type CreateRulesArgs struct {
|
||||
RegionId common.Region
|
||||
LoadBalancerId string
|
||||
ListenerPort int
|
||||
RuleList string
|
||||
}
|
||||
|
||||
type Rule struct {
|
||||
RuleId string
|
||||
RuleName string
|
||||
Domain string
|
||||
Url string `json:",omitempty"`
|
||||
VServerGroupId string
|
||||
}
|
||||
|
||||
// Create forward rules
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/35226.html?spm=5176.doc35226.6.671.625Omh
|
||||
func (client *Client) CreateRules(args *CreateRulesArgs) error {
|
||||
response := CreateRulesResponse{}
|
||||
err := client.Invoke("CreateRules", args, &response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
type DeleteRulesArgs struct {
|
||||
RegionId common.Region
|
||||
RuleIds string
|
||||
}
|
||||
|
||||
type DeleteRulesResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
// Delete forward rules
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/35227.html?spm=5176.doc35226.6.672.6iNBtR
|
||||
func (client *Client) DeleteRules(args *DeleteRulesArgs) error {
|
||||
response := DeleteRulesResponse{}
|
||||
err := client.Invoke("DeleteRules", args, &response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
type SetRuleArgs struct {
|
||||
RegionId common.Region
|
||||
RuleId string
|
||||
VServerGroupId string
|
||||
}
|
||||
|
||||
type SetRuleResponse struct {
|
||||
common.Response
|
||||
}
|
||||
|
||||
// Modify forward rules
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/35228.html?spm=5176.doc35227.6.673.rq40a9
|
||||
func (client *Client) SetRule(args *SetRuleArgs) error {
|
||||
response := SetRuleResponse{}
|
||||
err := client.Invoke("SetRule", args, &response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
type DescribeRuleAttributeArgs struct {
|
||||
RegionId common.Region
|
||||
RuleId string
|
||||
}
|
||||
|
||||
type DescribeRuleAttributeResponse struct {
|
||||
common.Response
|
||||
LoadBalancerId string
|
||||
ListenerPort int
|
||||
Rule
|
||||
}
|
||||
|
||||
// Describe rule
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/35229.html?spm=5176.doc35226.6.674.DRJeKJ
|
||||
func (client *Client) DescribeRuleAttribute(args *DescribeRuleAttributeArgs) (*DescribeRuleAttributeResponse, error) {
|
||||
response := &DescribeRuleAttributeResponse{}
|
||||
err := client.Invoke("DescribeRuleAttribute", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
type DescribeRulesArgs struct {
|
||||
RegionId common.Region
|
||||
LoadBalancerId string
|
||||
ListenerPort int
|
||||
}
|
||||
|
||||
type DescribeRulesResponse struct {
|
||||
common.Response
|
||||
Rules struct {
|
||||
Rule []Rule
|
||||
}
|
||||
}
|
||||
|
||||
// Describe rule
|
||||
//
|
||||
// You can read doc at https://help.aliyun.com/document_detail/35229.html?spm=5176.doc35226.6.674.DRJeKJ
|
||||
func (client *Client) DescribeRules(args *DescribeRulesArgs) (*DescribeRulesResponse, error) {
|
||||
response := &DescribeRulesResponse{}
|
||||
err := client.Invoke("DescribeRules", args, response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, nil
|
||||
}
|
|
@ -23,7 +23,6 @@ type AddBackendServersResponse struct {
|
|||
|
||||
type SetBackendServersResponse AddBackendServersResponse
|
||||
|
||||
|
||||
// SetBackendServers set weight of backend servers
|
||||
|
||||
func (client *Client) SetBackendServers(loadBalancerId string, backendServers []BackendServerType) (result []BackendServerType, err error) {
|
||||
|
@ -42,7 +41,6 @@ func (client *Client) SetBackendServers(loadBalancerId string, backendServers []
|
|||
return response.BackendServers.BackendServer, err
|
||||
}
|
||||
|
||||
|
||||
// AddBackendServers Add backend servers
|
||||
//
|
||||
// You can read doc at http://docs.aliyun.com/#/pub/slb/api-reference/api-related-backendserver&AddBackendServers
|
||||
|
|
|
@ -1292,28 +1292,34 @@
|
|||
"revisionTime": "2016-10-29T20:57:26Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "ADySw3nBHyzEHB6afBSeVRN2A4g=",
|
||||
"checksumSHA1": "SdiAYZOqWQ60ifRUHLwLiDMKMYA=",
|
||||
"path": "github.com/denverdino/aliyungo/common",
|
||||
"revision": "d123f5d1fa71b211b70b2e9b56a62da21076884a",
|
||||
"revisionTime": "2017-01-17T10:57:15Z"
|
||||
"revision": "c4c75afbf7ea86e66672c1b6ed981385b4ad5ec2",
|
||||
"revisionTime": "2017-03-21T07:55:32Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "9ZY3RlumKp5DAMfL08YwMoOOT2o=",
|
||||
"checksumSHA1": "UVYu5rvfoXgJnIpUyGcaovMvpms=",
|
||||
"path": "github.com/denverdino/aliyungo/ecs",
|
||||
"revision": "d123f5d1fa71b211b70b2e9b56a62da21076884a",
|
||||
"revisionTime": "2017-01-17T10:57:15Z"
|
||||
"revision": "c4c75afbf7ea86e66672c1b6ed981385b4ad5ec2",
|
||||
"revisionTime": "2017-03-21T07:55:32Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "QlA7zv05k7HWeR3tg4uHqIlFcg8=",
|
||||
"checksumSHA1": "riQMe2AR7qkLRkQ/MSr8gQp3zL4=",
|
||||
"path": "github.com/denverdino/aliyungo/rds",
|
||||
"revision": "c4c75afbf7ea86e66672c1b6ed981385b4ad5ec2",
|
||||
"revisionTime": "2017-03-21T07:55:32Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "2g6VZONB51rul5YuSBvngH6u4A0=",
|
||||
"path": "github.com/denverdino/aliyungo/slb",
|
||||
"revision": "d123f5d1fa71b211b70b2e9b56a62da21076884a",
|
||||
"revisionTime": "2017-01-17T10:57:15Z"
|
||||
"revision": "c4c75afbf7ea86e66672c1b6ed981385b4ad5ec2",
|
||||
"revisionTime": "2017-03-21T07:55:32Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "Lp0KtT7ycgq31ox3Uzhpxyw0U+Y=",
|
||||
"path": "github.com/denverdino/aliyungo/util",
|
||||
"revision": "d123f5d1fa71b211b70b2e9b56a62da21076884a",
|
||||
"revisionTime": "2017-01-17T10:57:15Z"
|
||||
"revision": "c4c75afbf7ea86e66672c1b6ed981385b4ad5ec2",
|
||||
"revisionTime": "2017-03-21T07:55:32Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "yDQQpeUxwqB3C+4opweg6znWJQk=",
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
---
|
||||
layout: "alicloud"
|
||||
page_title: "Alicloud: alicloud_db_instance"
|
||||
sidebar_current: "docs-alicloud-resource-db-instance"
|
||||
description: |-
|
||||
Provides an RDS instance resource.
|
||||
---
|
||||
|
||||
# alicloud\_db\_instance
|
||||
|
||||
Provides an RDS instance resource. A DB instance is an isolated database
|
||||
environment in the cloud. A DB instance can contain multiple user-created
|
||||
databases.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
resource "alicloud_db_instance" "default" {
|
||||
commodity_code = "rds"
|
||||
engine = "MySQL"
|
||||
engine_version = "5.6"
|
||||
db_instance_class = "rds.mysql.t1.small"
|
||||
db_instance_storage = "10"
|
||||
db_instance_net_type = "Intranet"
|
||||
}
|
||||
```
|
||||
|
||||
## Argument Reference
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
* `engine` - (Required) Database type. Value options: MySQL, SQLServer, PostgreSQL, and PPAS.
|
||||
* `engine_version` - (Required) Database version. Value options:
|
||||
- 5.5/5.6/5.7 for MySQL
|
||||
- 2008r2/2012 for SQLServer
|
||||
- 9.4 for PostgreSQL
|
||||
- 9.3 for PPAS
|
||||
* `db_instance_class` - (Required) Instance type. For details, see [Instance type table](https://intl.aliyun.com/help/doc-detail/26312.htm?spm=a3c0i.o26228en.a3.2.bRUHF3).
|
||||
* `db_instance_storage` - (Required) User-defined storage space. Value range:
|
||||
- [5, 2000] for MySQL/PostgreSQL/PPAS HA dual node edition;
|
||||
- [20,1000] for MySQL 5.7 basic single node edition;
|
||||
- [10, 2000] for SQL Server 2008R2;
|
||||
- [20,2000] for SQL Server 2012 basic single node edition
|
||||
Increase progressively at a rate of 5 GB. The unit is GB. For details, see [Instance type table](https://intl.aliyun.com/help/doc-detail/26312.htm?spm=a3c0i.o26228en.a3.3.bRUHF3).
|
||||
* `instance_charge_type` - (Optional) Valid values are `Prepaid`, `Postpaid`, The default is `Postpaid`.
|
||||
* `period` - (Optional) The time that you have bought the resource, in month. Only valid when instance_charge_type is set as `PrePaid`. Value range [1, 12].
|
||||
* `zone_id` - (Optional) Selected zone to create database instance. You cannot set the ZoneId parameter if the MultiAZ parameter is set to true.
|
||||
* `multi_az` - (Optional) Specifies if the database instance is a multiple Availability Zone deployment.
|
||||
* `db_instance_net_type` - (Optional) Network connection type of an instance. Internet: public network; Intranet: private network
|
||||
* `allocate_public_connection` - (Optional) If set to true will applies for an Internet connection string of an instance.
|
||||
* `instance_network_type` - (Optional) VPC: VPC instance; Classic: classic instance. If no value is specified, a classic instance will be created by default.
|
||||
* `vswitch_id` - (Optional) The virtual switch ID to launch in VPC. If you want to create instances in VPC network, this parameter must be set.
|
||||
* `master_user_name` - (Optional) The master user name for the database instance. Operation account requiring a uniqueness check. It may consist of lower case letters, numbers and underlines, and must start with a letter and have no more than 16 characters.
|
||||
* `master_user_password` - (Optional) The master password for the database instance. Operation password. It may consist of letters, digits, or underlines, with a length of 6 to 32 characters.
|
||||
* `preferred_backup_period` - (Optional) Backup period. Values: Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, and Sunday.
|
||||
* `preferred_backup_time` - (Optional) Backup time, in the format ofHH:mmZ- HH:mm Z.
|
||||
* `backup_retention_period` - (Optional) Retention days of the backup (7 to 730 days). The default value is 7 days.
|
||||
* `security_ips` - (Optional) List of IP addresses under the IP address white list array. The list contains up to 1,000 IP addresses, separated by commas. Supported formats include 0.0.0.0/0, 10.23.12.24 (IP), and 10.23.12.24/24 (Classless Inter-Domain Routing (CIDR) mode. /24 represents the length of the prefix in an IP address. The range of the prefix length is [1,32]).
|
||||
* `db_mappings` - (Optional) Database mappings to attach to db instance. See [Block database](#block-database) below for details.
|
||||
|
||||
|
||||
## Block database
|
||||
|
||||
The database mapping supports the following:
|
||||
|
||||
* `db_name` - (Required) Name of the database requiring a uniqueness check. It may consist of lower case letters, numbers and underlines, and must start with a letter and have no more than 64 characters.
|
||||
* `character_set_name` - (Required) Character set. The value range is limited to the following:
|
||||
- MySQL type:
|
||||
+ utf8
|
||||
+ gbk
|
||||
+ latin1
|
||||
+ utf8mb4 (included in versions 5.5 and 5.6).
|
||||
- SQLServer type:
|
||||
+ Chinese_PRC_CI_AS
|
||||
+ Chinese_PRC_CS_AS
|
||||
+ SQL_Latin1_General_CP1_CI_AS
|
||||
+ SQL_Latin1_General_CP1_CS_AS
|
||||
+ Chinese_PRC_BIN
|
||||
* `db_description` - (Optional) Database description, which cannot exceed 256 characters. NOTE: It cannot begin with https://.
|
||||
|
||||
|
||||
~> **NOTE:** We neither support modify any of database attribute, nor insert/remove item at the same time.
|
||||
We recommend split to two separate operations.
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
The following attributes are exported:
|
||||
|
||||
* `id` - The RDS instance ID.
|
||||
* `instance_charge_type` - The instance charge type.
|
||||
* `period` - The time that you have bought the resource.
|
||||
* `engine` - Database type.
|
||||
* `engine_version` - The database engine version.
|
||||
* `db_instance_class` - The RDS instance class.
|
||||
* `db_instance_storage` - The amount of allocated storage.
|
||||
* `port` - The database port.
|
||||
* `zone_id` - The zone ID of the DB instance.
|
||||
* `db_instance_net_type` - Network connection type of an instance, `Internet` or `Intranet`.
|
||||
* `instance_network_type` - The instance network type and it has two values: `vpc` and `classic`.
|
||||
* `db_mappings` - Database mappings attached to db instance.
|
||||
* `preferred_backup_period` - Backup period.
|
||||
* `preferred_backup_time` - Backup time.
|
||||
* `backup_retention_period` - Retention days of the backup.
|
||||
* `security_ips` - Security ips of instance whitelist.
|
||||
* `connections` - Views all the connection information of a specified instance.
|
||||
|
|
@ -54,16 +54,14 @@ resource "alicloud_slb" "vpc" {
|
|||
|
||||
The following arguments are supported:
|
||||
|
||||
* `availability_zone` - (Required) The Zone to start the instance in.
|
||||
* `image_id` - (Required) The Image to use for the instance.
|
||||
* `instance_type` - (Required) The type of instance to start.
|
||||
* `security_group_ids` - (Required) A list of security group ids to associate with. If you are creating Instances in a VPC, use `vpc_security_group_ids` instead.
|
||||
`security_group_ids` instead.
|
||||
* `io_optimized` - (Required) Valid values are `none`, `optimized`, If `optimized`, the launched ECS instance will be I/O optimized.
|
||||
* `security_group_ids` - (Optional) A list of security group ids to associate with.
|
||||
* `availability_zone` - (Optional) The Zone to start the instance in.
|
||||
* `instance_name` - (Optional) The name of the ECS. This instance_name can have a string of 2 to 128 characters, must contain only alphanumeric characters or hyphens, such as "-",".","_", and must not begin or end with a hyphen, and must not begin with http:// or https://. If not specified,
|
||||
Terraform will autogenerate a name beginning with `tf-ecs`.
|
||||
Terraform will autogenerate a default name is `ECS-Instance`.
|
||||
* `allocate_public_ip` - (Optional) Associate a public ip address with an instance in a VPC or Classic. Boolean value, Default is false.
|
||||
* `io_optimized` - (Optional) Valid
|
||||
values are `none`, `optimized`, If `optimized`, the launched ECS instance will be I/O optimized. Default is `optimized`.
|
||||
* `system_disk_category` - (Optional) Valid values are `cloud`, `cloud_efficiency`, `cloud_ssd`, For I/O optimized instance type, `cloud_ssd` and `cloud_efficiency` disks are supported. For non I/O Optimized instance type, `cloud` disk are supported.
|
||||
* `system_disk_size` - (Optional) Size of the system disk, value range: 40GB ~ 500GB. Default is 40GB.
|
||||
* `description` - (Optional) Description of the instance, This description can have a string of 2 to 256 characters, It cannot begin with http:// or https://. Default value is null.
|
||||
|
@ -77,7 +75,6 @@ On other OSs such as Linux, the host name can contain a maximum of 30 characters
|
|||
* `vswitch_id` - (Optional) The virtual switch ID to launch in VPC. If you want to create instances in VPC network, this parameter must be set.
|
||||
* `instance_charge_type` - (Optional) Valid values are `PrePaid`, `PostPaid`, The default is `PostPaid`.
|
||||
* `period` - (Optional) The time that you have bought the resource, in month. Only valid when instance_charge_type is set as `PrePaid`. Value range [1, 12].
|
||||
* `private_ip` - (Optional) Private IP address to associate with the instance in a VPC.
|
||||
* `tags` - (Optional) A mapping of tags to assign to the resource.
|
||||
|
||||
## Attributes Reference
|
||||
|
|
Loading…
Reference in New Issue