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 (
|
import (
|
||||||
"github.com/denverdino/aliyungo/common"
|
"github.com/denverdino/aliyungo/common"
|
||||||
|
"github.com/denverdino/aliyungo/ecs"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -12,8 +13,12 @@ const (
|
||||||
VpcNet = InstanceNetWork("vpc")
|
VpcNet = InstanceNetWork("vpc")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// timeout for common product, ecs e.g.
|
||||||
const defaultTimeout = 120
|
const defaultTimeout = 120
|
||||||
|
|
||||||
|
// timeout for long time progerss product, rds e.g.
|
||||||
|
const defaultLongTimeout = 800
|
||||||
|
|
||||||
func getRegion(d *schema.ResourceData, meta interface{}) common.Region {
|
func getRegion(d *schema.ResourceData, meta interface{}) common.Region {
|
||||||
return meta.(*AliyunClient).Region
|
return meta.(*AliyunClient).Region
|
||||||
}
|
}
|
||||||
|
@ -50,3 +55,26 @@ func isProtocalValid(value string) bool {
|
||||||
}
|
}
|
||||||
return res
|
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/common"
|
||||||
"github.com/denverdino/aliyungo/ecs"
|
"github.com/denverdino/aliyungo/ecs"
|
||||||
|
"github.com/denverdino/aliyungo/rds"
|
||||||
"github.com/denverdino/aliyungo/slb"
|
"github.com/denverdino/aliyungo/slb"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -19,8 +20,11 @@ type Config struct {
|
||||||
type AliyunClient struct {
|
type AliyunClient struct {
|
||||||
Region common.Region
|
Region common.Region
|
||||||
ecsconn *ecs.Client
|
ecsconn *ecs.Client
|
||||||
vpcconn *ecs.Client
|
rdsconn *rds.Client
|
||||||
slbconn *slb.Client
|
// use new version
|
||||||
|
ecsNewconn *ecs.Client
|
||||||
|
vpcconn *ecs.Client
|
||||||
|
slbconn *slb.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client for AliyunClient
|
// Client for AliyunClient
|
||||||
|
@ -35,6 +39,17 @@ func (c *Config) Client() (*AliyunClient, error) {
|
||||||
return nil, err
|
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()
|
slbconn, err := c.slbConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -46,13 +61,17 @@ func (c *Config) Client() (*AliyunClient, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return &AliyunClient{
|
return &AliyunClient{
|
||||||
Region: c.Region,
|
Region: c.Region,
|
||||||
ecsconn: ecsconn,
|
ecsconn: ecsconn,
|
||||||
vpcconn: vpcconn,
|
ecsNewconn: ecsNewconn,
|
||||||
slbconn: slbconn,
|
vpcconn: vpcconn,
|
||||||
|
slbconn: slbconn,
|
||||||
|
rdsconn: rdsconn,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const BusinessInfoKey = "Terraform"
|
||||||
|
|
||||||
func (c *Config) loadAndValidate() error {
|
func (c *Config) loadAndValidate() error {
|
||||||
err := c.validateRegion()
|
err := c.validateRegion()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -74,7 +93,9 @@ func (c *Config) validateRegion() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) ecsConn() (*ecs.Client, 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()
|
_, err := client.DescribeRegions()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -84,20 +105,21 @@ func (c *Config) ecsConn() (*ecs.Client, error) {
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) slbConn() (*slb.Client, error) {
|
func (c *Config) rdsConn() (*rds.Client, error) {
|
||||||
client := slb.NewClient(c.AccessKey, c.SecretKey)
|
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
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) vpcConn() (*ecs.Client, error) {
|
func (c *Config) vpcConn() (*ecs.Client, error) {
|
||||||
_, err := c.ecsConn()
|
client := ecs.NewVPCClient(c.AccessKey, c.SecretKey, c.Region)
|
||||||
|
client.SetBusinessInfo(BusinessInfoKey)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
client := &ecs.Client{}
|
|
||||||
client.Init("https://vpc.aliyuncs.com/", "2016-04-28", c.AccessKey, c.SecretKey)
|
|
||||||
return client, nil
|
return client, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,10 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/denverdino/aliyungo/ecs"
|
"github.com/denverdino/aliyungo/ecs"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func dataSourceAlicloudImages() *schema.Resource {
|
func dataSourceAlicloudImages() *schema.Resource {
|
||||||
|
@ -175,15 +175,28 @@ func dataSourceAlicloudImagesRead(d *schema.ResourceData, meta interface{}) erro
|
||||||
params.ImageOwnerAlias = ecs.ImageOwnerAlias(owners.(string))
|
params.ImageOwnerAlias = ecs.ImageOwnerAlias(owners.(string))
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, _, err := conn.DescribeImages(params)
|
var allImages []ecs.ImageType
|
||||||
if err != nil {
|
|
||||||
return err
|
for {
|
||||||
|
images, paginationResult, err := conn.DescribeImages(params)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
allImages = append(allImages, images...)
|
||||||
|
|
||||||
|
pagination := paginationResult.NextPage()
|
||||||
|
if pagination == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
params.Pagination = *pagination
|
||||||
}
|
}
|
||||||
|
|
||||||
var filteredImages []ecs.ImageType
|
var filteredImages []ecs.ImageType
|
||||||
if nameRegexOk {
|
if nameRegexOk {
|
||||||
r := regexp.MustCompile(nameRegex.(string))
|
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
|
// Check for a very rare case where the response would include no
|
||||||
// image name. No name means nothing to attempt a match against,
|
// image name. No name means nothing to attempt a match against,
|
||||||
// therefore we are skipping such image.
|
// therefore we are skipping such image.
|
||||||
|
@ -198,7 +211,7 @@ func dataSourceAlicloudImagesRead(d *schema.ResourceData, meta interface{}) erro
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
filteredImages = resp[:]
|
filteredImages = allImages[:]
|
||||||
}
|
}
|
||||||
|
|
||||||
var images []ecs.ImageType
|
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
|
// Instance store test - using centos images
|
||||||
const testAccCheckAlicloudImagesDataSourceImagesConfig = `
|
const testAccCheckAlicloudImagesDataSourceImagesConfig = `
|
||||||
data "alicloud_images" "multi_image" {
|
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}.*"
|
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(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAlicloudDataSourceID("data.alicloud_instance_types.4c8g"),
|
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.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.memory_size", "8"),
|
||||||
resource.TestCheckResourceAttr("data.alicloud_instance_types.4c8g", "instance_types.0.id", "ecs.s3.large"),
|
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(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAlicloudDataSourceID("data.alicloud_regions.empty_params_region"),
|
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.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.region_id", "cn-shenzhen"),
|
||||||
resource.TestCheckResourceAttr("data.alicloud_regions.empty_params_region", "regions.0.local_name", "华南 1"),
|
resource.TestCheckResourceAttr("data.alicloud_regions.empty_params_region", "regions.0.local_name", "华南 1"),
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
package alicloud
|
package alicloud
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"github.com/hashicorp/terraform/helper/resource"
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -23,6 +26,7 @@ func TestAccAlicloudZonesDataSource_basic(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAccAlicloudZonesDataSource_filter(t *testing.T) {
|
func TestAccAlicloudZonesDataSource_filter(t *testing.T) {
|
||||||
|
|
||||||
resource.Test(t, resource.TestCase{
|
resource.Test(t, resource.TestCase{
|
||||||
PreCheck: func() {
|
PreCheck: func() {
|
||||||
testAccPreCheck(t)
|
testAccPreCheck(t)
|
||||||
|
@ -33,7 +37,7 @@ func TestAccAlicloudZonesDataSource_filter(t *testing.T) {
|
||||||
Config: testAccCheckAlicloudZonesDataSourceFilter,
|
Config: testAccCheckAlicloudZonesDataSourceFilter,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAlicloudDataSourceID("data.alicloud_zones.foo"),
|
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,
|
Config: testAccCheckAlicloudZonesDataSourceFilterIoOptimized,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckAlicloudDataSourceID("data.alicloud_zones.foo"),
|
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 = `
|
const testAccCheckAlicloudZonesDataSourceBasicConfig = `
|
||||||
data "alicloud_zones" "foo" {
|
data "alicloud_zones" "foo" {
|
||||||
}
|
}
|
||||||
|
@ -55,16 +105,28 @@ data "alicloud_zones" "foo" {
|
||||||
|
|
||||||
const testAccCheckAlicloudZonesDataSourceFilter = `
|
const testAccCheckAlicloudZonesDataSourceFilter = `
|
||||||
data "alicloud_zones" "foo" {
|
data "alicloud_zones" "foo" {
|
||||||
"available_instance_type"= "ecs.c2.xlarge"
|
available_instance_type= "ecs.c2.xlarge"
|
||||||
"available_resource_creation"= "VSwitch"
|
available_resource_creation= "VSwitch"
|
||||||
"available_disk_category"= "cloud_efficiency"
|
available_disk_category= "cloud_efficiency"
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const testAccCheckAlicloudZonesDataSourceFilterIoOptimized = `
|
const testAccCheckAlicloudZonesDataSourceFilterIoOptimized = `
|
||||||
data "alicloud_zones" "foo" {
|
data "alicloud_zones" "foo" {
|
||||||
"available_instance_type"= "ecs.c2.xlarge"
|
available_instance_type= "ecs.c2.xlarge"
|
||||||
"available_resource_creation"= "IoOptimized"
|
available_resource_creation= "IoOptimized"
|
||||||
"available_disk_category"= "cloud"
|
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"
|
DiskIncorrectStatus = "IncorrectDiskStatus"
|
||||||
DiskCreatingSnapshot = "DiskCreatingSnapshot"
|
DiskCreatingSnapshot = "DiskCreatingSnapshot"
|
||||||
InstanceLockedForSecurity = "InstanceLockedForSecurity"
|
InstanceLockedForSecurity = "InstanceLockedForSecurity"
|
||||||
|
SystemDiskNotFound = "SystemDiskNotFound"
|
||||||
// eip
|
// eip
|
||||||
EipIncorrectStatus = "IncorrectEipStatus"
|
EipIncorrectStatus = "IncorrectEipStatus"
|
||||||
InstanceIncorrectStatus = "IncorrectInstanceStatus"
|
InstanceIncorrectStatus = "IncorrectInstanceStatus"
|
||||||
|
|
|
@ -30,3 +30,8 @@ const (
|
||||||
GroupRulePolicyAccept = GroupRulePolicy("accept")
|
GroupRulePolicyAccept = GroupRulePolicy("accept")
|
||||||
GroupRulePolicyDrop = GroupRulePolicy("drop")
|
GroupRulePolicyDrop = GroupRulePolicy("drop")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
EcsApiVersion20160314 = "2016-03-14"
|
||||||
|
EcsApiVersion20140526 = "2014-05-26"
|
||||||
|
)
|
||||||
|
|
|
@ -8,13 +8,41 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Listener struct {
|
type Listener struct {
|
||||||
|
slb.HTTPListenerType
|
||||||
|
|
||||||
InstancePort int
|
InstancePort int
|
||||||
LoadBalancerPort int
|
LoadBalancerPort int
|
||||||
Protocol string
|
Protocol string
|
||||||
|
//tcp & udp
|
||||||
|
PersistenceTimeout int
|
||||||
|
|
||||||
|
//https
|
||||||
SSLCertificateId string
|
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
|
// Takes the result of flatmap.Expand for an array of listeners and
|
||||||
// returns ELB API compatible objects
|
// returns ELB API compatible objects
|
||||||
func expandListeners(configured []interface{}) ([]*Listener, error) {
|
func expandListeners(configured []interface{}) ([]*Listener, error) {
|
||||||
|
@ -31,13 +59,78 @@ func expandListeners(configured []interface{}) ([]*Listener, error) {
|
||||||
InstancePort: ip,
|
InstancePort: ip,
|
||||||
LoadBalancerPort: lp,
|
LoadBalancerPort: lp,
|
||||||
Protocol: data["lb_protocol"].(string),
|
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 {
|
if v, ok := data["ssl_certificate_id"]; ok {
|
||||||
l.SSLCertificateId = v.(string)
|
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
|
var valid bool
|
||||||
if l.SSLCertificateId != "" {
|
if l.SSLCertificateId != "" {
|
||||||
// validate the protocol is correct
|
// validate the protocol is correct
|
||||||
|
|
|
@ -26,7 +26,7 @@ func Provider() terraform.ResourceProvider {
|
||||||
"region": &schema.Schema{
|
"region": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
Required: true,
|
||||||
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_REGION", "cn-beijing"),
|
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_REGION", DEFAULT_REGION),
|
||||||
Description: descriptions["region"],
|
Description: descriptions["region"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -43,6 +43,7 @@ func Provider() terraform.ResourceProvider {
|
||||||
"alicloud_disk_attachment": resourceAliyunDiskAttachment(),
|
"alicloud_disk_attachment": resourceAliyunDiskAttachment(),
|
||||||
"alicloud_security_group": resourceAliyunSecurityGroup(),
|
"alicloud_security_group": resourceAliyunSecurityGroup(),
|
||||||
"alicloud_security_group_rule": resourceAliyunSecurityGroupRule(),
|
"alicloud_security_group_rule": resourceAliyunSecurityGroupRule(),
|
||||||
|
"alicloud_db_instance": resourceAlicloudDBInstance(),
|
||||||
"alicloud_vpc": resourceAliyunVpc(),
|
"alicloud_vpc": resourceAliyunVpc(),
|
||||||
"alicloud_nat_gateway": resourceAliyunNatGateway(),
|
"alicloud_nat_gateway": resourceAliyunNatGateway(),
|
||||||
//both subnet and vswith exists,cause compatible old version, and compatible aws habit.
|
//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"
|
name = "terraform-test-group"
|
||||||
description = "New security group"
|
description = "New security group"
|
||||||
}
|
}
|
||||||
|
|
||||||
`
|
`
|
||||||
|
|
|
@ -136,9 +136,13 @@ func testAccCheckDiskDestroy(s *terraform.State) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
const testAccDiskConfig = `
|
const testAccDiskConfig = `
|
||||||
|
data "alicloud_zones" "default" {
|
||||||
|
"available_disk_category"= "cloud_efficiency"
|
||||||
|
}
|
||||||
|
|
||||||
resource "alicloud_disk" "foo" {
|
resource "alicloud_disk" "foo" {
|
||||||
# cn-beijing
|
# cn-beijing
|
||||||
availability_zone = "cn-beijing-b"
|
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||||
name = "New-disk"
|
name = "New-disk"
|
||||||
description = "Hello ecs disk."
|
description = "Hello ecs disk."
|
||||||
category = "cloud_efficiency"
|
category = "cloud_efficiency"
|
||||||
|
@ -146,10 +150,15 @@ resource "alicloud_disk" "foo" {
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
const testAccDiskConfigWithTags = `
|
const testAccDiskConfigWithTags = `
|
||||||
|
data "alicloud_zones" "default" {
|
||||||
|
"available_disk_category"= "cloud_efficiency"
|
||||||
|
}
|
||||||
|
|
||||||
resource "alicloud_disk" "bar" {
|
resource "alicloud_disk" "bar" {
|
||||||
# cn-beijing
|
# cn-beijing
|
||||||
availability_zone = "cn-beijing-b"
|
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||||
size = "10"
|
category = "cloud_efficiency"
|
||||||
|
size = "20"
|
||||||
tags {
|
tags {
|
||||||
Name = "TerraformTest"
|
Name = "TerraformTest"
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,6 +108,10 @@ func testAccCheckEIPAssociationDestroy(s *terraform.State) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
const testAccEIPAssociationConfig = `
|
const testAccEIPAssociationConfig = `
|
||||||
|
data "alicloud_zones" "default" {
|
||||||
|
"available_resource_creation"= "VSwitch"
|
||||||
|
}
|
||||||
|
|
||||||
resource "alicloud_vpc" "main" {
|
resource "alicloud_vpc" "main" {
|
||||||
cidr_block = "10.1.0.0/21"
|
cidr_block = "10.1.0.0/21"
|
||||||
}
|
}
|
||||||
|
@ -115,19 +119,23 @@ resource "alicloud_vpc" "main" {
|
||||||
resource "alicloud_vswitch" "main" {
|
resource "alicloud_vswitch" "main" {
|
||||||
vpc_id = "${alicloud_vpc.main.id}"
|
vpc_id = "${alicloud_vpc.main.id}"
|
||||||
cidr_block = "10.1.1.0/24"
|
cidr_block = "10.1.1.0/24"
|
||||||
availability_zone = "cn-beijing-a"
|
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||||
depends_on = [
|
depends_on = [
|
||||||
"alicloud_vpc.main"]
|
"alicloud_vpc.main"]
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "alicloud_instance" "instance" {
|
resource "alicloud_instance" "instance" {
|
||||||
image_id = "ubuntu_140405_64_40G_cloudinit_20161115.vhd"
|
# cn-beijing
|
||||||
instance_type = "ecs.s1.small"
|
|
||||||
availability_zone = "cn-beijing-a"
|
|
||||||
security_groups = ["${alicloud_security_group.group.id}"]
|
|
||||||
vswitch_id = "${alicloud_vswitch.main.id}"
|
vswitch_id = "${alicloud_vswitch.main.id}"
|
||||||
instance_name = "hello"
|
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||||
io_optimized = "none"
|
|
||||||
|
# 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 {
|
tags {
|
||||||
Name = "TerraformTest-instance"
|
Name = "TerraformTest-instance"
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
"github.com/denverdino/aliyungo/common"
|
"github.com/denverdino/aliyungo/common"
|
||||||
"github.com/denverdino/aliyungo/ecs"
|
"github.com/denverdino/aliyungo/ecs"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
@ -21,8 +22,9 @@ func resourceAliyunInstance() *schema.Resource {
|
||||||
Schema: map[string]*schema.Schema{
|
Schema: map[string]*schema.Schema{
|
||||||
"availability_zone": &schema.Schema{
|
"availability_zone": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
|
Computed: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
"image_id": &schema.Schema{
|
"image_id": &schema.Schema{
|
||||||
|
@ -60,11 +62,6 @@ func resourceAliyunInstance() *schema.Resource {
|
||||||
ValidateFunc: validateInstanceDescription,
|
ValidateFunc: validateInstanceDescription,
|
||||||
},
|
},
|
||||||
|
|
||||||
"instance_network_type": &schema.Schema{
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Computed: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
"internet_charge_type": &schema.Schema{
|
"internet_charge_type": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
@ -104,11 +101,19 @@ func resourceAliyunInstance() *schema.Resource {
|
||||||
Default: "cloud",
|
Default: "cloud",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
|
ValidateFunc: validateAllowedStringValue([]string{
|
||||||
|
string(ecs.DiskCategoryCloud),
|
||||||
|
string(ecs.DiskCategoryCloudSSD),
|
||||||
|
string(ecs.DiskCategoryCloudEfficiency),
|
||||||
|
string(ecs.DiskCategoryEphemeralSSD),
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
"system_disk_size": &schema.Schema{
|
"system_disk_size": &schema.Schema{
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
|
ForceNew: true,
|
||||||
|
ValidateFunc: validateIntegerInRange(40, 500),
|
||||||
},
|
},
|
||||||
|
|
||||||
//subnet_id and vswitch_id both exists, cause compatible old version, and aws habit.
|
//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{
|
"private_ip": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
|
||||||
Computed: true,
|
Computed: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -168,6 +172,11 @@ func resourceAliyunInstance() *schema.Resource {
|
||||||
func resourceAliyunInstanceCreate(d *schema.ResourceData, meta interface{}) error {
|
func resourceAliyunInstanceCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
conn := meta.(*AliyunClient).ecsconn
|
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)
|
args, err := buildAliyunInstanceArgs(d, meta)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -181,7 +190,8 @@ func resourceAliyunInstanceCreate(d *schema.ResourceData, meta interface{}) erro
|
||||||
d.SetId(instanceID)
|
d.SetId(instanceID)
|
||||||
|
|
||||||
d.Set("password", d.Get("password"))
|
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) {
|
if d.Get("allocate_public_ip").(bool) {
|
||||||
_, err := conn.AllocatePublicIpAddress(d.Id())
|
_, err := conn.AllocatePublicIpAddress(d.Id())
|
||||||
|
@ -207,11 +217,56 @@ func resourceAliyunInstanceCreate(d *schema.ResourceData, meta interface{}) erro
|
||||||
return resourceAliyunInstanceUpdate(d, meta)
|
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 {
|
func resourceAliyunInstanceRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
client := meta.(*AliyunClient)
|
client := meta.(*AliyunClient)
|
||||||
conn := client.ecsconn
|
conn := client.ecsconn
|
||||||
|
|
||||||
instance, err := client.QueryInstancesById(d.Id())
|
instance, err := client.QueryInstancesById(d.Id())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if notFoundError(err) {
|
if notFoundError(err) {
|
||||||
d.SetId("")
|
d.SetId("")
|
||||||
|
@ -220,7 +275,15 @@ func resourceAliyunInstanceRead(d *schema.ResourceData, meta interface{}) error
|
||||||
return fmt.Errorf("Error DescribeInstanceAttribute: %#v", err)
|
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("instance_name", instance.InstanceName)
|
||||||
d.Set("description", instance.Description)
|
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("host_name", instance.HostName)
|
||||||
d.Set("image_id", instance.ImageId)
|
d.Set("image_id", instance.ImageId)
|
||||||
d.Set("instance_type", instance.InstanceType)
|
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 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'.
|
// 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")
|
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) != "" {
|
if d.Get("subnet_id").(string) != "" || d.Get("vswitch_id").(string) != "" {
|
||||||
ipAddress := instance.VpcAttributes.PrivateIpAddress.IpAddress[0]
|
ipAddress := instance.VpcAttributes.PrivateIpAddress.IpAddress[0]
|
||||||
d.Set("private_ip", ipAddress)
|
d.Set("private_ip", ipAddress)
|
||||||
|
@ -414,33 +475,71 @@ func resourceAliyunInstanceDelete(d *schema.ResourceData, meta interface{}) erro
|
||||||
|
|
||||||
return nil
|
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) {
|
func buildAliyunInstanceArgs(d *schema.ResourceData, meta interface{}) (*ecs.CreateInstanceArgs, error) {
|
||||||
client := meta.(*AliyunClient)
|
client := meta.(*AliyunClient)
|
||||||
|
|
||||||
args := &ecs.CreateInstanceArgs{
|
args := &ecs.CreateInstanceArgs{
|
||||||
RegionId: getRegion(d, meta),
|
RegionId: getRegion(d, meta),
|
||||||
InstanceType: d.Get("instance_type").(string),
|
InstanceType: d.Get("instance_type").(string),
|
||||||
PrivateIpAddress: d.Get("private_ip").(string),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
imageID := d.Get("image_id").(string)
|
imageID := d.Get("image_id").(string)
|
||||||
|
|
||||||
args.ImageId = imageID
|
args.ImageId = imageID
|
||||||
|
|
||||||
|
systemDiskCategory := ecs.DiskCategory(d.Get("system_disk_category").(string))
|
||||||
|
systemDiskSize := d.Get("system_disk_size").(int)
|
||||||
|
|
||||||
zoneID := d.Get("availability_zone").(string)
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := client.ResourceAvailable(zone, ecs.ResourceTypeInstance); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := client.DiskAvailable(zone, systemDiskCategory); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
args.ZoneId = zoneID
|
||||||
|
|
||||||
zone, err := client.DescribeZone(zoneID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := client.ResourceAvailable(zone, ecs.ResourceTypeInstance); err != nil {
|
args.SystemDisk = ecs.SystemDiskType{
|
||||||
return nil, err
|
Category: systemDiskCategory,
|
||||||
|
Size: systemDiskSize,
|
||||||
}
|
}
|
||||||
|
|
||||||
args.ZoneId = zoneID
|
|
||||||
|
|
||||||
sgs, ok := d.GetOk("security_groups")
|
sgs, ok := d.GetOk("security_groups")
|
||||||
|
|
||||||
if ok {
|
if ok {
|
||||||
|
@ -451,17 +550,6 @@ func buildAliyunInstanceArgs(d *schema.ResourceData, meta interface{}) (*ecs.Cre
|
||||||
if err == nil {
|
if err == nil {
|
||||||
args.SecurityGroupId = sg0
|
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 != "" {
|
if v := d.Get("instance_name").(string); v != "" {
|
||||||
|
@ -472,7 +560,7 @@ func buildAliyunInstanceArgs(d *schema.ResourceData, meta interface{}) (*ecs.Cre
|
||||||
args.Description = v
|
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 != "" {
|
if v := d.Get("internet_charge_type").(string); v != "" {
|
||||||
args.InternetChargeType = common.InternetChargeType(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 != "" {
|
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)
|
vswitchValue := d.Get("subnet_id").(string)
|
||||||
|
|
|
@ -56,6 +56,7 @@ func TestAccAlicloudInstance_basic(t *testing.T) {
|
||||||
"alicloud_instance.foo",
|
"alicloud_instance.foo",
|
||||||
"internet_charge_type",
|
"internet_charge_type",
|
||||||
"PayByBandwidth"),
|
"PayByBandwidth"),
|
||||||
|
testAccCheckSystemDiskSize("alicloud_instance.foo", 80),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -355,10 +356,6 @@ func TestAccAlicloudInstance_tags(t *testing.T) {
|
||||||
Config: testAccCheckInstanceConfigTagsUpdate,
|
Config: testAccCheckInstanceConfigTagsUpdate,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckInstanceExists("alicloud_instance.foo", &instance),
|
testAccCheckInstanceExists("alicloud_instance.foo", &instance),
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"alicloud_instance.foo",
|
|
||||||
"tags.foo",
|
|
||||||
""),
|
|
||||||
resource.TestCheckResourceAttr(
|
resource.TestCheckResourceAttr(
|
||||||
"alicloud_instance.foo",
|
"alicloud_instance.foo",
|
||||||
"tags.bar",
|
"tags.bar",
|
||||||
|
@ -418,8 +415,8 @@ func TestAccAlicloudInstance_privateIP(t *testing.T) {
|
||||||
testCheckPrivateIP := func() resource.TestCheckFunc {
|
testCheckPrivateIP := func() resource.TestCheckFunc {
|
||||||
return func(*terraform.State) error {
|
return func(*terraform.State) error {
|
||||||
privateIP := instance.VpcAttributes.PrivateIpAddress.IpAddress[0]
|
privateIP := instance.VpcAttributes.PrivateIpAddress.IpAddress[0]
|
||||||
if privateIP != "172.16.0.229" {
|
if privateIP == "" {
|
||||||
return fmt.Errorf("bad private IP: %s", privateIP)
|
return fmt.Errorf("can't get private IP")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
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
|
var instance ecs.InstanceAttributesType
|
||||||
|
|
||||||
testCheckPrivateIP := func() resource.TestCheckFunc {
|
testCheckPrivateIP := func() resource.TestCheckFunc {
|
||||||
return func(*terraform.State) error {
|
return func(*terraform.State) error {
|
||||||
privateIP := instance.VpcAttributes.PrivateIpAddress.IpAddress[0]
|
privateIP := instance.VpcAttributes.PrivateIpAddress.IpAddress[0]
|
||||||
if privateIP != "172.16.0.229" {
|
if privateIP == "" {
|
||||||
return fmt.Errorf("bad private IP: %s", privateIP)
|
return fmt.Errorf("can't get private IP")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -468,7 +465,7 @@ func TestAccAlicloudInstance_associatePublicIPAndPrivateIP(t *testing.T) {
|
||||||
CheckDestroy: testAccCheckInstanceDestroy,
|
CheckDestroy: testAccCheckInstanceDestroy,
|
||||||
Steps: []resource.TestStep{
|
Steps: []resource.TestStep{
|
||||||
resource.TestStep{
|
resource.TestStep{
|
||||||
Config: testAccInstanceConfigAssociatePublicIPAndPrivateIP,
|
Config: testAccInstanceConfigAssociatePublicIP,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testAccCheckInstanceExists("alicloud_instance.foo", &instance),
|
testAccCheckInstanceExists("alicloud_instance.foo", &instance),
|
||||||
testCheckPrivateIP(),
|
testCheckPrivateIP(),
|
||||||
|
@ -597,6 +594,36 @@ func testAccCheckInstanceDestroyWithProvider(s *terraform.State, provider *schem
|
||||||
return nil
|
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 = `
|
const testAccInstanceConfig = `
|
||||||
resource "alicloud_security_group" "tf_test_foo" {
|
resource "alicloud_security_group" "tf_test_foo" {
|
||||||
name = "tf_test_foo"
|
name = "tf_test_foo"
|
||||||
|
@ -609,11 +636,10 @@ resource "alicloud_security_group" "tf_test_bar" {
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "alicloud_instance" "foo" {
|
resource "alicloud_instance" "foo" {
|
||||||
# cn-beijing
|
|
||||||
availability_zone = "cn-beijing-b"
|
|
||||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||||
|
|
||||||
system_disk_category = "cloud_ssd"
|
system_disk_category = "cloud_ssd"
|
||||||
|
system_disk_size = 80
|
||||||
|
|
||||||
instance_type = "ecs.n1.small"
|
instance_type = "ecs.n1.small"
|
||||||
internet_charge_type = "PayByBandwidth"
|
internet_charge_type = "PayByBandwidth"
|
||||||
|
@ -628,15 +654,20 @@ resource "alicloud_instance" "foo" {
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
const testAccInstanceConfigVPC = `
|
const testAccInstanceConfigVPC = `
|
||||||
|
data "alicloud_zones" "default" {
|
||||||
|
"available_disk_category"= "cloud_efficiency"
|
||||||
|
"available_resource_creation"= "VSwitch"
|
||||||
|
}
|
||||||
|
|
||||||
resource "alicloud_vpc" "foo" {
|
resource "alicloud_vpc" "foo" {
|
||||||
name = "tf_test_foo"
|
name = "tf_test_foo"
|
||||||
cidr_block = "172.16.0.0/12"
|
cidr_block = "172.16.0.0/12"
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "alicloud_vswitch" "foo" {
|
resource "alicloud_vswitch" "foo" {
|
||||||
vpc_id = "${alicloud_vpc.foo.id}"
|
vpc_id = "${alicloud_vpc.foo.id}"
|
||||||
cidr_block = "172.16.0.0/21"
|
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" {
|
resource "alicloud_security_group" "tf_test_foo" {
|
||||||
|
@ -647,7 +678,6 @@ resource "alicloud_security_group" "tf_test_foo" {
|
||||||
|
|
||||||
resource "alicloud_instance" "foo" {
|
resource "alicloud_instance" "foo" {
|
||||||
# cn-beijing
|
# cn-beijing
|
||||||
availability_zone = "cn-beijing-b"
|
|
||||||
vswitch_id = "${alicloud_vswitch.foo.id}"
|
vswitch_id = "${alicloud_vswitch.foo.id}"
|
||||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||||
|
|
||||||
|
@ -666,15 +696,20 @@ resource "alicloud_instance" "foo" {
|
||||||
`
|
`
|
||||||
|
|
||||||
const testAccInstanceConfigUserData = `
|
const testAccInstanceConfigUserData = `
|
||||||
|
data "alicloud_zones" "default" {
|
||||||
|
"available_disk_category"= "cloud_efficiency"
|
||||||
|
"available_resource_creation"= "VSwitch"
|
||||||
|
}
|
||||||
|
|
||||||
resource "alicloud_vpc" "foo" {
|
resource "alicloud_vpc" "foo" {
|
||||||
name = "tf_test_foo"
|
name = "tf_test_foo"
|
||||||
cidr_block = "172.16.0.0/12"
|
cidr_block = "172.16.0.0/12"
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "alicloud_vswitch" "foo" {
|
resource "alicloud_vswitch" "foo" {
|
||||||
vpc_id = "${alicloud_vpc.foo.id}"
|
vpc_id = "${alicloud_vpc.foo.id}"
|
||||||
cidr_block = "172.16.0.0/21"
|
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" {
|
resource "alicloud_security_group" "tf_test_foo" {
|
||||||
|
@ -685,7 +720,6 @@ resource "alicloud_security_group" "tf_test_foo" {
|
||||||
|
|
||||||
resource "alicloud_instance" "foo" {
|
resource "alicloud_instance" "foo" {
|
||||||
# cn-beijing
|
# cn-beijing
|
||||||
availability_zone = "cn-beijing-b"
|
|
||||||
vswitch_id = "${alicloud_vswitch.foo.id}"
|
vswitch_id = "${alicloud_vswitch.foo.id}"
|
||||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||||
# series II
|
# series II
|
||||||
|
@ -725,24 +759,22 @@ resource "alicloud_security_group" "tf_test_bar" {
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "alicloud_instance" "foo" {
|
resource "alicloud_instance" "foo" {
|
||||||
# cn-beijing
|
# cn-beijing
|
||||||
provider = "alicloud.beijing"
|
provider = "alicloud.beijing"
|
||||||
availability_zone = "cn-beijing-b"
|
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
|
||||||
|
|
||||||
internet_charge_type = "PayByBandwidth"
|
internet_charge_type = "PayByBandwidth"
|
||||||
|
|
||||||
instance_type = "ecs.n1.medium"
|
instance_type = "ecs.n1.medium"
|
||||||
io_optimized = "optimized"
|
io_optimized = "optimized"
|
||||||
system_disk_category = "cloud_efficiency"
|
system_disk_category = "cloud_efficiency"
|
||||||
security_groups = ["${alicloud_security_group.tf_test_foo.id}"]
|
security_groups = ["${alicloud_security_group.tf_test_foo.id}"]
|
||||||
instance_name = "test_foo"
|
instance_name = "test_foo"
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "alicloud_instance" "bar" {
|
resource "alicloud_instance" "bar" {
|
||||||
# cn-shanghai
|
# cn-shanghai
|
||||||
provider = "alicloud.shanghai"
|
provider = "alicloud.shanghai"
|
||||||
availability_zone = "cn-shanghai-b"
|
|
||||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||||
|
|
||||||
internet_charge_type = "PayByBandwidth"
|
internet_charge_type = "PayByBandwidth"
|
||||||
|
@ -768,7 +800,6 @@ resource "alicloud_security_group" "tf_test_bar" {
|
||||||
|
|
||||||
resource "alicloud_instance" "foo" {
|
resource "alicloud_instance" "foo" {
|
||||||
# cn-beijing
|
# cn-beijing
|
||||||
availability_zone = "cn-beijing-b"
|
|
||||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||||
|
|
||||||
instance_type = "ecs.s2.large"
|
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}"]
|
security_groups = ["${alicloud_security_group.tf_test_foo.id}", "${alicloud_security_group.tf_test_bar.id}"]
|
||||||
instance_name = "test_foo"
|
instance_name = "test_foo"
|
||||||
io_optimized = "optimized"
|
io_optimized = "optimized"
|
||||||
|
system_disk_category = "cloud_efficiency"
|
||||||
}`
|
}`
|
||||||
|
|
||||||
const testAccInstanceConfig_multiSecurityGroup_add = `
|
const testAccInstanceConfig_multiSecurityGroup_add = `
|
||||||
|
@ -796,7 +828,6 @@ resource "alicloud_security_group" "tf_test_add_sg" {
|
||||||
|
|
||||||
resource "alicloud_instance" "foo" {
|
resource "alicloud_instance" "foo" {
|
||||||
# cn-beijing
|
# cn-beijing
|
||||||
availability_zone = "cn-beijing-b"
|
|
||||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||||
|
|
||||||
instance_type = "ecs.s2.large"
|
instance_type = "ecs.s2.large"
|
||||||
|
@ -805,6 +836,7 @@ resource "alicloud_instance" "foo" {
|
||||||
"${alicloud_security_group.tf_test_add_sg.id}"]
|
"${alicloud_security_group.tf_test_add_sg.id}"]
|
||||||
instance_name = "test_foo"
|
instance_name = "test_foo"
|
||||||
io_optimized = "optimized"
|
io_optimized = "optimized"
|
||||||
|
system_disk_category = "cloud_efficiency"
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
@ -814,9 +846,30 @@ resource "alicloud_security_group" "tf_test_foo" {
|
||||||
description = "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" {
|
resource "alicloud_instance" "foo" {
|
||||||
# cn-beijing
|
# cn-beijing
|
||||||
availability_zone = "cn-beijing-b"
|
|
||||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||||
|
|
||||||
instance_type = "ecs.s2.large"
|
instance_type = "ecs.s2.large"
|
||||||
|
@ -824,6 +877,7 @@ resource "alicloud_instance" "foo" {
|
||||||
security_groups = ["${alicloud_security_group.tf_test_foo.id}"]
|
security_groups = ["${alicloud_security_group.tf_test_foo.id}"]
|
||||||
instance_name = "test_foo"
|
instance_name = "test_foo"
|
||||||
io_optimized = "optimized"
|
io_optimized = "optimized"
|
||||||
|
system_disk_category = "cloud_efficiency"
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
@ -836,27 +890,32 @@ resource "alicloud_security_group" "tf_test_foo" {
|
||||||
|
|
||||||
resource "alicloud_instance" "foo" {
|
resource "alicloud_instance" "foo" {
|
||||||
# cn-beijing
|
# cn-beijing
|
||||||
availability_zone = "cn-beijing-b"
|
|
||||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||||
|
|
||||||
instance_type = "ecs.s2.large"
|
instance_type = "ecs.s2.large"
|
||||||
internet_charge_type = "PayByBandwidth"
|
internet_charge_type = "PayByBandwidth"
|
||||||
security_groups = ["${alicloud_security_group.tf_test_foo.*.id}"]
|
security_groups = ["${alicloud_security_group.tf_test_foo.*.id}"]
|
||||||
instance_name = "test_foo"
|
instance_name = "test_foo"
|
||||||
io_optimized = "none"
|
io_optimized = "optimized"
|
||||||
|
system_disk_category = "cloud_efficiency"
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const testAccInstanceNetworkInstanceSecurityGroups = `
|
const testAccInstanceNetworkInstanceSecurityGroups = `
|
||||||
|
data "alicloud_zones" "default" {
|
||||||
|
"available_disk_category"= "cloud_efficiency"
|
||||||
|
"available_resource_creation"= "VSwitch"
|
||||||
|
}
|
||||||
|
|
||||||
resource "alicloud_vpc" "foo" {
|
resource "alicloud_vpc" "foo" {
|
||||||
name = "tf_test_foo"
|
name = "tf_test_foo"
|
||||||
cidr_block = "172.16.0.0/12"
|
cidr_block = "172.16.0.0/12"
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "alicloud_vswitch" "foo" {
|
resource "alicloud_vswitch" "foo" {
|
||||||
vpc_id = "${alicloud_vpc.foo.id}"
|
vpc_id = "${alicloud_vpc.foo.id}"
|
||||||
cidr_block = "172.16.0.0/21"
|
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" {
|
resource "alicloud_security_group" "tf_test_foo" {
|
||||||
|
@ -867,7 +926,6 @@ resource "alicloud_security_group" "tf_test_foo" {
|
||||||
|
|
||||||
resource "alicloud_instance" "foo" {
|
resource "alicloud_instance" "foo" {
|
||||||
# cn-beijing
|
# cn-beijing
|
||||||
availability_zone = "cn-beijing-b"
|
|
||||||
vswitch_id = "${alicloud_vswitch.foo.id}"
|
vswitch_id = "${alicloud_vswitch.foo.id}"
|
||||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||||
|
|
||||||
|
@ -892,7 +950,6 @@ resource "alicloud_security_group" "tf_test_foo" {
|
||||||
|
|
||||||
resource "alicloud_instance" "foo" {
|
resource "alicloud_instance" "foo" {
|
||||||
# cn-beijing
|
# cn-beijing
|
||||||
availability_zone = "cn-beijing-b"
|
|
||||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||||
|
|
||||||
# series II
|
# series II
|
||||||
|
@ -918,7 +975,6 @@ resource "alicloud_security_group" "tf_test_foo" {
|
||||||
|
|
||||||
resource "alicloud_instance" "foo" {
|
resource "alicloud_instance" "foo" {
|
||||||
# cn-beijing
|
# cn-beijing
|
||||||
availability_zone = "cn-beijing-b"
|
|
||||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||||
|
|
||||||
# series II
|
# series II
|
||||||
|
@ -941,9 +997,30 @@ resource "alicloud_security_group" "tf_test_foo" {
|
||||||
description = "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" {
|
resource "alicloud_instance" "foo" {
|
||||||
# cn-beijing
|
# cn-beijing
|
||||||
availability_zone = "cn-beijing-b"
|
|
||||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||||
|
|
||||||
# series II
|
# series II
|
||||||
|
@ -965,9 +1042,30 @@ resource "alicloud_security_group" "tf_test_foo" {
|
||||||
description = "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" {
|
resource "alicloud_instance" "foo" {
|
||||||
# cn-beijing
|
# cn-beijing
|
||||||
availability_zone = "cn-beijing-b"
|
|
||||||
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||||
|
|
||||||
# series II
|
# series II
|
||||||
|
@ -984,15 +1082,20 @@ resource "alicloud_instance" "foo" {
|
||||||
`
|
`
|
||||||
|
|
||||||
const testAccInstanceConfigPrivateIP = `
|
const testAccInstanceConfigPrivateIP = `
|
||||||
|
data "alicloud_zones" "default" {
|
||||||
|
"available_disk_category"= "cloud_efficiency"
|
||||||
|
"available_resource_creation"= "VSwitch"
|
||||||
|
}
|
||||||
|
|
||||||
resource "alicloud_vpc" "foo" {
|
resource "alicloud_vpc" "foo" {
|
||||||
name = "tf_test_foo"
|
name = "tf_test_foo"
|
||||||
cidr_block = "172.16.0.0/12"
|
cidr_block = "172.16.0.0/12"
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "alicloud_vswitch" "foo" {
|
resource "alicloud_vswitch" "foo" {
|
||||||
vpc_id = "${alicloud_vpc.foo.id}"
|
vpc_id = "${alicloud_vpc.foo.id}"
|
||||||
cidr_block = "172.16.0.0/24"
|
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" {
|
resource "alicloud_security_group" "tf_test_foo" {
|
||||||
|
@ -1003,11 +1106,9 @@ resource "alicloud_security_group" "tf_test_foo" {
|
||||||
|
|
||||||
resource "alicloud_instance" "foo" {
|
resource "alicloud_instance" "foo" {
|
||||||
# cn-beijing
|
# cn-beijing
|
||||||
availability_zone = "cn-beijing-b"
|
|
||||||
security_groups = ["${alicloud_security_group.tf_test_foo.id}"]
|
security_groups = ["${alicloud_security_group.tf_test_foo.id}"]
|
||||||
|
|
||||||
vswitch_id = "${alicloud_vswitch.foo.id}"
|
vswitch_id = "${alicloud_vswitch.foo.id}"
|
||||||
private_ip = "172.16.0.229"
|
|
||||||
|
|
||||||
# series II
|
# series II
|
||||||
instance_type = "ecs.n1.medium"
|
instance_type = "ecs.n1.medium"
|
||||||
|
@ -1017,16 +1118,21 @@ resource "alicloud_instance" "foo" {
|
||||||
instance_name = "test_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" {
|
resource "alicloud_vpc" "foo" {
|
||||||
name = "tf_test_foo"
|
name = "tf_test_foo"
|
||||||
cidr_block = "172.16.0.0/12"
|
cidr_block = "172.16.0.0/12"
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "alicloud_vswitch" "foo" {
|
resource "alicloud_vswitch" "foo" {
|
||||||
vpc_id = "${alicloud_vpc.foo.id}"
|
vpc_id = "${alicloud_vpc.foo.id}"
|
||||||
cidr_block = "172.16.0.0/24"
|
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" {
|
resource "alicloud_security_group" "tf_test_foo" {
|
||||||
|
@ -1037,11 +1143,9 @@ resource "alicloud_security_group" "tf_test_foo" {
|
||||||
|
|
||||||
resource "alicloud_instance" "foo" {
|
resource "alicloud_instance" "foo" {
|
||||||
# cn-beijing
|
# cn-beijing
|
||||||
availability_zone = "cn-beijing-b"
|
|
||||||
security_groups = ["${alicloud_security_group.tf_test_foo.id}"]
|
security_groups = ["${alicloud_security_group.tf_test_foo.id}"]
|
||||||
|
|
||||||
vswitch_id = "${alicloud_vswitch.foo.id}"
|
vswitch_id = "${alicloud_vswitch.foo.id}"
|
||||||
private_ip = "172.16.0.229"
|
|
||||||
allocate_public_ip = "true"
|
allocate_public_ip = "true"
|
||||||
internet_max_bandwidth_out = 5
|
internet_max_bandwidth_out = 5
|
||||||
internet_charge_type = "PayByBandwidth"
|
internet_charge_type = "PayByBandwidth"
|
||||||
|
@ -1055,52 +1159,56 @@ resource "alicloud_instance" "foo" {
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
const testAccVpcInstanceWithSecurityRule = `
|
const testAccVpcInstanceWithSecurityRule = `
|
||||||
|
data "alicloud_zones" "default" {
|
||||||
|
"available_disk_category"= "cloud_efficiency"
|
||||||
|
"available_resource_creation"= "VSwitch"
|
||||||
|
}
|
||||||
|
|
||||||
resource "alicloud_vpc" "foo" {
|
resource "alicloud_vpc" "foo" {
|
||||||
name = "tf_test_foo"
|
name = "tf_test_foo"
|
||||||
cidr_block = "10.1.0.0/21"
|
cidr_block = "10.1.0.0/21"
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "alicloud_vswitch" "foo" {
|
resource "alicloud_vswitch" "foo" {
|
||||||
vpc_id = "${alicloud_vpc.foo.id}"
|
vpc_id = "${alicloud_vpc.foo.id}"
|
||||||
cidr_block = "10.1.1.0/24"
|
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" {
|
resource "alicloud_security_group" "tf_test_foo" {
|
||||||
name = "tf_test_foo"
|
name = "tf_test_foo"
|
||||||
description = "foo"
|
description = "foo"
|
||||||
vpc_id = "${alicloud_vpc.foo.id}"
|
vpc_id = "${alicloud_vpc.foo.id}"
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "alicloud_security_group_rule" "ingress" {
|
resource "alicloud_security_group_rule" "ingress" {
|
||||||
type = "ingress"
|
type = "ingress"
|
||||||
ip_protocol = "tcp"
|
ip_protocol = "tcp"
|
||||||
nic_type = "intranet"
|
nic_type = "intranet"
|
||||||
policy = "accept"
|
policy = "accept"
|
||||||
port_range = "22/22"
|
port_range = "22/22"
|
||||||
priority = 1
|
priority = 1
|
||||||
security_group_id = "${alicloud_security_group.tf_test_foo.id}"
|
security_group_id = "${alicloud_security_group.tf_test_foo.id}"
|
||||||
cidr_ip = "0.0.0.0/0"
|
cidr_ip = "0.0.0.0/0"
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "alicloud_instance" "foo" {
|
resource "alicloud_instance" "foo" {
|
||||||
# cn-beijing
|
# cn-beijing
|
||||||
availability_zone = "cn-beijing-c"
|
security_groups = ["${alicloud_security_group.tf_test_foo.id}"]
|
||||||
security_groups = ["${alicloud_security_group.tf_test_foo.id}"]
|
|
||||||
|
|
||||||
vswitch_id = "${alicloud_vswitch.foo.id}"
|
vswitch_id = "${alicloud_vswitch.foo.id}"
|
||||||
allocate_public_ip = true
|
allocate_public_ip = true
|
||||||
|
|
||||||
# series II
|
# series II
|
||||||
instance_charge_type = "PostPaid"
|
instance_charge_type = "PostPaid"
|
||||||
instance_type = "ecs.n1.small"
|
instance_type = "ecs.n1.small"
|
||||||
internet_charge_type = "PayByBandwidth"
|
internet_charge_type = "PayByBandwidth"
|
||||||
internet_max_bandwidth_out = 5
|
internet_max_bandwidth_out = 5
|
||||||
|
|
||||||
system_disk_category = "cloud_efficiency"
|
system_disk_category = "cloud_efficiency"
|
||||||
image_id = "ubuntu_140405_64_40G_cloudinit_20161115.vhd"
|
image_id = "ubuntu_140405_64_40G_cloudinit_20161115.vhd"
|
||||||
instance_name = "test_foo"
|
instance_name = "test_foo"
|
||||||
io_optimized = "optimized"
|
io_optimized = "optimized"
|
||||||
}
|
}
|
||||||
|
|
||||||
`
|
`
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/denverdino/aliyungo/common"
|
"github.com/denverdino/aliyungo/common"
|
||||||
|
"github.com/denverdino/aliyungo/ecs"
|
||||||
"github.com/hashicorp/terraform/helper/resource"
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
"log"
|
"log"
|
||||||
|
@ -71,7 +72,7 @@ func resourceAliyunNatGateway() *schema.Resource {
|
||||||
func resourceAliyunNatGatewayCreate(d *schema.ResourceData, meta interface{}) error {
|
func resourceAliyunNatGatewayCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
conn := meta.(*AliyunClient).vpcconn
|
conn := meta.(*AliyunClient).vpcconn
|
||||||
|
|
||||||
args := &CreateNatGatewayArgs{
|
args := &ecs.CreateNatGatewayArgs{
|
||||||
RegionId: getRegion(d, meta),
|
RegionId: getRegion(d, meta),
|
||||||
VpcId: d.Get("vpc_id").(string),
|
VpcId: d.Get("vpc_id").(string),
|
||||||
Spec: d.Get("spec").(string),
|
Spec: d.Get("spec").(string),
|
||||||
|
@ -79,11 +80,11 @@ func resourceAliyunNatGatewayCreate(d *schema.ResourceData, meta interface{}) er
|
||||||
|
|
||||||
bandwidthPackages := d.Get("bandwidth_packages").([]interface{})
|
bandwidthPackages := d.Get("bandwidth_packages").([]interface{})
|
||||||
|
|
||||||
bandwidthPackageTypes := []BandwidthPackageType{}
|
bandwidthPackageTypes := []ecs.BandwidthPackageType{}
|
||||||
|
|
||||||
for _, e := range bandwidthPackages {
|
for _, e := range bandwidthPackages {
|
||||||
pack := e.(map[string]interface{})
|
pack := e.(map[string]interface{})
|
||||||
bandwidthPackage := BandwidthPackageType{
|
bandwidthPackage := ecs.BandwidthPackageType{
|
||||||
IpCount: pack["ip_count"].(int),
|
IpCount: pack["ip_count"].(int),
|
||||||
Bandwidth: pack["bandwidth"].(int),
|
Bandwidth: pack["bandwidth"].(int),
|
||||||
}
|
}
|
||||||
|
@ -106,8 +107,7 @@ func resourceAliyunNatGatewayCreate(d *schema.ResourceData, meta interface{}) er
|
||||||
if v, ok := d.GetOk("description"); ok {
|
if v, ok := d.GetOk("description"); ok {
|
||||||
args.Description = v.(string)
|
args.Description = v.(string)
|
||||||
}
|
}
|
||||||
|
resp, err := conn.CreateNatGateway(args)
|
||||||
resp, err := CreateNatGateway(conn, args)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("CreateNatGateway got error: %#v", err)
|
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 {
|
func resourceAliyunNatGatewayUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
|
||||||
client := meta.(*AliyunClient)
|
client := meta.(*AliyunClient)
|
||||||
|
conn := client.vpcconn
|
||||||
|
|
||||||
natGateway, err := client.DescribeNatGateway(d.Id())
|
natGateway, err := client.DescribeNatGateway(d.Id())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -150,7 +151,7 @@ func resourceAliyunNatGatewayUpdate(d *schema.ResourceData, meta interface{}) er
|
||||||
|
|
||||||
d.Partial(true)
|
d.Partial(true)
|
||||||
attributeUpdate := false
|
attributeUpdate := false
|
||||||
args := &ModifyNatGatewayAttributeArgs{
|
args := &ecs.ModifyNatGatewayAttributeArgs{
|
||||||
RegionId: natGateway.RegionId,
|
RegionId: natGateway.RegionId,
|
||||||
NatGatewayId: natGateway.NatGatewayId,
|
NatGatewayId: natGateway.NatGatewayId,
|
||||||
}
|
}
|
||||||
|
@ -183,28 +184,28 @@ func resourceAliyunNatGatewayUpdate(d *schema.ResourceData, meta interface{}) er
|
||||||
}
|
}
|
||||||
|
|
||||||
if attributeUpdate {
|
if attributeUpdate {
|
||||||
if err := ModifyNatGatewayAttribute(client.vpcconn, args); err != nil {
|
if err := conn.ModifyNatGatewayAttribute(args); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.HasChange("spec") {
|
if d.HasChange("spec") {
|
||||||
d.SetPartial("spec")
|
d.SetPartial("spec")
|
||||||
var spec NatGatewaySpec
|
var spec ecs.NatGatewaySpec
|
||||||
if v, ok := d.GetOk("spec"); ok {
|
if v, ok := d.GetOk("spec"); ok {
|
||||||
spec = NatGatewaySpec(v.(string))
|
spec = ecs.NatGatewaySpec(v.(string))
|
||||||
} else {
|
} else {
|
||||||
// set default to small spec
|
// set default to small spec
|
||||||
spec = NatGatewaySmallSpec
|
spec = ecs.NatGatewaySmallSpec
|
||||||
}
|
}
|
||||||
|
|
||||||
args := &ModifyNatGatewaySpecArgs{
|
args := &ecs.ModifyNatGatewaySpecArgs{
|
||||||
RegionId: natGateway.RegionId,
|
RegionId: natGateway.RegionId,
|
||||||
NatGatewayId: natGateway.NatGatewayId,
|
NatGatewayId: natGateway.NatGatewayId,
|
||||||
Spec: spec,
|
Spec: spec,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := ModifyNatGatewaySpec(client.vpcconn, args)
|
err := conn.ModifyNatGatewaySpec(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%#v %#v", err, *args)
|
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 {
|
func resourceAliyunNatGatewayDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
|
||||||
client := meta.(*AliyunClient)
|
client := meta.(*AliyunClient)
|
||||||
|
conn := client.vpcconn
|
||||||
|
|
||||||
return resource.Retry(5*time.Minute, func() *resource.RetryError {
|
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),
|
RegionId: getRegion(d, meta),
|
||||||
NatGatewayId: d.Id(),
|
NatGatewayId: d.Id(),
|
||||||
})
|
})
|
||||||
|
@ -232,7 +234,7 @@ func resourceAliyunNatGatewayDelete(d *schema.ResourceData, meta interface{}) er
|
||||||
|
|
||||||
retry := false
|
retry := false
|
||||||
for _, pack := range packages {
|
for _, pack := range packages {
|
||||||
err = DeleteBandwidthPackage(client.vpcconn, &DeleteBandwidthPackageArgs{
|
err = conn.DeleteBandwidthPackage(&ecs.DeleteBandwidthPackageArgs{
|
||||||
RegionId: getRegion(d, meta),
|
RegionId: getRegion(d, meta),
|
||||||
BandwidthPackageId: pack.BandwidthPackageId,
|
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."))
|
return resource.RetryableError(fmt.Errorf("Bandwidth package in use - trying again while it is deleted."))
|
||||||
}
|
}
|
||||||
|
|
||||||
args := &DeleteNatGatewayArgs{
|
args := &ecs.DeleteNatGatewayArgs{
|
||||||
RegionId: client.Region,
|
RegionId: client.Region,
|
||||||
NatGatewayId: d.Id(),
|
NatGatewayId: d.Id(),
|
||||||
}
|
}
|
||||||
|
|
||||||
err = DeleteNatGateway(client.vpcconn, args)
|
err = conn.DeleteNatGateway(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
er, _ := err.(*common.Error)
|
er, _ := err.(*common.Error)
|
||||||
if er.ErrorResponse.Code == DependencyViolationBandwidthPackages {
|
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,
|
RegionId: client.Region,
|
||||||
NatGatewayId: d.Id(),
|
NatGatewayId: d.Id(),
|
||||||
}
|
}
|
||||||
gw, _, gwErr := DescribeNatGateways(client.vpcconn, describeArgs)
|
gw, _, gwErr := conn.DescribeNatGateways(describeArgs)
|
||||||
|
|
||||||
if gwErr != nil {
|
if gwErr != nil {
|
||||||
log.Printf("[ERROR] Describe NatGateways failed.")
|
log.Printf("[ERROR] Describe NatGateways failed.")
|
||||||
|
|
|
@ -3,13 +3,14 @@ package alicloud
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/denverdino/aliyungo/common"
|
"github.com/denverdino/aliyungo/common"
|
||||||
|
"github.com/denverdino/aliyungo/ecs"
|
||||||
"github.com/hashicorp/terraform/helper/resource"
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAccAlicloudNatGateway_basic(t *testing.T) {
|
func TestAccAlicloudNatGateway_basic(t *testing.T) {
|
||||||
var nat NatGatewaySetType
|
var nat ecs.NatGatewaySetType
|
||||||
|
|
||||||
testCheck := func(*terraform.State) error {
|
testCheck := func(*terraform.State) error {
|
||||||
if nat.BusinessStatus != "Normal" {
|
if nat.BusinessStatus != "Normal" {
|
||||||
|
@ -55,7 +56,7 @@ func TestAccAlicloudNatGateway_basic(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAccAlicloudNatGateway_spec(t *testing.T) {
|
func TestAccAlicloudNatGateway_spec(t *testing.T) {
|
||||||
var nat NatGatewaySetType
|
var nat ecs.NatGatewaySetType
|
||||||
|
|
||||||
resource.Test(t, resource.TestCase{
|
resource.Test(t, resource.TestCase{
|
||||||
PreCheck: func() {
|
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 {
|
return func(s *terraform.State) error {
|
||||||
rs, ok := s.RootModule().Resources[n]
|
rs, ok := s.RootModule().Resources[n]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -151,6 +152,10 @@ func testAccCheckNatGatewayDestroy(s *terraform.State) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
const testAccNatGatewayConfig = `
|
const testAccNatGatewayConfig = `
|
||||||
|
data "alicloud_zones" "default" {
|
||||||
|
"available_resource_creation"= "VSwitch"
|
||||||
|
}
|
||||||
|
|
||||||
resource "alicloud_vpc" "foo" {
|
resource "alicloud_vpc" "foo" {
|
||||||
name = "tf_test_foo"
|
name = "tf_test_foo"
|
||||||
cidr_block = "172.16.0.0/12"
|
cidr_block = "172.16.0.0/12"
|
||||||
|
@ -159,7 +164,7 @@ resource "alicloud_vpc" "foo" {
|
||||||
resource "alicloud_vswitch" "foo" {
|
resource "alicloud_vswitch" "foo" {
|
||||||
vpc_id = "${alicloud_vpc.foo.id}"
|
vpc_id = "${alicloud_vpc.foo.id}"
|
||||||
cidr_block = "172.16.0.0/21"
|
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" {
|
resource "alicloud_nat_gateway" "foo" {
|
||||||
|
@ -169,11 +174,11 @@ resource "alicloud_nat_gateway" "foo" {
|
||||||
bandwidth_packages = [{
|
bandwidth_packages = [{
|
||||||
ip_count = 1
|
ip_count = 1
|
||||||
bandwidth = 5
|
bandwidth = 5
|
||||||
zone = "cn-beijing-b"
|
zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||||
}, {
|
}, {
|
||||||
ip_count = 2
|
ip_count = 2
|
||||||
bandwidth = 10
|
bandwidth = 10
|
||||||
zone = "cn-beijing-b"
|
zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||||
}]
|
}]
|
||||||
depends_on = [
|
depends_on = [
|
||||||
"alicloud_vswitch.foo"]
|
"alicloud_vswitch.foo"]
|
||||||
|
@ -181,6 +186,10 @@ resource "alicloud_nat_gateway" "foo" {
|
||||||
`
|
`
|
||||||
|
|
||||||
const testAccNatGatewayConfigSpec = `
|
const testAccNatGatewayConfigSpec = `
|
||||||
|
data "alicloud_zones" "default" {
|
||||||
|
"available_resource_creation"= "VSwitch"
|
||||||
|
}
|
||||||
|
|
||||||
resource "alicloud_vpc" "foo" {
|
resource "alicloud_vpc" "foo" {
|
||||||
name = "tf_test_foo"
|
name = "tf_test_foo"
|
||||||
cidr_block = "172.16.0.0/12"
|
cidr_block = "172.16.0.0/12"
|
||||||
|
@ -189,7 +198,7 @@ resource "alicloud_vpc" "foo" {
|
||||||
resource "alicloud_vswitch" "foo" {
|
resource "alicloud_vswitch" "foo" {
|
||||||
vpc_id = "${alicloud_vpc.foo.id}"
|
vpc_id = "${alicloud_vpc.foo.id}"
|
||||||
cidr_block = "172.16.0.0/21"
|
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" {
|
resource "alicloud_nat_gateway" "foo" {
|
||||||
|
@ -199,11 +208,11 @@ resource "alicloud_nat_gateway" "foo" {
|
||||||
bandwidth_packages = [{
|
bandwidth_packages = [{
|
||||||
ip_count = 1
|
ip_count = 1
|
||||||
bandwidth = 5
|
bandwidth = 5
|
||||||
zone = "cn-beijing-b"
|
zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||||
}, {
|
}, {
|
||||||
ip_count = 2
|
ip_count = 2
|
||||||
bandwidth = 10
|
bandwidth = 10
|
||||||
zone = "cn-beijing-b"
|
zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||||
}]
|
}]
|
||||||
depends_on = [
|
depends_on = [
|
||||||
"alicloud_vswitch.foo"]
|
"alicloud_vswitch.foo"]
|
||||||
|
@ -211,6 +220,10 @@ resource "alicloud_nat_gateway" "foo" {
|
||||||
`
|
`
|
||||||
|
|
||||||
const testAccNatGatewayConfigSpecUpgrade = `
|
const testAccNatGatewayConfigSpecUpgrade = `
|
||||||
|
data "alicloud_zones" "default" {
|
||||||
|
"available_resource_creation"= "VSwitch"
|
||||||
|
}
|
||||||
|
|
||||||
resource "alicloud_vpc" "foo" {
|
resource "alicloud_vpc" "foo" {
|
||||||
name = "tf_test_foo"
|
name = "tf_test_foo"
|
||||||
cidr_block = "172.16.0.0/12"
|
cidr_block = "172.16.0.0/12"
|
||||||
|
@ -219,7 +232,7 @@ resource "alicloud_vpc" "foo" {
|
||||||
resource "alicloud_vswitch" "foo" {
|
resource "alicloud_vswitch" "foo" {
|
||||||
vpc_id = "${alicloud_vpc.foo.id}"
|
vpc_id = "${alicloud_vpc.foo.id}"
|
||||||
cidr_block = "172.16.0.0/21"
|
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" {
|
resource "alicloud_nat_gateway" "foo" {
|
||||||
|
@ -229,11 +242,11 @@ resource "alicloud_nat_gateway" "foo" {
|
||||||
bandwidth_packages = [{
|
bandwidth_packages = [{
|
||||||
ip_count = 1
|
ip_count = 1
|
||||||
bandwidth = 5
|
bandwidth = 5
|
||||||
zone = "cn-beijing-b"
|
zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||||
}, {
|
}, {
|
||||||
ip_count = 2
|
ip_count = 2
|
||||||
bandwidth = 10
|
bandwidth = 10
|
||||||
zone = "cn-beijing-b"
|
zone = "${data.alicloud_zones.default.zones.0.id}"
|
||||||
}]
|
}]
|
||||||
depends_on = [
|
depends_on = [
|
||||||
"alicloud_vswitch.foo"]
|
"alicloud_vswitch.foo"]
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"github.com/denverdino/aliyungo/common"
|
"github.com/denverdino/aliyungo/common"
|
||||||
"github.com/denverdino/aliyungo/ecs"
|
"github.com/denverdino/aliyungo/ecs"
|
||||||
"github.com/hashicorp/terraform/helper/resource"
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
"time"
|
"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."))
|
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) {
|
func buildAliyunSecurityGroupArgs(d *schema.ResourceData, meta interface{}) (*ecs.CreateSecurityGroupArgs, error) {
|
||||||
|
|
|
@ -34,6 +34,7 @@ func resourceAliyunSecurityGroupRule() *schema.Resource {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
|
Computed: true,
|
||||||
ValidateFunc: validateSecurityRuleNicType,
|
ValidateFunc: validateSecurityRuleNicType,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -67,7 +68,6 @@ func resourceAliyunSecurityGroupRule() *schema.Resource {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
Default: "0.0.0.0/0",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"source_security_group_id": &schema.Schema{
|
"source_security_group_id": &schema.Schema{
|
||||||
|
@ -86,15 +86,17 @@ func resourceAliyunSecurityGroupRule() *schema.Resource {
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAliyunSecurityGroupRuleCreate(d *schema.ResourceData, meta interface{}) error {
|
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)
|
sgId := d.Get("security_group_id").(string)
|
||||||
ptl := d.Get("ip_protocol").(string)
|
ptl := d.Get("ip_protocol").(string)
|
||||||
port := d.Get("port_range").(string)
|
port := d.Get("port_range").(string)
|
||||||
|
nicType := d.Get("nic_type").(string)
|
||||||
|
|
||||||
var autherr error
|
var autherr error
|
||||||
switch GroupRuleDirection(ruleType) {
|
switch GroupRuleDirection(direction) {
|
||||||
case GroupRuleIngress:
|
case GroupRuleIngress:
|
||||||
args, err := buildAliyunSecurityIngressArgs(d, meta)
|
args, err := buildAliyunSecurityIngressArgs(d, meta)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -114,10 +116,11 @@ func resourceAliyunSecurityGroupRuleCreate(d *schema.ResourceData, meta interfac
|
||||||
if autherr != nil {
|
if autherr != nil {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"Error authorizing security group rule type %s: %s",
|
"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)
|
return resourceAliyunSecurityGroupRuleRead(d, meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,10 +128,11 @@ func resourceAliyunSecurityGroupRuleRead(d *schema.ResourceData, meta interface{
|
||||||
client := meta.(*AliyunClient)
|
client := meta.(*AliyunClient)
|
||||||
parts := strings.Split(d.Id(), ":")
|
parts := strings.Split(d.Id(), ":")
|
||||||
sgId := parts[0]
|
sgId := parts[0]
|
||||||
types := parts[1]
|
direction := parts[1]
|
||||||
ip_protocol := parts[2]
|
ip_protocol := parts[2]
|
||||||
port_range := parts[3]
|
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 err != nil {
|
||||||
if notFoundError(err) {
|
if notFoundError(err) {
|
||||||
|
@ -137,7 +141,7 @@ func resourceAliyunSecurityGroupRuleRead(d *schema.ResourceData, meta interface{
|
||||||
}
|
}
|
||||||
return fmt.Errorf("Error SecurityGroup rule: %#v", err)
|
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("type", rule.Direction)
|
||||||
d.Set("ip_protocol", strings.ToLower(string(rule.IpProtocol)))
|
d.Set("ip_protocol", strings.ToLower(string(rule.IpProtocol)))
|
||||||
d.Set("nic_type", rule.NicType)
|
d.Set("nic_type", rule.NicType)
|
||||||
|
@ -146,7 +150,7 @@ func resourceAliyunSecurityGroupRuleRead(d *schema.ResourceData, meta interface{
|
||||||
d.Set("priority", rule.Priority)
|
d.Set("priority", rule.Priority)
|
||||||
d.Set("security_group_id", sgId)
|
d.Set("security_group_id", sgId)
|
||||||
//support source and desc by type
|
//support source and desc by type
|
||||||
if GroupRuleDirection(types) == GroupRuleIngress {
|
if GroupRuleDirection(direction) == GroupRuleIngress {
|
||||||
d.Set("cidr_ip", rule.SourceCidrIp)
|
d.Set("cidr_ip", rule.SourceCidrIp)
|
||||||
d.Set("source_security_group_id", rule.SourceGroupId)
|
d.Set("source_security_group_id", rule.SourceGroupId)
|
||||||
d.Set("source_group_owner_account", rule.SourceGroupOwnerAccount)
|
d.Set("source_group_owner_account", rule.SourceGroupOwnerAccount)
|
||||||
|
@ -161,17 +165,41 @@ func resourceAliyunSecurityGroupRuleRead(d *schema.ResourceData, meta interface{
|
||||||
|
|
||||||
func resourceAliyunSecurityGroupRuleDelete(d *schema.ResourceData, meta interface{}) error {
|
func resourceAliyunSecurityGroupRuleDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
client := meta.(*AliyunClient)
|
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
|
||||||
|
}
|
||||||
|
revokeArgs := &ecs.RevokeSecurityGroupArgs{
|
||||||
|
AuthorizeSecurityGroupArgs: *args,
|
||||||
|
}
|
||||||
|
return client.RevokeSecurityGroup(revokeArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
args, err := buildAliyunSecurityEgressArgs(d, meta)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
revokeArgs := &ecs.RevokeSecurityGroupArgs{
|
revokeArgs := &ecs.RevokeSecurityGroupEgressArgs{
|
||||||
AuthorizeSecurityGroupArgs: *args,
|
AuthorizeSecurityGroupEgressArgs: *args,
|
||||||
}
|
}
|
||||||
return client.RevokeSecurityGroup(revokeArgs)
|
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) {
|
func buildAliyunSecurityIngressArgs(d *schema.ResourceData, meta interface{}) (*ecs.AuthorizeSecurityGroupArgs, error) {
|
||||||
conn := meta.(*AliyunClient).ecsconn
|
conn := meta.(*AliyunClient).ecsconn
|
||||||
|
|
||||||
|
@ -199,12 +227,17 @@ func buildAliyunSecurityIngressArgs(d *schema.ResourceData, meta interface{}) (*
|
||||||
args.NicType = ecs.NicType(v)
|
args.NicType = ecs.NicType(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
if v := d.Get("cidr_ip").(string); v != "" {
|
cidrIp := d.Get("cidr_ip").(string)
|
||||||
args.SourceCidrIp = v
|
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 != "" {
|
if sourceGroupId != "" {
|
||||||
args.SourceGroupId = v
|
args.SourceGroupId = sourceGroupId
|
||||||
}
|
}
|
||||||
|
|
||||||
if v := d.Get("source_group_owner_account").(string); v != "" {
|
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)
|
args.NicType = ecs.NicType(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
if v := d.Get("cidr_ip").(string); v != "" {
|
cidrIp := d.Get("cidr_ip").(string)
|
||||||
args.DestCidrIp = v
|
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 != "" {
|
if sourceGroupId != "" {
|
||||||
args.DestGroupId = v
|
args.DestGroupId = sourceGroupId
|
||||||
}
|
}
|
||||||
|
|
||||||
if v := d.Get("source_group_owner_account").(string); v != "" {
|
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/helper/resource"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
"log"
|
"log"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"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) {
|
func TestAccAlicloudSecurityGroupRule_Vpc_Ingress(t *testing.T) {
|
||||||
var pt ecs.PermissionType
|
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 {
|
func testAccCheckSecurityGroupRuleExists(n string, m *ecs.PermissionType) resource.TestCheckFunc {
|
||||||
return func(s *terraform.State) error {
|
return func(s *terraform.State) error {
|
||||||
rs, ok := s.RootModule().Resources[n]
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
@ -128,7 +236,8 @@ func testAccCheckSecurityGroupRuleExists(n string, m *ecs.PermissionType) resour
|
||||||
client := testAccProvider.Meta().(*AliyunClient)
|
client := testAccProvider.Meta().(*AliyunClient)
|
||||||
log.Printf("[WARN]get sg rule %s", rs.Primary.ID)
|
log.Printf("[WARN]get sg rule %s", rs.Primary.ID)
|
||||||
parts := strings.Split(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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -152,7 +261,7 @@ func testAccCheckSecurityGroupRuleDestroy(s *terraform.State) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
parts := strings.Split(rs.Primary.ID, ":")
|
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 {
|
if rule != nil {
|
||||||
return fmt.Errorf("Error SecurityGroup Rule still exist")
|
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 = `
|
const testAccSecurityGroupRuleVpcIngress = `
|
||||||
resource "alicloud_security_group" "foo" {
|
resource "alicloud_security_group" "foo" {
|
||||||
vpc_id = "${alicloud_vpc.vpc.id}"
|
vpc_id = "${alicloud_vpc.vpc.id}"
|
||||||
|
@ -231,6 +357,22 @@ resource "alicloud_security_group_rule" "ingress" {
|
||||||
cidr_ip = "10.159.6.18/12"
|
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 = `
|
const testAccSecurityGroupRuleMultiIngress = `
|
||||||
|
@ -260,4 +402,27 @@ resource "alicloud_security_group_rule" "ingress2" {
|
||||||
cidr_ip = "127.0.1.18/16"
|
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"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"errors"
|
||||||
"github.com/denverdino/aliyungo/common"
|
"github.com/denverdino/aliyungo/common"
|
||||||
"github.com/denverdino/aliyungo/slb"
|
"github.com/denverdino/aliyungo/slb"
|
||||||
"github.com/hashicorp/terraform/helper/hashcode"
|
"github.com/hashicorp/terraform/helper/hashcode"
|
||||||
|
@ -83,40 +84,124 @@ func resourceAliyunSlb() *schema.Resource {
|
||||||
ValidateFunc: validateSlbListenerBandwidth,
|
ValidateFunc: validateSlbListenerBandwidth,
|
||||||
Required: true,
|
Required: true,
|
||||||
},
|
},
|
||||||
//http
|
|
||||||
"scheduler": &schema.Schema{
|
"scheduler": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
ValidateFunc: validateSlbListenerScheduler,
|
ValidateFunc: validateSlbListenerScheduler,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: "wrr",
|
Default: slb.WRRScheduler,
|
||||||
},
|
},
|
||||||
|
//http & https
|
||||||
"sticky_session": &schema.Schema{
|
"sticky_session": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
ValidateFunc: validateSlbListenerStickySession,
|
ValidateFunc: validateAllowedStringValue([]string{
|
||||||
Optional: true,
|
string(slb.OnFlag),
|
||||||
|
string(slb.OffFlag)}),
|
||||||
|
Optional: true,
|
||||||
|
Default: slb.OffFlag,
|
||||||
},
|
},
|
||||||
|
//http & https
|
||||||
"sticky_session_type": &schema.Schema{
|
"sticky_session_type": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
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,
|
Optional: true,
|
||||||
},
|
},
|
||||||
|
//http & https
|
||||||
"cookie": &schema.Schema{
|
"cookie": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
ValidateFunc: validateSlbListenerCookie,
|
ValidateFunc: validateSlbListenerCookie,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
},
|
},
|
||||||
"PersistenceTimeout": &schema.Schema{
|
//tcp & udp
|
||||||
|
"persistence_timeout": &schema.Schema{
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
ValidateFunc: validateSlbListenerPersistenceTimeout,
|
ValidateFunc: validateSlbListenerPersistenceTimeout,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: 0,
|
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
|
//https
|
||||||
"ssl_certificate_id": &schema.Schema{
|
"ssl_certificate_id": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
},
|
},
|
||||||
|
//https
|
||||||
|
//"ca_certificate_id": &schema.Schema{
|
||||||
|
// Type: schema.TypeString,
|
||||||
|
// Optional: true,
|
||||||
|
//},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Set: resourceAliyunSlbListenerHash,
|
Set: resourceAliyunSlbListenerHash,
|
||||||
|
@ -349,44 +434,53 @@ func resourceAliyunSlbListenerHash(v interface{}) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func createListener(conn *slb.Client, loadBalancerId string, listener *Listener) error {
|
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") {
|
if listener.Protocol == strings.ToLower("tcp") {
|
||||||
args := &slb.CreateLoadBalancerTCPListenerArgs{
|
|
||||||
LoadBalancerId: loadBalancerId,
|
args := getTcpListenerArgs(loadBalancerId, listener)
|
||||||
ListenerPort: listener.LoadBalancerPort,
|
|
||||||
BackendServerPort: listener.InstancePort,
|
if err := conn.CreateLoadBalancerTCPListener(&args); err != nil {
|
||||||
Bandwidth: listener.Bandwidth,
|
|
||||||
}
|
|
||||||
if err := conn.CreateLoadBalancerTCPListener(args); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
} else if listener.Protocol == strings.ToLower("http") {
|
||||||
|
args, argsErr := getHttpListenerArgs(loadBalancerId, listener)
|
||||||
if listener.Protocol == strings.ToLower("http") {
|
if paramErr := errTypeJudge(argsErr); paramErr != nil {
|
||||||
args := &slb.CreateLoadBalancerHTTPListenerArgs{
|
return paramErr
|
||||||
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
|
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{
|
args := &slb.CreateLoadBalancerHTTPSListenerArgs{
|
||||||
|
HTTPListenerType: listenerType,
|
||||||
HTTPListenerType: slb.HTTPListenerType{
|
|
||||||
LoadBalancerId: loadBalancerId,
|
|
||||||
ListenerPort: listener.LoadBalancerPort,
|
|
||||||
BackendServerPort: listener.InstancePort,
|
|
||||||
Bandwidth: listener.Bandwidth,
|
|
||||||
StickySession: slb.OffFlag,
|
|
||||||
HealthCheck: slb.OffFlag,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
if listener.SSLCertificateId == "" {
|
if listener.SSLCertificateId == "" {
|
||||||
return fmt.Errorf("Server Certificated Id cann't be null")
|
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 {
|
if err := conn.CreateLoadBalancerHTTPSListener(args); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
} else if listener.Protocol == strings.ToLower("udp") {
|
||||||
|
args := getUdpListenerArgs(loadBalancerId, listener)
|
||||||
|
|
||||||
if listener.Protocol == strings.ToLower("udp") {
|
if err := conn.CreateLoadBalancerUDPListener(&args); err != nil {
|
||||||
args := &slb.CreateLoadBalancerUDPListenerArgs{
|
|
||||||
LoadBalancerId: loadBalancerId,
|
|
||||||
ListenerPort: listener.LoadBalancerPort,
|
|
||||||
BackendServerPort: listener.InstancePort,
|
|
||||||
Bandwidth: listener.Bandwidth,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := conn.CreateLoadBalancerUDPListener(args); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -418,3 +505,102 @@ func createListener(conn *slb.Client, loadBalancerId string, listener *Listener)
|
||||||
|
|
||||||
return nil
|
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"
|
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" {
|
resource "alicloud_instance" "foo" {
|
||||||
# cn-beijing
|
# cn-beijing
|
||||||
availability_zone = "cn-beijing-b"
|
|
||||||
image_id = "ubuntu_140405_64_40G_cloudinit_20161115.vhd"
|
image_id = "ubuntu_140405_64_40G_cloudinit_20161115.vhd"
|
||||||
|
|
||||||
# series II
|
# series II
|
||||||
|
|
|
@ -85,7 +85,7 @@ func TestAccAlicloudSlb_listener(t *testing.T) {
|
||||||
testListener := func() resource.TestCheckFunc {
|
testListener := func() resource.TestCheckFunc {
|
||||||
return func(*terraform.State) error {
|
return func(*terraform.State) error {
|
||||||
listenerPorts := slb.ListenerPorts.ListenerPort[0]
|
listenerPorts := slb.ListenerPorts.ListenerPort[0]
|
||||||
if listenerPorts != 161 {
|
if listenerPorts != 2001 {
|
||||||
return fmt.Errorf("bad loadbalancer listener: %#v", listenerPorts)
|
return fmt.Errorf("bad loadbalancer listener: %#v", listenerPorts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,21 +260,49 @@ resource "alicloud_slb" "listener" {
|
||||||
"lb_port" = "21"
|
"lb_port" = "21"
|
||||||
"lb_protocol" = "tcp"
|
"lb_protocol" = "tcp"
|
||||||
"bandwidth" = 1
|
"bandwidth" = 1
|
||||||
|
"persistence_timeout" = 500
|
||||||
|
"health_check_type" = "http"
|
||||||
},{
|
},{
|
||||||
"instance_port" = "8000"
|
"instance_port" = "8000"
|
||||||
"lb_port" = "80"
|
"lb_port" = "80"
|
||||||
"lb_protocol" = "http"
|
"lb_protocol" = "http"
|
||||||
|
"sticky_session" = "on"
|
||||||
|
"sticky_session_type" = "insert"
|
||||||
|
"cookie_timeout" = 800
|
||||||
"bandwidth" = 1
|
"bandwidth" = 1
|
||||||
},{
|
},{
|
||||||
"instance_port" = "1611"
|
"instance_port" = "8001"
|
||||||
"lb_port" = "161"
|
"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"
|
"lb_protocol" = "udp"
|
||||||
"bandwidth" = 1
|
"bandwidth" = 1
|
||||||
|
"persistence_timeout" = 700
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const testAccSlb4Vpc = `
|
const testAccSlb4Vpc = `
|
||||||
|
data "alicloud_zones" "default" {
|
||||||
|
"available_resource_creation"= "VSwitch"
|
||||||
|
}
|
||||||
|
|
||||||
resource "alicloud_vpc" "foo" {
|
resource "alicloud_vpc" "foo" {
|
||||||
name = "tf_test_foo"
|
name = "tf_test_foo"
|
||||||
cidr_block = "172.16.0.0/12"
|
cidr_block = "172.16.0.0/12"
|
||||||
|
@ -283,7 +311,7 @@ resource "alicloud_vpc" "foo" {
|
||||||
resource "alicloud_vswitch" "foo" {
|
resource "alicloud_vswitch" "foo" {
|
||||||
vpc_id = "${alicloud_vpc.foo.id}"
|
vpc_id = "${alicloud_vpc.foo.id}"
|
||||||
cidr_block = "172.16.0.0/21"
|
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" {
|
resource "alicloud_slb" "vpc" {
|
||||||
|
|
|
@ -124,6 +124,10 @@ func testAccCheckRouteEntryDestroy(s *terraform.State) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
const testAccRouteEntryConfig = `
|
const testAccRouteEntryConfig = `
|
||||||
|
data "alicloud_zones" "default" {
|
||||||
|
"available_resource_creation"= "VSwitch"
|
||||||
|
}
|
||||||
|
|
||||||
resource "alicloud_vpc" "foo" {
|
resource "alicloud_vpc" "foo" {
|
||||||
name = "tf_test_foo"
|
name = "tf_test_foo"
|
||||||
cidr_block = "10.1.0.0/21"
|
cidr_block = "10.1.0.0/21"
|
||||||
|
@ -132,7 +136,7 @@ resource "alicloud_vpc" "foo" {
|
||||||
resource "alicloud_vswitch" "foo" {
|
resource "alicloud_vswitch" "foo" {
|
||||||
vpc_id = "${alicloud_vpc.foo.id}"
|
vpc_id = "${alicloud_vpc.foo.id}"
|
||||||
cidr_block = "10.1.1.0/24"
|
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" {
|
resource "alicloud_route_entry" "foo" {
|
||||||
|
@ -162,7 +166,6 @@ resource "alicloud_security_group_rule" "ingress" {
|
||||||
|
|
||||||
resource "alicloud_instance" "foo" {
|
resource "alicloud_instance" "foo" {
|
||||||
# cn-beijing
|
# cn-beijing
|
||||||
availability_zone = "cn-beijing-c"
|
|
||||||
security_groups = ["${alicloud_security_group.tf_test_foo.id}"]
|
security_groups = ["${alicloud_security_group.tf_test_foo.id}"]
|
||||||
|
|
||||||
vswitch_id = "${alicloud_vswitch.foo.id}"
|
vswitch_id = "${alicloud_vswitch.foo.id}"
|
||||||
|
|
|
@ -92,6 +92,10 @@ func testAccCheckVswitchDestroy(s *terraform.State) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
const testAccVswitchConfig = `
|
const testAccVswitchConfig = `
|
||||||
|
data "alicloud_zones" "default" {
|
||||||
|
"available_resource_creation"= "VSwitch"
|
||||||
|
}
|
||||||
|
|
||||||
resource "alicloud_vpc" "foo" {
|
resource "alicloud_vpc" "foo" {
|
||||||
name = "tf_test_foo"
|
name = "tf_test_foo"
|
||||||
cidr_block = "172.16.0.0/12"
|
cidr_block = "172.16.0.0/12"
|
||||||
|
@ -100,6 +104,6 @@ resource "alicloud_vpc" "foo" {
|
||||||
resource "alicloud_vswitch" "foo" {
|
resource "alicloud_vswitch" "foo" {
|
||||||
vpc_id = "${alicloud_vpc.foo.id}"
|
vpc_id = "${alicloud_vpc.foo.id}"
|
||||||
cidr_block = "172.16.0.0/21"
|
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 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) {
|
func (client *AliyunClient) QueryInstancesByIds(ids []string) (instances []ecs.InstanceAttributesType, err error) {
|
||||||
idsStr, jerr := json.Marshal(ids)
|
idsStr, jerr := json.Marshal(ids)
|
||||||
if jerr != nil {
|
if jerr != nil {
|
||||||
|
@ -119,6 +137,23 @@ func (client *AliyunClient) QueryInstancesById(id string) (instance *ecs.Instanc
|
||||||
return &instances[0], nil
|
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
|
// ResourceAvailable check resource available for zone
|
||||||
func (client *AliyunClient) ResourceAvailable(zone *ecs.ZoneType, resourceType ecs.ResourceType) error {
|
func (client *AliyunClient) ResourceAvailable(zone *ecs.ZoneType, resourceType ecs.ResourceType) error {
|
||||||
available := false
|
available := false
|
||||||
|
@ -186,15 +221,26 @@ func (client *AliyunClient) DescribeSecurity(securityGroupId string) (*ecs.Descr
|
||||||
return client.ecsconn.DescribeSecurityGroupAttribute(args)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, p := range sg.Permissions.Permission {
|
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
|
return &p, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -203,6 +249,11 @@ func (client *AliyunClient) DescribeSecurityGroupRule(securityGroupId, types, ip
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *AliyunClient) RevokeSecurityGroup(args *ecs.RevokeSecurityGroupArgs) error {
|
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)
|
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
|
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,
|
RegionId: client.Region,
|
||||||
NatGatewayId: natGatewayId,
|
NatGatewayId: natGatewayId,
|
||||||
}
|
}
|
||||||
|
|
||||||
natGateways, _, err := DescribeNatGateways(client.ecsconn, args)
|
natGateways, _, err := client.vpcconn.DescribeNatGateways(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -132,3 +132,23 @@ func (client *AliyunClient) QueryRouteEntry(routeTableId, cidrBlock, nextHopType
|
||||||
}
|
}
|
||||||
return nil, nil
|
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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"net"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/denverdino/aliyungo/common"
|
"github.com/denverdino/aliyungo/common"
|
||||||
"github.com/denverdino/aliyungo/ecs"
|
"github.com/denverdino/aliyungo/ecs"
|
||||||
"github.com/hashicorp/terraform/helper/validation"
|
"github.com/denverdino/aliyungo/slb"
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
// common
|
// common
|
||||||
func validateInstancePort(v interface{}, k string) (ws []string, errors []error) {
|
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) {
|
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
|
// ecs
|
||||||
func validateDiskCategory(v interface{}, k string) (ws []string, errors []error) {
|
func validateDiskCategory(v interface{}, k string) (ws []string, errors []error) {
|
||||||
return validation.StringInSlice([]string{
|
category := ecs.DiskCategory(v.(string))
|
||||||
string(ecs.DiskCategoryCloud),
|
if category != ecs.DiskCategoryCloud && category != ecs.DiskCategoryCloudEfficiency && category != ecs.DiskCategoryCloudSSD {
|
||||||
string(ecs.DiskCategoryCloudEfficiency),
|
errors = append(errors, fmt.Errorf("%s must be one of %s %s %s", k, ecs.DiskCategoryCloud, ecs.DiskCategoryCloudEfficiency, ecs.DiskCategoryCloudSSD))
|
||||||
string(ecs.DiskCategoryCloudSSD),
|
}
|
||||||
}, false)(v, k)
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateInstanceName(v interface{}, k string) (ws []string, errors []error) {
|
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) {
|
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) {
|
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) {
|
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
|
//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) {
|
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) {
|
func validateSecurityRuleType(v interface{}, k string) (ws []string, errors []error) {
|
||||||
return validation.StringInSlice([]string{
|
rt := GroupRuleDirection(v.(string))
|
||||||
string(GroupRuleIngress),
|
if rt != GroupRuleIngress && rt != GroupRuleEgress {
|
||||||
string(GroupRuleEgress),
|
errors = append(errors, fmt.Errorf("%s must be one of %s %s", k, GroupRuleIngress, GroupRuleEgress))
|
||||||
}, false)(v, k)
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateSecurityRuleIpProtocol(v interface{}, k string) (ws []string, errors []error) {
|
func validateSecurityRuleIpProtocol(v interface{}, k string) (ws []string, errors []error) {
|
||||||
return validation.StringInSlice([]string{
|
pt := GroupRuleIpProtocol(v.(string))
|
||||||
string(GroupRuleTcp),
|
if pt != GroupRuleTcp && pt != GroupRuleUdp && pt != GroupRuleIcmp && pt != GroupRuleGre && pt != GroupRuleAll {
|
||||||
string(GroupRuleUdp),
|
errors = append(errors, fmt.Errorf("%s must be one of %s %s %s %s %s", k,
|
||||||
string(GroupRuleIcmp),
|
GroupRuleTcp, GroupRuleUdp, GroupRuleIcmp, GroupRuleGre, GroupRuleAll))
|
||||||
string(GroupRuleGre),
|
}
|
||||||
string(GroupRuleAll),
|
|
||||||
}, false)(v, k)
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateSecurityRuleNicType(v interface{}, k string) (ws []string, errors []error) {
|
func validateSecurityRuleNicType(v interface{}, k string) (ws []string, errors []error) {
|
||||||
return validation.StringInSlice([]string{
|
pt := GroupRuleNicType(v.(string))
|
||||||
string(GroupRuleInternet),
|
if pt != GroupRuleInternet && pt != GroupRuleIntranet {
|
||||||
string(GroupRuleIntranet),
|
errors = append(errors, fmt.Errorf("%s must be one of %s %s", k, GroupRuleInternet, GroupRuleIntranet))
|
||||||
}, false)(v, k)
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateSecurityRulePolicy(v interface{}, k string) (ws []string, errors []error) {
|
func validateSecurityRulePolicy(v interface{}, k string) (ws []string, errors []error) {
|
||||||
return validation.StringInSlice([]string{
|
pt := GroupRulePolicy(v.(string))
|
||||||
string(GroupRulePolicyAccept),
|
if pt != GroupRulePolicyAccept && pt != GroupRulePolicyDrop {
|
||||||
string(GroupRulePolicyDrop),
|
errors = append(errors, fmt.Errorf("%s must be one of %s %s", k, GroupRulePolicyAccept, GroupRulePolicyDrop))
|
||||||
}, false)(v, k)
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateSecurityPriority(v interface{}, k string) (ws []string, errors []error) {
|
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
|
// validateCIDRNetworkAddress ensures that the string value is a valid CIDR that
|
||||||
// represents a network address - it adds an error otherwise
|
// represents a network address - it adds an error otherwise
|
||||||
func validateCIDRNetworkAddress(v interface{}, k string) (ws []string, errors []error) {
|
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) {
|
func validateRouteEntryNextHopType(v interface{}, k string) (ws []string, errors []error) {
|
||||||
return validation.StringInSlice([]string{
|
nht := ecs.NextHopType(v.(string))
|
||||||
string(ecs.NextHopIntance),
|
if nht != ecs.NextHopIntance && nht != ecs.NextHopTunnel {
|
||||||
string(ecs.NextHopTunnel),
|
errors = append(errors, fmt.Errorf("%s must be one of %s %s", k,
|
||||||
}, false)(v, k)
|
ecs.NextHopIntance, ecs.NextHopTunnel))
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateSwitchCIDRNetworkAddress(v interface{}, k string) (ws []string, errors []error) {
|
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
|
// validateIoOptimized ensures that the string value is a valid IoOptimized that
|
||||||
// represents a IoOptimized - it adds an error otherwise
|
// represents a IoOptimized - it adds an error otherwise
|
||||||
func validateIoOptimized(v interface{}, k string) (ws []string, errors []error) {
|
func validateIoOptimized(v interface{}, k string) (ws []string, errors []error) {
|
||||||
return validation.StringInSlice([]string{
|
if value := v.(string); value != "" {
|
||||||
"",
|
ioOptimized := ecs.IoOptimized(value)
|
||||||
string(ecs.IoOptimizedNone),
|
if ioOptimized != ecs.IoOptimizedNone &&
|
||||||
string(ecs.IoOptimizedOptimized),
|
ioOptimized != ecs.IoOptimizedOptimized {
|
||||||
}, false)(v, k)
|
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
|
// validateInstanceNetworkType ensures that the string value is a classic or vpc
|
||||||
func validateInstanceNetworkType(v interface{}, k string) (ws []string, errors []error) {
|
func validateInstanceNetworkType(v interface{}, k string) (ws []string, errors []error) {
|
||||||
return validation.StringInSlice([]string{
|
if value := v.(string); value != "" {
|
||||||
"",
|
network := InstanceNetWork(value)
|
||||||
string(ClassicNet),
|
if network != ClassicNet &&
|
||||||
string(VpcNet),
|
network != VpcNet {
|
||||||
}, false)(v, k)
|
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) {
|
func validateInstanceChargeType(v interface{}, k string) (ws []string, errors []error) {
|
||||||
return validation.StringInSlice([]string{
|
if value := v.(string); value != "" {
|
||||||
"",
|
chargeType := common.InstanceChargeType(value)
|
||||||
string(common.PrePaid),
|
if chargeType != common.PrePaid &&
|
||||||
string(common.PostPaid),
|
chargeType != common.PostPaid {
|
||||||
}, false)(v, k)
|
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) {
|
func validateInternetChargeType(v interface{}, k string) (ws []string, errors []error) {
|
||||||
return validation.StringInSlice([]string{
|
if value := v.(string); value != "" {
|
||||||
"",
|
chargeType := common.InternetChargeType(value)
|
||||||
string(common.PayByBandwidth),
|
if chargeType != common.PayByBandwidth &&
|
||||||
string(common.PayByTraffic),
|
chargeType != common.PayByTraffic {
|
||||||
}, false)(v, k)
|
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) {
|
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
|
// SLB
|
||||||
func validateSlbName(v interface{}, k string) (ws []string, errors []error) {
|
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) {
|
func validateSlbInternetChargeType(v interface{}, k string) (ws []string, errors []error) {
|
||||||
return validation.StringInSlice([]string{
|
if value := v.(string); value != "" {
|
||||||
"paybybandwidth",
|
chargeType := common.InternetChargeType(value)
|
||||||
"paybytraffic",
|
|
||||||
}, false)(v, k)
|
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) {
|
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) {
|
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) {
|
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)
|
||||||
|
|
||||||
func validateSlbListenerStickySession(v interface{}, k string) (ws []string, errors []error) {
|
if scheduler != "wrr" && scheduler != "wlc" {
|
||||||
return validation.StringInSlice([]string{"", "on", "off"}, false)(v, k)
|
errors = append(errors, fmt.Errorf(
|
||||||
}
|
"%q must contain a valid SchedulerType, expected %s or %s, got %q",
|
||||||
|
k, "wrr", "wlc", value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func validateSlbListenerStickySessionType(v interface{}, k string) (ws []string, errors []error) {
|
return
|
||||||
return validation.StringInSlice([]string{"", "insert", "server"}, false)(v, k)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateSlbListenerCookie(v interface{}, k string) (ws []string, errors []error) {
|
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) {
|
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
|
//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) {
|
func validateImageOwners(v interface{}, k string) (ws []string, errors []error) {
|
||||||
return validation.StringInSlice([]string{
|
if value := v.(string); value != "" {
|
||||||
"",
|
owners := ecs.ImageOwnerAlias(value)
|
||||||
string(ecs.ImageOwnerSystem),
|
if owners != ecs.ImageOwnerSystem &&
|
||||||
string(ecs.ImageOwnerSelf),
|
owners != ecs.ImageOwnerSelf &&
|
||||||
string(ecs.ImageOwnerOthers),
|
owners != ecs.ImageOwnerOthers &&
|
||||||
string(ecs.ImageOwnerMarketplace),
|
owners != ecs.ImageOwnerMarketplace &&
|
||||||
string(ecs.ImageOwnerDefault),
|
owners != ecs.ImageOwnerDefault {
|
||||||
}, false)(v, k)
|
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) {
|
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"
|
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" {
|
resource "alicloud_disk" "disk" {
|
||||||
availability_zone = "${var.availability_zones}"
|
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"
|
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" {
|
resource "alicloud_instance" "instance" {
|
||||||
instance_name = "${var.short_name}-${var.role}-${format(var.count_format, count.index+1)}"
|
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)}"
|
host_name = "${var.short_name}-${var.role}-${format(var.count_format, count.index+1)}"
|
||||||
image_id = "${var.image_id}"
|
image_id = "${var.image_id}"
|
||||||
instance_type = "${var.ecs_type}"
|
instance_type = "${var.ecs_type}"
|
||||||
count = "${var.count}"
|
count = "${var.count}"
|
||||||
availability_zone = "${var.availability_zones}"
|
|
||||||
security_groups = ["${alicloud_security_group.group.*.id}"]
|
security_groups = ["${alicloud_security_group.group.*.id}"]
|
||||||
|
|
||||||
internet_charge_type = "${var.internet_charge_type}"
|
internet_charge_type = "${var.internet_charge_type}"
|
||||||
internet_max_bandwidth_out = "${var.internet_max_bandwidth_out}"
|
internet_max_bandwidth_out = "${var.internet_max_bandwidth_out}"
|
||||||
|
|
||||||
io_optimized = "${var.io_optimized}"
|
io_optimized = "${var.io_optimized}"
|
||||||
|
|
||||||
password = "${var.ecs_password}"
|
password = "${var.ecs_password}"
|
||||||
|
|
||||||
allocate_public_ip = "${var.allocate_public_ip}"
|
allocate_public_ip = "${var.allocate_public_ip}"
|
||||||
|
availability_zone = ""
|
||||||
instance_charge_type = "PostPaid"
|
instance_charge_type = "PostPaid"
|
||||||
system_disk_category = "cloud_efficiency"
|
system_disk_category = "cloud_efficiency"
|
||||||
|
|
||||||
|
|
||||||
tags {
|
tags {
|
||||||
role = "${var.role}"
|
role = "${var.role}"
|
||||||
dc = "${var.datacenter}"
|
dc = "${var.datacenter}"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "alicloud_slb" "instance" {
|
resource "alicloud_slb" "instance" {
|
||||||
|
|
|
@ -11,27 +11,38 @@ resource "alicloud_vswitch" "vsw" {
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "alicloud_security_group" "sg" {
|
resource "alicloud_security_group" "sg" {
|
||||||
name = "tf-sg"
|
name = "tf-sg"
|
||||||
description = "sg"
|
description = "sg"
|
||||||
vpc_id = "${alicloud_vpc.default.id}"
|
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" {
|
resource "alicloud_instance" "website" {
|
||||||
# cn-beijing
|
# cn-beijing
|
||||||
availability_zone = "${var.zone}"
|
availability_zone = "${var.zone}"
|
||||||
vswitch_id = "${alicloud_vswitch.vsw.id}"
|
vswitch_id = "${alicloud_vswitch.vsw.id}"
|
||||||
image_id = "${var.image}"
|
image_id = "${var.image}"
|
||||||
|
|
||||||
# series II
|
# series II
|
||||||
instance_type = "${var.ecs_type}"
|
instance_type = "${var.ecs_type}"
|
||||||
io_optimized = "optimized"
|
io_optimized = "optimized"
|
||||||
system_disk_category = "cloud_efficiency"
|
system_disk_category = "cloud_efficiency"
|
||||||
|
|
||||||
internet_charge_type = "PayByTraffic"
|
internet_charge_type = "PayByTraffic"
|
||||||
internet_max_bandwidth_out = 5
|
internet_max_bandwidth_out = 5
|
||||||
allocate_public_ip = true
|
allocate_public_ip = true
|
||||||
security_groups = ["${alicloud_security_group.sg.id}"]
|
security_groups = ["${alicloud_security_group.sg.id}"]
|
||||||
instance_name = "test_foo"
|
instance_name = "tf_website"
|
||||||
|
password= "${var.password}"
|
||||||
|
|
||||||
user_data = "${file("userdata.sh")}"
|
user_data = "${file("userdata.sh")}"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
output "hostname" {
|
|
||||||
value = "${alicloud_instance.website.instance_name}"
|
|
||||||
}
|
|
||||||
|
|
||||||
output "ecs_id" {
|
output "ecs_id" {
|
||||||
value = "${alicloud_instance.website.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"
|
default = "cn-beijing-b"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "password" {
|
||||||
|
default = "Test123456"
|
||||||
|
}
|
||||||
|
|
||||||
variable "image" {
|
variable "image" {
|
||||||
default = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
default = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
provider "alicloud" {
|
|
||||||
region = "${var.region}"
|
|
||||||
}
|
|
||||||
|
|
||||||
module "vpc" {
|
module "vpc" {
|
||||||
availability_zones = "${var.availability_zones}"
|
availability_zones = "${var.availability_zones}"
|
||||||
|
@ -21,14 +18,12 @@ module "control-nodes" {
|
||||||
role = "control"
|
role = "control"
|
||||||
datacenter = "${var.datacenter}"
|
datacenter = "${var.datacenter}"
|
||||||
ecs_type = "${var.control_ecs_type}"
|
ecs_type = "${var.control_ecs_type}"
|
||||||
ecs_password = "${var.ecs_password}"
|
|
||||||
disk_size = "${var.control_disk_size}"
|
disk_size = "${var.control_disk_size}"
|
||||||
ssh_username = "${var.ssh_username}"
|
ssh_username = "${var.ssh_username}"
|
||||||
short_name = "${var.short_name}"
|
short_name = "${var.short_name}"
|
||||||
availability_zones = "${module.vpc.availability_zones}"
|
availability_zones = "${module.vpc.availability_zones}"
|
||||||
security_groups = ["${module.security-groups.control_security_group}"]
|
security_groups = ["${module.security-groups.control_security_group}"]
|
||||||
vswitch_id = "${module.vpc.vswitch_ids}"
|
vswitch_id = "${module.vpc.vswitch_ids}"
|
||||||
internet_charge_type = "${var.internet_charge_type}"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module "edge-nodes" {
|
module "edge-nodes" {
|
||||||
|
@ -37,13 +32,11 @@ module "edge-nodes" {
|
||||||
role = "edge"
|
role = "edge"
|
||||||
datacenter = "${var.datacenter}"
|
datacenter = "${var.datacenter}"
|
||||||
ecs_type = "${var.edge_ecs_type}"
|
ecs_type = "${var.edge_ecs_type}"
|
||||||
ecs_password = "${var.ecs_password}"
|
|
||||||
ssh_username = "${var.ssh_username}"
|
ssh_username = "${var.ssh_username}"
|
||||||
short_name = "${var.short_name}"
|
short_name = "${var.short_name}"
|
||||||
availability_zones = "${module.vpc.availability_zones}"
|
availability_zones = "${module.vpc.availability_zones}"
|
||||||
security_groups = ["${module.security-groups.worker_security_group}"]
|
security_groups = ["${module.security-groups.worker_security_group}"]
|
||||||
vswitch_id = "${module.vpc.vswitch_ids}"
|
vswitch_id = "${module.vpc.vswitch_ids}"
|
||||||
internet_charge_type = "${var.internet_charge_type}"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module "worker-nodes" {
|
module "worker-nodes" {
|
||||||
|
@ -52,11 +45,9 @@ module "worker-nodes" {
|
||||||
role = "worker"
|
role = "worker"
|
||||||
datacenter = "${var.datacenter}"
|
datacenter = "${var.datacenter}"
|
||||||
ecs_type = "${var.worker_ecs_type}"
|
ecs_type = "${var.worker_ecs_type}"
|
||||||
ecs_password = "${var.ecs_password}"
|
|
||||||
ssh_username = "${var.ssh_username}"
|
ssh_username = "${var.ssh_username}"
|
||||||
short_name = "${var.short_name}"
|
short_name = "${var.short_name}"
|
||||||
availability_zones = "${module.vpc.availability_zones}"
|
availability_zones = "${module.vpc.availability_zones}"
|
||||||
security_groups = ["${module.security-groups.worker_security_group}"]
|
security_groups = ["${module.security-groups.worker_security_group}"]
|
||||||
vswitch_id = "${module.vpc.vswitch_ids}"
|
vswitch_id = "${module.vpc.vswitch_ids}"
|
||||||
internet_charge_type = "${var.internet_charge_type}"
|
|
||||||
}
|
}
|
|
@ -50,10 +50,6 @@ variable "availability_zones" {
|
||||||
default = "cn-beijing-c"
|
default = "cn-beijing-c"
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "internet_charge_type" {
|
|
||||||
default = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "datacenter" {
|
variable "datacenter" {
|
||||||
default = "beijing"
|
default = "beijing"
|
||||||
}
|
}
|
|
@ -18,6 +18,7 @@ variable "short_name" {
|
||||||
variable "ecs_type" {
|
variable "ecs_type" {
|
||||||
}
|
}
|
||||||
variable "ecs_password" {
|
variable "ecs_password" {
|
||||||
|
default = "Test12345"
|
||||||
}
|
}
|
||||||
variable "availability_zones" {
|
variable "availability_zones" {
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ data "alicloud_instance_types" "1c2g" {
|
||||||
}
|
}
|
||||||
|
|
||||||
data "alicloud_zones" "default" {
|
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}"
|
"available_disk_category"= "${var.disk_category}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,39 @@ resource "alicloud_security_group" "group" {
|
||||||
description = "New security 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" {
|
resource "alicloud_instance" "instance" {
|
||||||
instance_name = "${var.short_name}-${var.role}-${format(var.count_format, count.index+1)}"
|
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)}"
|
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" {
|
resource "alicloud_security_group" "group" {
|
||||||
name = "${var.short_name}"
|
name = "${var.short_name}"
|
||||||
description = "New security group"
|
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" {
|
resource "alicloud_disk" "disk" {
|
||||||
availability_zone = "${var.availability_zones}"
|
availability_zone = "${alicloud_instance.instance.0.availability_zone}"
|
||||||
category = "${var.disk_category}"
|
category = "${var.disk_category}"
|
||||||
size = "${var.disk_size}"
|
size = "${var.disk_size}"
|
||||||
count = "${var.count}"
|
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)}"
|
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)}"
|
host_name = "${var.short_name}-${var.role}-${format(var.count_format, count.index+1)}"
|
||||||
image_id = "${var.image_id}"
|
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}"
|
count = "${var.count}"
|
||||||
availability_zone = "${var.availability_zones}"
|
availability_zone = "${var.availability_zones}"
|
||||||
security_groups = ["${alicloud_security_group.group.*.id}"]
|
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)}"
|
instance_id = "${element(alicloud_instance.instance.*.id, count.index)}"
|
||||||
device_name = "${var.device_name}"
|
device_name = "${var.device_name}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,10 @@ variable "image_id" {
|
||||||
default = "ubuntu_140405_64_40G_cloudinit_20161115.vhd"
|
default = "ubuntu_140405_64_40G_cloudinit_20161115.vhd"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "availability_zones" {
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
variable "role" {
|
variable "role" {
|
||||||
default = "work"
|
default = "work"
|
||||||
}
|
}
|
||||||
|
@ -23,9 +27,6 @@ variable "ecs_type" {
|
||||||
variable "ecs_password" {
|
variable "ecs_password" {
|
||||||
default = "Test12345"
|
default = "Test12345"
|
||||||
}
|
}
|
||||||
variable "availability_zones" {
|
|
||||||
default = "cn-beijing-b"
|
|
||||||
}
|
|
||||||
variable "allocate_public_ip" {
|
variable "allocate_public_ip" {
|
||||||
default = true
|
default = true
|
||||||
}
|
}
|
||||||
|
@ -41,7 +42,7 @@ variable "io_optimized" {
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "disk_category" {
|
variable "disk_category" {
|
||||||
default = "cloud_ssd"
|
default = "cloud_efficiency"
|
||||||
}
|
}
|
||||||
variable "disk_size" {
|
variable "disk_size" {
|
||||||
default = "40"
|
default = "40"
|
||||||
|
@ -49,3 +50,7 @@ variable "disk_size" {
|
||||||
variable "device_name" {
|
variable "device_name" {
|
||||||
default = "/dev/xvdb"
|
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}"
|
name = "${var.security_group_name}"
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "alicloud_security_group_rule" "allow_all_tcp" {
|
resource "alicloud_security_group_rule" "http-in" {
|
||||||
type = "ingress"
|
type = "ingress"
|
||||||
ip_protocol = "tcp"
|
ip_protocol = "tcp"
|
||||||
nic_type = "${var.nic_type}"
|
nic_type = "internet"
|
||||||
policy = "accept"
|
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
|
priority = 1
|
||||||
security_group_id = "${alicloud_security_group.default.id}"
|
security_group_id = "${alicloud_security_group.default.id}"
|
||||||
cidr_ip = "0.0.0.0/0"
|
cidr_ip = "0.0.0.0/0"
|
||||||
|
|
Binary file not shown.
|
@ -5,21 +5,50 @@ resource "alicloud_slb" "instance" {
|
||||||
|
|
||||||
listener = [
|
listener = [
|
||||||
{
|
{
|
||||||
"instance_port" = "2111"
|
"instance_port" = "22"
|
||||||
"lb_port" = "21"
|
"lb_port" = "22"
|
||||||
"lb_protocol" = "tcp"
|
"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" = "80"
|
"lb_port" = "2001"
|
||||||
"lb_protocol" = "http"
|
|
||||||
"bandwidth" = "5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"instance_port" = "1611"
|
|
||||||
"lb_port" = "161"
|
|
||||||
"lb_protocol" = "udp"
|
"lb_protocol" = "udp"
|
||||||
"bandwidth" = "5"
|
"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"
|
||||||
|
"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,9 +23,9 @@ resource "alicloud_security_group" "sg" {
|
||||||
vpc_id = "${alicloud_vpc.default.id}"
|
vpc_id = "${alicloud_vpc.default.id}"
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "alicloud_security_group_rule" "ssh" {
|
resource "alicloud_security_group_rule" "ssh-in" {
|
||||||
type = "ingress"
|
type = "ingress"
|
||||||
ip_protocol = "tcp"
|
ip_protocol = "tcp"
|
||||||
nic_type = "intranet"
|
nic_type = "intranet"
|
||||||
policy = "${var.rule_policy}"
|
policy = "${var.rule_policy}"
|
||||||
port_range = "22/22"
|
port_range = "22/22"
|
||||||
|
@ -34,6 +34,28 @@ resource "alicloud_security_group_rule" "ssh" {
|
||||||
cidr_ip = "0.0.0.0/0"
|
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" {
|
resource "alicloud_instance" "snat" {
|
||||||
# cn-beijing
|
# cn-beijing
|
||||||
availability_zone = "${var.zone_id}"
|
availability_zone = "${var.zone_id}"
|
||||||
|
|
|
@ -7,8 +7,8 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/denverdino/aliyungo/util"
|
"github.com/denverdino/aliyungo/util"
|
||||||
)
|
)
|
||||||
|
@ -21,6 +21,9 @@ type Client struct {
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
endpoint string
|
endpoint string
|
||||||
version string
|
version string
|
||||||
|
serviceCode string
|
||||||
|
regionID Region
|
||||||
|
businessInfo string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient creates a new instance of ECS client
|
// NewClient creates a new instance of ECS client
|
||||||
|
@ -33,6 +36,26 @@ func (client *Client) Init(endpoint, version, accessKeyId, accessKeySecret strin
|
||||||
client.version = version
|
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
|
// SetEndpoint sets custom endpoint
|
||||||
func (client *Client) SetEndpoint(endpoint string) {
|
func (client *Client) SetEndpoint(endpoint string) {
|
||||||
client.endpoint = endpoint
|
client.endpoint = endpoint
|
||||||
|
@ -43,6 +66,15 @@ func (client *Client) SetVersion(version string) {
|
||||||
client.version = version
|
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
|
// SetAccessKeyId sets new AccessKeyId
|
||||||
func (client *Client) SetAccessKeyId(id string) {
|
func (client *Client) SetAccessKeyId(id string) {
|
||||||
client.AccessKeyId = id
|
client.AccessKeyId = id
|
||||||
|
@ -58,6 +90,15 @@ func (client *Client) SetDebug(debug bool) {
|
||||||
client.debug = debug
|
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
|
// Invoke sends the raw HTTP request for ECS services
|
||||||
func (client *Client) Invoke(action string, args interface{}, response interface{}) error {
|
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
|
// 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()
|
t0 := time.Now()
|
||||||
httpResp, err := client.httpClient.Do(httpReq)
|
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
|
// Invoke sends the raw HTTP request for ECS services
|
||||||
//改进了一下上面那个方法,可以使用各种Http方法
|
//改进了一下上面那个方法,可以使用各种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 := Request{}
|
||||||
request.init(client.version, action, client.AccessKeyId)
|
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)
|
signature := util.CreateSignatureForRequest(method, &data, client.AccessKeySecret)
|
||||||
|
|
||||||
data.Add("Signature", signature)
|
data.Add("Signature", signature)
|
||||||
|
|
||||||
// Generate the request URL
|
// Generate the request URL
|
||||||
var (
|
var (
|
||||||
httpReq *http.Request
|
httpReq *http.Request
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
if method == http.MethodGet {
|
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)
|
httpReq, err = http.NewRequest(method, requestURL, nil)
|
||||||
} else {
|
} 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")
|
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
|
// 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()
|
t0 := time.Now()
|
||||||
httpResp, err := client.httpClient.Do(httpReq)
|
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
|
@ -5,23 +5,28 @@ type Region string
|
||||||
|
|
||||||
// Constants of region definition
|
// Constants of region definition
|
||||||
const (
|
const (
|
||||||
Hangzhou = Region("cn-hangzhou")
|
Hangzhou = Region("cn-hangzhou")
|
||||||
Qingdao = Region("cn-qingdao")
|
Qingdao = Region("cn-qingdao")
|
||||||
Beijing = Region("cn-beijing")
|
Beijing = Region("cn-beijing")
|
||||||
Hongkong = Region("cn-hongkong")
|
Hongkong = Region("cn-hongkong")
|
||||||
Shenzhen = Region("cn-shenzhen")
|
Shenzhen = Region("cn-shenzhen")
|
||||||
USWest1 = Region("us-west-1")
|
Shanghai = Region("cn-shanghai")
|
||||||
USEast1 = Region("us-east-1")
|
Zhangjiakou = Region("cn-zhangjiakou")
|
||||||
|
|
||||||
APSouthEast1 = Region("ap-southeast-1")
|
APSouthEast1 = Region("ap-southeast-1")
|
||||||
Shanghai = Region("cn-shanghai")
|
|
||||||
MEEast1 = Region("me-east-1")
|
|
||||||
APNorthEast1 = Region("ap-northeast-1")
|
APNorthEast1 = Region("ap-northeast-1")
|
||||||
APSouthEast2 = Region("ap-southeast-2")
|
APSouthEast2 = Region("ap-southeast-2")
|
||||||
EUCentral1 = Region("eu-central-1")
|
|
||||||
|
USWest1 = Region("us-west-1")
|
||||||
|
USEast1 = Region("us-east-1")
|
||||||
|
|
||||||
|
MEEast1 = Region("me-east-1")
|
||||||
|
|
||||||
|
EUCentral1 = Region("eu-central-1")
|
||||||
)
|
)
|
||||||
|
|
||||||
var ValidRegions = []Region{
|
var ValidRegions = []Region{
|
||||||
Hangzhou, Qingdao, Beijing, Shenzhen, Hongkong, Shanghai,
|
Hangzhou, Qingdao, Beijing, Shenzhen, Hongkong, Shanghai, Zhangjiakou,
|
||||||
USWest1, USEast1,
|
USWest1, USEast1,
|
||||||
APNorthEast1, APSouthEast1, APSouthEast2,
|
APNorthEast1, APSouthEast1, APSouthEast2,
|
||||||
MEEast1,
|
MEEast1,
|
||||||
|
|
|
@ -13,3 +13,77 @@ const (
|
||||||
PrePaid = InstanceChargeType("PrePaid")
|
PrePaid = InstanceChargeType("PrePaid")
|
||||||
PostPaid = InstanceChargeType("PostPaid")
|
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
|
package ecs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/denverdino/aliyungo/common"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/denverdino/aliyungo/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Interval for checking status in WaitForXXX method
|
// Interval for checking status in WaitForXXX method
|
||||||
|
@ -19,6 +20,12 @@ const (
|
||||||
// ECSDefaultEndpoint is the default API endpoint of ECS services
|
// ECSDefaultEndpoint is the default API endpoint of ECS services
|
||||||
ECSDefaultEndpoint = "https://ecs-cn-hangzhou.aliyuncs.com"
|
ECSDefaultEndpoint = "https://ecs-cn-hangzhou.aliyuncs.com"
|
||||||
ECSAPIVersion = "2014-05-26"
|
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
|
// NewClient creates a new instance of ECS client
|
||||||
|
@ -30,8 +37,38 @@ func NewClient(accessKeyId, accessKeySecret string) *Client {
|
||||||
return NewClientWithEndpoint(endpoint, accessKeyId, accessKeySecret)
|
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 {
|
func NewClientWithEndpoint(endpoint string, accessKeyId, accessKeySecret string) *Client {
|
||||||
client := &Client{}
|
client := &Client{}
|
||||||
client.Init(endpoint, ECSAPIVersion, accessKeyId, accessKeySecret)
|
client.Init(endpoint, ECSAPIVersion, accessKeyId, accessKeySecret)
|
||||||
return client
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -63,8 +63,12 @@ type DescribeImagesResponse struct {
|
||||||
type DiskDeviceMapping struct {
|
type DiskDeviceMapping struct {
|
||||||
SnapshotId string
|
SnapshotId string
|
||||||
//Why Size Field is string-type.
|
//Why Size Field is string-type.
|
||||||
Size string
|
Size string
|
||||||
Device 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 {
|
type CreateImageArgs struct {
|
||||||
RegionId common.Region
|
RegionId common.Region
|
||||||
SnapshotId string
|
SnapshotId string
|
||||||
|
InstanceId string
|
||||||
ImageName string
|
ImageName string
|
||||||
ImageVersion string
|
ImageVersion string
|
||||||
Description string
|
Description string
|
||||||
|
@ -227,6 +232,38 @@ func (client *Client) CopyImage(args *CopyImageArgs) (string, error) {
|
||||||
return response.ImageId, nil
|
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
|
// Default timeout value for WaitForImageReady method
|
||||||
const ImageDefaultTimeout = 120
|
const ImageDefaultTimeout = 120
|
||||||
|
|
||||||
|
|
|
@ -15,12 +15,14 @@ type InstanceStatus string
|
||||||
|
|
||||||
// Constants of InstanceStatus
|
// Constants of InstanceStatus
|
||||||
const (
|
const (
|
||||||
Creating = InstanceStatus("Creating")
|
Creating = InstanceStatus("Creating") // For backward compatability
|
||||||
|
Pending = InstanceStatus("Pending")
|
||||||
Running = InstanceStatus("Running")
|
Running = InstanceStatus("Running")
|
||||||
Starting = InstanceStatus("Starting")
|
Starting = InstanceStatus("Starting")
|
||||||
|
|
||||||
Stopped = InstanceStatus("Stopped")
|
Stopped = InstanceStatus("Stopped")
|
||||||
Stopping = InstanceStatus("Stopping")
|
Stopping = InstanceStatus("Stopping")
|
||||||
|
Deleted = InstanceStatus("Deleted")
|
||||||
)
|
)
|
||||||
|
|
||||||
type LockReason string
|
type LockReason string
|
||||||
|
@ -279,6 +281,7 @@ type ModifyInstanceAttributeArgs struct {
|
||||||
Description string
|
Description string
|
||||||
Password string
|
Password string
|
||||||
HostName string
|
HostName string
|
||||||
|
UserData string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ModifyInstanceAttributeResponse struct {
|
type ModifyInstanceAttributeResponse struct {
|
||||||
|
@ -323,6 +326,38 @@ func (client *Client) WaitForInstance(instanceId string, status InstanceStatus,
|
||||||
return nil
|
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 {
|
type DescribeInstanceVncUrlArgs struct {
|
||||||
RegionId common.Region
|
RegionId common.Region
|
||||||
InstanceId string
|
InstanceId string
|
||||||
|
@ -510,6 +545,43 @@ func (client *Client) CreateInstance(args *CreateInstanceArgs) (instanceId strin
|
||||||
return response.InstanceId, err
|
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 {
|
type SecurityGroupArgs struct {
|
||||||
InstanceId string
|
InstanceId string
|
||||||
SecurityGroupId string
|
SecurityGroupId string
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
package alicloud
|
package ecs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/denverdino/aliyungo/common"
|
"github.com/denverdino/aliyungo/common"
|
||||||
"github.com/denverdino/aliyungo/ecs"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type BandwidthPackageType struct {
|
type BandwidthPackageType struct {
|
||||||
|
@ -25,6 +24,10 @@ type ForwardTableIdType struct {
|
||||||
ForwardTableId []string
|
ForwardTableId []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SnatTableIdType struct {
|
||||||
|
SnatTableId []string
|
||||||
|
}
|
||||||
|
|
||||||
type BandwidthPackageIdType struct {
|
type BandwidthPackageIdType struct {
|
||||||
BandwidthPackageId []string
|
BandwidthPackageId []string
|
||||||
}
|
}
|
||||||
|
@ -39,7 +42,7 @@ type CreateNatGatewayResponse struct {
|
||||||
// CreateNatGateway creates Virtual Private Cloud
|
// CreateNatGateway creates Virtual Private Cloud
|
||||||
//
|
//
|
||||||
// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/vpc&createvpc
|
// 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{}
|
response := CreateNatGatewayResponse{}
|
||||||
err = client.Invoke("CreateNatGateway", args, &response)
|
err = client.Invoke("CreateNatGateway", args, &response)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -53,6 +56,7 @@ type NatGatewaySetType struct {
|
||||||
Description string
|
Description string
|
||||||
BandwidthPackageIds BandwidthPackageIdType
|
BandwidthPackageIds BandwidthPackageIdType
|
||||||
ForwardTableIds ForwardTableIdType
|
ForwardTableIds ForwardTableIdType
|
||||||
|
SnatTableIds SnatTableIdType
|
||||||
InstanceChargeType string
|
InstanceChargeType string
|
||||||
Name string
|
Name string
|
||||||
NatGatewayId string
|
NatGatewayId string
|
||||||
|
@ -77,7 +81,7 @@ type DescribeNatGatewaysArgs struct {
|
||||||
common.Pagination
|
common.Pagination
|
||||||
}
|
}
|
||||||
|
|
||||||
func DescribeNatGateways(client *ecs.Client, args *DescribeNatGatewaysArgs) (natGateways []NatGatewaySetType,
|
func (client *Client) DescribeNatGateways(args *DescribeNatGatewaysArgs) (natGateways []NatGatewaySetType,
|
||||||
pagination *common.PaginationResult, err error) {
|
pagination *common.PaginationResult, err error) {
|
||||||
|
|
||||||
args.Validate()
|
args.Validate()
|
||||||
|
@ -103,7 +107,7 @@ type ModifyNatGatewayAttributeResponse struct {
|
||||||
common.Response
|
common.Response
|
||||||
}
|
}
|
||||||
|
|
||||||
func ModifyNatGatewayAttribute(client *ecs.Client, args *ModifyNatGatewayAttributeArgs) error {
|
func (client *Client) ModifyNatGatewayAttribute(args *ModifyNatGatewayAttributeArgs) error {
|
||||||
response := ModifyNatGatewayAttributeResponse{}
|
response := ModifyNatGatewayAttributeResponse{}
|
||||||
return client.Invoke("ModifyNatGatewayAttribute", args, &response)
|
return client.Invoke("ModifyNatGatewayAttribute", args, &response)
|
||||||
}
|
}
|
||||||
|
@ -114,7 +118,7 @@ type ModifyNatGatewaySpecArgs struct {
|
||||||
Spec NatGatewaySpec
|
Spec NatGatewaySpec
|
||||||
}
|
}
|
||||||
|
|
||||||
func ModifyNatGatewaySpec(client *ecs.Client, args *ModifyNatGatewaySpecArgs) error {
|
func (client *Client) ModifyNatGatewaySpec(args *ModifyNatGatewaySpecArgs) error {
|
||||||
response := ModifyNatGatewayAttributeResponse{}
|
response := ModifyNatGatewayAttributeResponse{}
|
||||||
return client.Invoke("ModifyNatGatewaySpec", args, &response)
|
return client.Invoke("ModifyNatGatewaySpec", args, &response)
|
||||||
}
|
}
|
||||||
|
@ -128,7 +132,7 @@ type DeleteNatGatewayResponse struct {
|
||||||
common.Response
|
common.Response
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteNatGateway(client *ecs.Client, args *DeleteNatGatewayArgs) error {
|
func (client *Client) DeleteNatGateway(args *DeleteNatGatewayArgs) error {
|
||||||
response := DeleteNatGatewayResponse{}
|
response := DeleteNatGatewayResponse{}
|
||||||
err := client.Invoke("DeleteNatGateway", args, &response)
|
err := client.Invoke("DeleteNatGateway", args, &response)
|
||||||
return err
|
return err
|
||||||
|
@ -140,10 +144,20 @@ type DescribeBandwidthPackagesArgs struct {
|
||||||
NatGatewayId string
|
NatGatewayId string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PublicIpAddresseType struct {
|
||||||
|
AllocationId string
|
||||||
|
IpAddress string
|
||||||
|
}
|
||||||
|
|
||||||
type DescribeBandwidthPackageType struct {
|
type DescribeBandwidthPackageType struct {
|
||||||
Bandwidth string
|
Bandwidth string
|
||||||
BandwidthPackageId string
|
BandwidthPackageId string
|
||||||
IpCount string
|
IpCount string
|
||||||
|
PublicIpAddresses struct {
|
||||||
|
PublicIpAddresse []PublicIpAddresseType
|
||||||
|
}
|
||||||
|
|
||||||
|
ZoneId string
|
||||||
}
|
}
|
||||||
|
|
||||||
type DescribeBandwidthPackagesResponse struct {
|
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{}
|
response := &DescribeBandwidthPackagesResponse{}
|
||||||
|
|
||||||
err := client.Invoke("DescribeBandwidthPackages", args, response)
|
err := client.Invoke("DescribeBandwidthPackages", args, response)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.BandwidthPackages.BandwidthPackage, err
|
return response.BandwidthPackages.BandwidthPackage, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,20 +187,12 @@ type DeleteBandwidthPackageResponse struct {
|
||||||
common.Response
|
common.Response
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteBandwidthPackage(client *ecs.Client, args *DeleteBandwidthPackageArgs) error {
|
func (client *Client) DeleteBandwidthPackage(args *DeleteBandwidthPackageArgs) error {
|
||||||
response := DeleteBandwidthPackageResponse{}
|
response := DeleteBandwidthPackageResponse{}
|
||||||
err := client.Invoke("DeleteBandwidthPackage", args, &response)
|
err := client.Invoke("DeleteBandwidthPackage", args, &response)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
type DescribeSnatTableEntriesArgs struct {
|
|
||||||
RegionId common.Region
|
|
||||||
}
|
|
||||||
|
|
||||||
func DescribeSnatTableEntries(client *ecs.Client, args *DescribeSnatTableEntriesArgs) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
type NatGatewaySpec string
|
type NatGatewaySpec string
|
||||||
|
|
||||||
const (
|
const (
|
|
@ -33,6 +33,7 @@ type DescribeSecurityGroupAttributeArgs struct {
|
||||||
SecurityGroupId string
|
SecurityGroupId string
|
||||||
RegionId common.Region
|
RegionId common.Region
|
||||||
NicType NicType //enum for internet (default) |intranet
|
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
|
package slb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/denverdino/aliyungo/common"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/denverdino/aliyungo/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
|
@ -13,6 +14,8 @@ const (
|
||||||
// SLBDefaultEndpoint is the default API endpoint of SLB services
|
// SLBDefaultEndpoint is the default API endpoint of SLB services
|
||||||
SLBDefaultEndpoint = "https://slb.aliyuncs.com"
|
SLBDefaultEndpoint = "https://slb.aliyuncs.com"
|
||||||
SLBAPIVersion = "2014-05-15"
|
SLBAPIVersion = "2014-05-15"
|
||||||
|
|
||||||
|
SLBServiceCode = "slb"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewClient creates a new instance of ECS client
|
// 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)
|
client.Init(endpoint, SLBAPIVersion, accessKeyId, accessKeySecret)
|
||||||
return client
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -138,22 +138,22 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type TCPListenerType struct {
|
type TCPListenerType struct {
|
||||||
LoadBalancerId string
|
LoadBalancerId string
|
||||||
ListenerPort int
|
ListenerPort int
|
||||||
BackendServerPort int
|
BackendServerPort int
|
||||||
Bandwidth int
|
Bandwidth int
|
||||||
Scheduler SchedulerType
|
Scheduler SchedulerType
|
||||||
PersistenceTimeout int
|
PersistenceTimeout int
|
||||||
HealthCheckType HealthCheckType
|
HealthCheckType HealthCheckType
|
||||||
HealthCheckDomain string
|
HealthCheckDomain string
|
||||||
HealthCheckURI string
|
HealthCheckURI string
|
||||||
HealthCheckConnectPort int
|
HealthCheckConnectPort int
|
||||||
HealthyThreshold int
|
HealthyThreshold int
|
||||||
UnhealthyThreshold int
|
UnhealthyThreshold int
|
||||||
HealthCheckTimeout int
|
HealthCheckConnectTimeout int
|
||||||
HealthCheckInterval int
|
HealthCheckInterval int
|
||||||
HealthCheckHttpCode HealthCheckHttpCodeType
|
HealthCheckHttpCode HealthCheckHttpCodeType
|
||||||
VServerGroupId string
|
VServerGroupId string
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateLoadBalancerTCPListenerArgs TCPListenerType
|
type CreateLoadBalancerTCPListenerArgs TCPListenerType
|
||||||
|
@ -168,18 +168,18 @@ func (client *Client) CreateLoadBalancerTCPListener(args *CreateLoadBalancerTCPL
|
||||||
}
|
}
|
||||||
|
|
||||||
type UDPListenerType struct {
|
type UDPListenerType struct {
|
||||||
LoadBalancerId string
|
LoadBalancerId string
|
||||||
ListenerPort int
|
ListenerPort int
|
||||||
BackendServerPort int
|
BackendServerPort int
|
||||||
Bandwidth int
|
Bandwidth int
|
||||||
Scheduler SchedulerType
|
Scheduler SchedulerType
|
||||||
PersistenceTimeout int
|
PersistenceTimeout int
|
||||||
HealthCheckConnectPort int
|
HealthCheckConnectPort int
|
||||||
HealthyThreshold int
|
HealthyThreshold int
|
||||||
UnhealthyThreshold int
|
UnhealthyThreshold int
|
||||||
HealthCheckTimeout int
|
HealthCheckConnectTimeout int
|
||||||
HealthCheckInterval int
|
HealthCheckInterval int
|
||||||
VServerGroupId string
|
VServerGroupId string
|
||||||
}
|
}
|
||||||
type CreateLoadBalancerUDPListenerArgs UDPListenerType
|
type CreateLoadBalancerUDPListenerArgs UDPListenerType
|
||||||
|
|
||||||
|
|
|
@ -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
|
type SetBackendServersResponse AddBackendServersResponse
|
||||||
|
|
||||||
|
|
||||||
// SetBackendServers set weight of backend servers
|
// SetBackendServers set weight of backend servers
|
||||||
|
|
||||||
func (client *Client) SetBackendServers(loadBalancerId string, backendServers []BackendServerType) (result []BackendServerType, err error) {
|
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
|
return response.BackendServers.BackendServer, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// AddBackendServers Add backend servers
|
// AddBackendServers Add backend servers
|
||||||
//
|
//
|
||||||
// You can read doc at http://docs.aliyun.com/#/pub/slb/api-reference/api-related-backendserver&AddBackendServers
|
// 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"
|
"revisionTime": "2016-10-29T20:57:26Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "ADySw3nBHyzEHB6afBSeVRN2A4g=",
|
"checksumSHA1": "SdiAYZOqWQ60ifRUHLwLiDMKMYA=",
|
||||||
"path": "github.com/denverdino/aliyungo/common",
|
"path": "github.com/denverdino/aliyungo/common",
|
||||||
"revision": "d123f5d1fa71b211b70b2e9b56a62da21076884a",
|
"revision": "c4c75afbf7ea86e66672c1b6ed981385b4ad5ec2",
|
||||||
"revisionTime": "2017-01-17T10:57:15Z"
|
"revisionTime": "2017-03-21T07:55:32Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "9ZY3RlumKp5DAMfL08YwMoOOT2o=",
|
"checksumSHA1": "UVYu5rvfoXgJnIpUyGcaovMvpms=",
|
||||||
"path": "github.com/denverdino/aliyungo/ecs",
|
"path": "github.com/denverdino/aliyungo/ecs",
|
||||||
"revision": "d123f5d1fa71b211b70b2e9b56a62da21076884a",
|
"revision": "c4c75afbf7ea86e66672c1b6ed981385b4ad5ec2",
|
||||||
"revisionTime": "2017-01-17T10:57:15Z"
|
"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",
|
"path": "github.com/denverdino/aliyungo/slb",
|
||||||
"revision": "d123f5d1fa71b211b70b2e9b56a62da21076884a",
|
"revision": "c4c75afbf7ea86e66672c1b6ed981385b4ad5ec2",
|
||||||
"revisionTime": "2017-01-17T10:57:15Z"
|
"revisionTime": "2017-03-21T07:55:32Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "Lp0KtT7ycgq31ox3Uzhpxyw0U+Y=",
|
"checksumSHA1": "Lp0KtT7ycgq31ox3Uzhpxyw0U+Y=",
|
||||||
"path": "github.com/denverdino/aliyungo/util",
|
"path": "github.com/denverdino/aliyungo/util",
|
||||||
"revision": "d123f5d1fa71b211b70b2e9b56a62da21076884a",
|
"revision": "c4c75afbf7ea86e66672c1b6ed981385b4ad5ec2",
|
||||||
"revisionTime": "2017-01-17T10:57:15Z"
|
"revisionTime": "2017-03-21T07:55:32Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "yDQQpeUxwqB3C+4opweg6znWJQk=",
|
"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:
|
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.
|
* `image_id` - (Required) The Image to use for the instance.
|
||||||
* `instance_type` - (Required) The type of instance to start.
|
* `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.
|
* `io_optimized` - (Required) Valid values are `none`, `optimized`, If `optimized`, the launched ECS instance will be I/O optimized.
|
||||||
`security_group_ids` instead.
|
* `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,
|
* `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.
|
* `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_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.
|
* `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.
|
* `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.
|
* `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`.
|
* `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].
|
* `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.
|
* `tags` - (Optional) A mapping of tags to assign to the resource.
|
||||||
|
|
||||||
## Attributes Reference
|
## Attributes Reference
|
||||||
|
|
Loading…
Reference in New Issue