provider/alicloud: change create ecs postpaid instance API (#12226)

* change create ecs postpaid instance API form createInstance to runInstances, support BusinessInfo and userdata

* update sdk vendor
This commit is contained in:
demonwy 2017-03-15 22:50:17 +08:00 committed by Paul Stack
parent fff0b694f7
commit ffc5a06cb5
36 changed files with 911 additions and 176 deletions

View File

@ -2,6 +2,7 @@ package alicloud
import (
"github.com/denverdino/aliyungo/common"
"github.com/denverdino/aliyungo/ecs"
"github.com/hashicorp/terraform/helper/schema"
)
@ -50,3 +51,10 @@ func isProtocalValid(value string) bool {
}
return res
}
var DefaultBusinessInfo = ecs.BusinessInfo{
Pack: "terraform",
}
// default region for all resource
const DEFAULT_REGION = "cn-beijing"

View File

@ -19,8 +19,10 @@ type Config struct {
type AliyunClient struct {
Region common.Region
ecsconn *ecs.Client
vpcconn *ecs.Client
slbconn *slb.Client
// use new version
ecsNewconn *ecs.Client
vpcconn *ecs.Client
slbconn *slb.Client
}
// Client for AliyunClient
@ -35,6 +37,12 @@ func (c *Config) Client() (*AliyunClient, error) {
return nil, err
}
ecsNewconn, err := c.ecsConn()
if err != nil {
return nil, err
}
ecsNewconn.SetVersion(EcsApiVersion20160314)
slbconn, err := c.slbConn()
if err != nil {
return nil, err
@ -46,13 +54,27 @@ func (c *Config) Client() (*AliyunClient, error) {
}
return &AliyunClient{
Region: c.Region,
ecsconn: ecsconn,
vpcconn: vpcconn,
slbconn: slbconn,
Region: c.Region,
ecsconn: ecsconn,
ecsNewconn: ecsNewconn,
vpcconn: vpcconn,
slbconn: slbconn,
}, nil
}
// return new ecs Client
// when you need new client not global client, use this method
func (c *Config) NewEcsConn() (*ecs.Client, error) {
client := ecs.NewClient(c.AccessKey, c.SecretKey)
_, err := client.DescribeRegions()
if err != nil {
return nil, err
}
return client, nil
}
func (c *Config) loadAndValidate() error {
err := c.validateRegion()
if err != nil {

View File

@ -5,10 +5,10 @@ import (
"log"
"regexp"
"sort"
"time"
"github.com/denverdino/aliyungo/ecs"
"github.com/hashicorp/terraform/helper/schema"
"time"
)
func dataSourceAlicloudImages() *schema.Resource {
@ -175,15 +175,28 @@ func dataSourceAlicloudImagesRead(d *schema.ResourceData, meta interface{}) erro
params.ImageOwnerAlias = ecs.ImageOwnerAlias(owners.(string))
}
resp, _, err := conn.DescribeImages(params)
if err != nil {
return err
var allImages []ecs.ImageType
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
if nameRegexOk {
r := regexp.MustCompile(nameRegex.(string))
for _, image := range resp {
for _, image := range allImages {
// Check for a very rare case where the response would include no
// image name. No name means nothing to attempt a match against,
// therefore we are skipping such image.
@ -198,7 +211,7 @@ func dataSourceAlicloudImagesRead(d *schema.ResourceData, meta interface{}) erro
}
}
} else {
filteredImages = resp[:]
filteredImages = allImages[:]
}
var images []ecs.ImageType

View File

@ -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_1404")),
),
},
},
})
}
// Instance store test - using centos images
const testAccCheckAlicloudImagesDataSourceImagesConfig = `
data "alicloud_images" "multi_image" {
@ -128,3 +144,12 @@ data "alicloud_images" "name_regex_filtered_image" {
name_regex = "^centos_6\\w{1,5}[64]{1}.*"
}
`
// Testing image not in first page response
const testAccCheckAlicloudImagesDataSourceImageNotInFirstPageConfig = `
data "alicloud_images" "name_regex_filtered_image" {
most_recent = true
owners = "system"
name_regex = "^ubuntu_1404\\d{2}_64"
}
`

View File

@ -17,8 +17,6 @@ func TestAccAlicloudInstanceTypesDataSource_basic(t *testing.T) {
Check: resource.ComposeTestCheckFunc(
testAccCheckAlicloudDataSourceID("data.alicloud_instance_types.4c8g"),
resource.TestCheckResourceAttr("data.alicloud_instance_types.4c8g", "instance_types.#", "4"),
resource.TestCheckResourceAttr("data.alicloud_instance_types.4c8g", "instance_types.0.cpu_core_count", "4"),
resource.TestCheckResourceAttr("data.alicloud_instance_types.4c8g", "instance_types.0.memory_size", "8"),
resource.TestCheckResourceAttr("data.alicloud_instance_types.4c8g", "instance_types.0.id", "ecs.s3.large"),

View File

@ -71,9 +71,6 @@ func TestAccAlicloudRegionsDataSource_empty(t *testing.T) {
Check: resource.ComposeTestCheckFunc(
testAccCheckAlicloudDataSourceID("data.alicloud_regions.empty_params_region"),
resource.TestCheckResourceAttr("data.alicloud_regions.empty_params_region", "name", ""),
resource.TestCheckResourceAttr("data.alicloud_regions.empty_params_region", "current", ""),
resource.TestCheckResourceAttr("data.alicloud_regions.empty_params_region", "regions.#", "13"),
resource.TestCheckResourceAttr("data.alicloud_regions.empty_params_region", "regions.0.id", "cn-shenzhen"),

View File

@ -1,7 +1,10 @@
package alicloud
import (
"fmt"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"strconv"
"testing"
)
@ -23,6 +26,35 @@ func TestAccAlicloudZonesDataSource_basic(t *testing.T) {
}
func TestAccAlicloudZonesDataSource_filter(t *testing.T) {
// the zone length changed occasionally
// check by range to avoid test case failure
testCheckZoneLength := func(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
}
}
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
@ -33,7 +65,7 @@ func TestAccAlicloudZonesDataSource_filter(t *testing.T) {
Config: testAccCheckAlicloudZonesDataSourceFilter,
Check: resource.ComposeTestCheckFunc(
testAccCheckAlicloudDataSourceID("data.alicloud_zones.foo"),
resource.TestCheckResourceAttr("data.alicloud_zones.foo", "zones.#", "2"),
testCheckZoneLength("data.alicloud_zones.foo"),
),
},
@ -41,7 +73,7 @@ func TestAccAlicloudZonesDataSource_filter(t *testing.T) {
Config: testAccCheckAlicloudZonesDataSourceFilterIoOptimized,
Check: resource.ComposeTestCheckFunc(
testAccCheckAlicloudDataSourceID("data.alicloud_zones.foo"),
resource.TestCheckResourceAttr("data.alicloud_zones.foo", "zones.#", "1"),
testCheckZoneLength("data.alicloud_zones.foo"),
),
},
},

View File

@ -30,3 +30,8 @@ const (
GroupRulePolicyAccept = GroupRulePolicy("accept")
GroupRulePolicyDrop = GroupRulePolicy("drop")
)
const (
EcsApiVersion20160314 = "2016-03-14"
EcsApiVersion20140526 = "2014-05-26"
)

View File

@ -26,7 +26,7 @@ func Provider() terraform.ResourceProvider {
"region": &schema.Schema{
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_REGION", "cn-beijing"),
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_REGION", DEFAULT_REGION),
Description: descriptions["region"],
},
},

View File

@ -136,9 +136,13 @@ func testAccCheckDiskDestroy(s *terraform.State) error {
}
const testAccDiskConfig = `
data "alicloud_zones" "default" {
"available_disk_category"= "cloud_efficiency"
}
resource "alicloud_disk" "foo" {
# cn-beijing
availability_zone = "cn-beijing-b"
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
name = "New-disk"
description = "Hello ecs disk."
category = "cloud_efficiency"
@ -146,10 +150,15 @@ resource "alicloud_disk" "foo" {
}
`
const testAccDiskConfigWithTags = `
data "alicloud_zones" "default" {
"available_disk_category"= "cloud_efficiency"
}
resource "alicloud_disk" "bar" {
# cn-beijing
availability_zone = "cn-beijing-b"
size = "10"
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
category = "cloud_efficiency"
size = "20"
tags {
Name = "TerraformTest"
}

View File

@ -5,6 +5,7 @@ import (
"log"
"encoding/base64"
"encoding/json"
"github.com/denverdino/aliyungo/common"
"github.com/denverdino/aliyungo/ecs"
"github.com/hashicorp/terraform/helper/schema"
@ -21,8 +22,9 @@ func resourceAliyunInstance() *schema.Resource {
Schema: map[string]*schema.Schema{
"availability_zone": &schema.Schema{
Type: schema.TypeString,
Required: true,
Optional: true,
ForceNew: true,
Computed: true,
},
"image_id": &schema.Schema{
@ -61,8 +63,11 @@ func resourceAliyunInstance() *schema.Resource {
},
"instance_network_type": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
ValidateFunc: validateInstanceNetworkType,
},
"internet_charge_type": &schema.Schema{
@ -145,7 +150,6 @@ func resourceAliyunInstance() *schema.Resource {
"private_ip": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
@ -168,6 +172,11 @@ func resourceAliyunInstance() *schema.Resource {
func resourceAliyunInstanceCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AliyunClient).ecsconn
// create postpaid instance by runInstances API
if v := d.Get("instance_charge_type").(string); v != string(common.PrePaid) {
return resourceAliyunRunInstance(d, meta)
}
args, err := buildAliyunInstanceArgs(d, meta)
if err != nil {
return err
@ -207,6 +216,49 @@ func resourceAliyunInstanceCreate(d *schema.ResourceData, meta interface{}) erro
return resourceAliyunInstanceUpdate(d, meta)
}
func resourceAliyunRunInstance(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AliyunClient).ecsconn
newConn := meta.(*AliyunClient).ecsNewconn
args, err := buildAliyunInstanceArgs(d, meta)
if err != nil {
return err
}
runArgs, err := buildAliyunRunInstancesArgs(d, meta)
if err != nil {
return err
}
runArgs.CreateInstanceArgs = *args
// runInstances is support in version 2016-03-14
instanceIds, err := newConn.RunInstances(runArgs)
if err != nil {
return fmt.Errorf("Error creating Aliyun ecs instance: %#v", err)
}
d.SetId(instanceIds[0])
d.Set("password", d.Get("password"))
d.Set("system_disk_category", d.Get("system_disk_category"))
if d.Get("allocate_public_ip").(bool) {
_, err := conn.AllocatePublicIpAddress(d.Id())
if err != nil {
log.Printf("[DEBUG] AllocatePublicIpAddress for instance got error: %#v", err)
}
}
// after instance created, its status change from pending, starting to running
if err := conn.WaitForInstanceAsyn(d.Id(), ecs.Running, defaultTimeout); err != nil {
log.Printf("[DEBUG] WaitForInstance %s got error: %#v", ecs.Running, err)
}
return resourceAliyunInstanceUpdate(d, meta)
}
func resourceAliyunInstanceRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*AliyunClient)
conn := client.ecsconn
@ -414,33 +466,68 @@ func resourceAliyunInstanceDelete(d *schema.ResourceData, meta interface{}) erro
return nil
}
func buildAliyunRunInstancesArgs(d *schema.ResourceData, meta interface{}) (*ecs.RunInstanceArgs, error) {
args := &ecs.RunInstanceArgs{
MaxAmount: 1,
MinAmount: 1,
}
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 == "" && networkValue == "" {
args.NetworkType = string(ClassicNet)
}
return args, nil
}
func buildAliyunInstanceArgs(d *schema.ResourceData, meta interface{}) (*ecs.CreateInstanceArgs, error) {
client := meta.(*AliyunClient)
args := &ecs.CreateInstanceArgs{
RegionId: getRegion(d, meta),
InstanceType: d.Get("instance_type").(string),
PrivateIpAddress: d.Get("private_ip").(string),
RegionId: getRegion(d, meta),
InstanceType: d.Get("instance_type").(string),
}
imageID := d.Get("image_id").(string)
args.ImageId = imageID
systemDiskCategory := ecs.DiskCategory(d.Get("system_disk_category").(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 {
return nil, err
args.SystemDisk = ecs.SystemDiskType{
Category: systemDiskCategory,
}
args.ZoneId = zoneID
sgs, ok := d.GetOk("security_groups")
if ok {
@ -454,16 +541,6 @@ func buildAliyunInstanceArgs(d *schema.ResourceData, meta interface{}) (*ecs.Cre
}
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 != "" {
args.InstanceName = v
}
@ -490,7 +567,11 @@ func buildAliyunInstanceArgs(d *schema.ResourceData, meta interface{}) (*ecs.Cre
}
if v := d.Get("io_optimized").(string); v != "" {
args.IoOptimized = ecs.IoOptimized(v)
if v == "optimized" {
args.IoOptimized = ecs.IoOptimized("true")
} else {
args.IoOptimized = ecs.IoOptimized("false")
}
}
vswitchValue := d.Get("subnet_id").(string)

View File

@ -355,10 +355,6 @@ func TestAccAlicloudInstance_tags(t *testing.T) {
Config: testAccCheckInstanceConfigTagsUpdate,
Check: resource.ComposeTestCheckFunc(
testAccCheckInstanceExists("alicloud_instance.foo", &instance),
resource.TestCheckResourceAttr(
"alicloud_instance.foo",
"tags.foo",
""),
resource.TestCheckResourceAttr(
"alicloud_instance.foo",
"tags.bar",
@ -418,8 +414,8 @@ func TestAccAlicloudInstance_privateIP(t *testing.T) {
testCheckPrivateIP := func() resource.TestCheckFunc {
return func(*terraform.State) error {
privateIP := instance.VpcAttributes.PrivateIpAddress.IpAddress[0]
if privateIP != "172.16.0.229" {
return fmt.Errorf("bad private IP: %s", privateIP)
if privateIP == "" {
return fmt.Errorf("can't get private IP")
}
return nil
@ -445,14 +441,14 @@ func TestAccAlicloudInstance_privateIP(t *testing.T) {
})
}
func TestAccAlicloudInstance_associatePublicIPAndPrivateIP(t *testing.T) {
func TestAccAlicloudInstance_associatePublicIP(t *testing.T) {
var instance ecs.InstanceAttributesType
testCheckPrivateIP := func() resource.TestCheckFunc {
return func(*terraform.State) error {
privateIP := instance.VpcAttributes.PrivateIpAddress.IpAddress[0]
if privateIP != "172.16.0.229" {
return fmt.Errorf("bad private IP: %s", privateIP)
if privateIP == "" {
return fmt.Errorf("can't get private IP")
}
return nil
@ -468,7 +464,7 @@ func TestAccAlicloudInstance_associatePublicIPAndPrivateIP(t *testing.T) {
CheckDestroy: testAccCheckInstanceDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccInstanceConfigAssociatePublicIPAndPrivateIP,
Config: testAccInstanceConfigAssociatePublicIP,
Check: resource.ComposeTestCheckFunc(
testAccCheckInstanceExists("alicloud_instance.foo", &instance),
testCheckPrivateIP(),
@ -609,8 +605,6 @@ resource "alicloud_security_group" "tf_test_bar" {
}
resource "alicloud_instance" "foo" {
# cn-beijing
availability_zone = "cn-beijing-b"
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
system_disk_category = "cloud_ssd"
@ -628,6 +622,11 @@ resource "alicloud_instance" "foo" {
}
`
const testAccInstanceConfigVPC = `
data "alicloud_zones" "default" {
"available_disk_category"= "cloud_efficiency"
"available_resource_creation"= "VSwitch"
}
resource "alicloud_vpc" "foo" {
name = "tf_test_foo"
cidr_block = "172.16.0.0/12"
@ -636,7 +635,7 @@ resource "alicloud_vpc" "foo" {
resource "alicloud_vswitch" "foo" {
vpc_id = "${alicloud_vpc.foo.id}"
cidr_block = "172.16.0.0/21"
availability_zone = "cn-beijing-b"
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
}
resource "alicloud_security_group" "tf_test_foo" {
@ -647,7 +646,6 @@ resource "alicloud_security_group" "tf_test_foo" {
resource "alicloud_instance" "foo" {
# cn-beijing
availability_zone = "cn-beijing-b"
vswitch_id = "${alicloud_vswitch.foo.id}"
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
@ -666,6 +664,11 @@ resource "alicloud_instance" "foo" {
`
const testAccInstanceConfigUserData = `
data "alicloud_zones" "default" {
"available_disk_category"= "cloud_efficiency"
"available_resource_creation"= "VSwitch"
}
resource "alicloud_vpc" "foo" {
name = "tf_test_foo"
cidr_block = "172.16.0.0/12"
@ -674,7 +677,7 @@ resource "alicloud_vpc" "foo" {
resource "alicloud_vswitch" "foo" {
vpc_id = "${alicloud_vpc.foo.id}"
cidr_block = "172.16.0.0/21"
availability_zone = "cn-beijing-b"
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
}
resource "alicloud_security_group" "tf_test_foo" {
@ -685,7 +688,6 @@ resource "alicloud_security_group" "tf_test_foo" {
resource "alicloud_instance" "foo" {
# cn-beijing
availability_zone = "cn-beijing-b"
vswitch_id = "${alicloud_vswitch.foo.id}"
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
# series II
@ -727,7 +729,6 @@ resource "alicloud_security_group" "tf_test_bar" {
resource "alicloud_instance" "foo" {
# cn-beijing
provider = "alicloud.beijing"
availability_zone = "cn-beijing-b"
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
internet_charge_type = "PayByBandwidth"
@ -742,7 +743,6 @@ resource "alicloud_instance" "foo" {
resource "alicloud_instance" "bar" {
# cn-shanghai
provider = "alicloud.shanghai"
availability_zone = "cn-shanghai-b"
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
internet_charge_type = "PayByBandwidth"
@ -768,7 +768,6 @@ resource "alicloud_security_group" "tf_test_bar" {
resource "alicloud_instance" "foo" {
# cn-beijing
availability_zone = "cn-beijing-b"
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
instance_type = "ecs.s2.large"
@ -776,6 +775,7 @@ resource "alicloud_instance" "foo" {
security_groups = ["${alicloud_security_group.tf_test_foo.id}", "${alicloud_security_group.tf_test_bar.id}"]
instance_name = "test_foo"
io_optimized = "optimized"
system_disk_category = "cloud_efficiency"
}`
const testAccInstanceConfig_multiSecurityGroup_add = `
@ -796,7 +796,6 @@ resource "alicloud_security_group" "tf_test_add_sg" {
resource "alicloud_instance" "foo" {
# cn-beijing
availability_zone = "cn-beijing-b"
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
instance_type = "ecs.s2.large"
@ -805,6 +804,7 @@ resource "alicloud_instance" "foo" {
"${alicloud_security_group.tf_test_add_sg.id}"]
instance_name = "test_foo"
io_optimized = "optimized"
system_disk_category = "cloud_efficiency"
}
`
@ -816,7 +816,6 @@ resource "alicloud_security_group" "tf_test_foo" {
resource "alicloud_instance" "foo" {
# cn-beijing
availability_zone = "cn-beijing-b"
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
instance_type = "ecs.s2.large"
@ -824,6 +823,7 @@ resource "alicloud_instance" "foo" {
security_groups = ["${alicloud_security_group.tf_test_foo.id}"]
instance_name = "test_foo"
io_optimized = "optimized"
system_disk_category = "cloud_efficiency"
}
`
@ -836,18 +836,23 @@ resource "alicloud_security_group" "tf_test_foo" {
resource "alicloud_instance" "foo" {
# cn-beijing
availability_zone = "cn-beijing-b"
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
instance_type = "ecs.s2.large"
internet_charge_type = "PayByBandwidth"
security_groups = ["${alicloud_security_group.tf_test_foo.*.id}"]
instance_name = "test_foo"
io_optimized = "none"
io_optimized = "optimized"
system_disk_category = "cloud_efficiency"
}
`
const testAccInstanceNetworkInstanceSecurityGroups = `
data "alicloud_zones" "default" {
"available_disk_category"= "cloud_efficiency"
"available_resource_creation"= "VSwitch"
}
resource "alicloud_vpc" "foo" {
name = "tf_test_foo"
cidr_block = "172.16.0.0/12"
@ -856,7 +861,7 @@ resource "alicloud_vpc" "foo" {
resource "alicloud_vswitch" "foo" {
vpc_id = "${alicloud_vpc.foo.id}"
cidr_block = "172.16.0.0/21"
availability_zone = "cn-beijing-b"
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
}
resource "alicloud_security_group" "tf_test_foo" {
@ -867,7 +872,6 @@ resource "alicloud_security_group" "tf_test_foo" {
resource "alicloud_instance" "foo" {
# cn-beijing
availability_zone = "cn-beijing-b"
vswitch_id = "${alicloud_vswitch.foo.id}"
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
@ -892,7 +896,6 @@ resource "alicloud_security_group" "tf_test_foo" {
resource "alicloud_instance" "foo" {
# cn-beijing
availability_zone = "cn-beijing-b"
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
# series II
@ -918,7 +921,6 @@ resource "alicloud_security_group" "tf_test_foo" {
resource "alicloud_instance" "foo" {
# cn-beijing
availability_zone = "cn-beijing-b"
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
# series II
@ -943,7 +945,6 @@ resource "alicloud_security_group" "tf_test_foo" {
resource "alicloud_instance" "foo" {
# cn-beijing
availability_zone = "cn-beijing-b"
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
# series II
@ -967,7 +968,6 @@ resource "alicloud_security_group" "tf_test_foo" {
resource "alicloud_instance" "foo" {
# cn-beijing
availability_zone = "cn-beijing-b"
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
# series II
@ -984,6 +984,11 @@ resource "alicloud_instance" "foo" {
`
const testAccInstanceConfigPrivateIP = `
data "alicloud_zones" "default" {
"available_disk_category"= "cloud_efficiency"
"available_resource_creation"= "VSwitch"
}
resource "alicloud_vpc" "foo" {
name = "tf_test_foo"
cidr_block = "172.16.0.0/12"
@ -992,7 +997,7 @@ resource "alicloud_vpc" "foo" {
resource "alicloud_vswitch" "foo" {
vpc_id = "${alicloud_vpc.foo.id}"
cidr_block = "172.16.0.0/24"
availability_zone = "cn-beijing-b"
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
}
resource "alicloud_security_group" "tf_test_foo" {
@ -1003,11 +1008,9 @@ resource "alicloud_security_group" "tf_test_foo" {
resource "alicloud_instance" "foo" {
# cn-beijing
availability_zone = "cn-beijing-b"
security_groups = ["${alicloud_security_group.tf_test_foo.id}"]
vswitch_id = "${alicloud_vswitch.foo.id}"
private_ip = "172.16.0.229"
# series II
instance_type = "ecs.n1.medium"
@ -1017,7 +1020,12 @@ resource "alicloud_instance" "foo" {
instance_name = "test_foo"
}
`
const testAccInstanceConfigAssociatePublicIPAndPrivateIP = `
const testAccInstanceConfigAssociatePublicIP = `
data "alicloud_zones" "default" {
"available_disk_category"= "cloud_efficiency"
"available_resource_creation"= "VSwitch"
}
resource "alicloud_vpc" "foo" {
name = "tf_test_foo"
cidr_block = "172.16.0.0/12"
@ -1026,7 +1034,7 @@ resource "alicloud_vpc" "foo" {
resource "alicloud_vswitch" "foo" {
vpc_id = "${alicloud_vpc.foo.id}"
cidr_block = "172.16.0.0/24"
availability_zone = "cn-beijing-b"
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
}
resource "alicloud_security_group" "tf_test_foo" {
@ -1037,11 +1045,9 @@ resource "alicloud_security_group" "tf_test_foo" {
resource "alicloud_instance" "foo" {
# cn-beijing
availability_zone = "cn-beijing-b"
security_groups = ["${alicloud_security_group.tf_test_foo.id}"]
vswitch_id = "${alicloud_vswitch.foo.id}"
private_ip = "172.16.0.229"
allocate_public_ip = "true"
internet_max_bandwidth_out = 5
internet_charge_type = "PayByBandwidth"
@ -1055,6 +1061,11 @@ resource "alicloud_instance" "foo" {
}
`
const testAccVpcInstanceWithSecurityRule = `
data "alicloud_zones" "default" {
"available_disk_category"= "cloud_efficiency"
"available_resource_creation"= "VSwitch"
}
resource "alicloud_vpc" "foo" {
name = "tf_test_foo"
cidr_block = "10.1.0.0/21"
@ -1063,7 +1074,7 @@ resource "alicloud_vpc" "foo" {
resource "alicloud_vswitch" "foo" {
vpc_id = "${alicloud_vpc.foo.id}"
cidr_block = "10.1.1.0/24"
availability_zone = "cn-beijing-c"
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
}
resource "alicloud_security_group" "tf_test_foo" {
@ -1085,7 +1096,6 @@ resource "alicloud_security_group_rule" "ingress" {
resource "alicloud_instance" "foo" {
# cn-beijing
availability_zone = "cn-beijing-c"
security_groups = ["${alicloud_security_group.tf_test_foo.id}"]
vswitch_id = "${alicloud_vswitch.foo.id}"

View File

@ -151,6 +151,10 @@ func testAccCheckNatGatewayDestroy(s *terraform.State) error {
}
const testAccNatGatewayConfig = `
data "alicloud_zones" "default" {
"available_resource_creation"= "VSwitch"
}
resource "alicloud_vpc" "foo" {
name = "tf_test_foo"
cidr_block = "172.16.0.0/12"
@ -159,7 +163,7 @@ resource "alicloud_vpc" "foo" {
resource "alicloud_vswitch" "foo" {
vpc_id = "${alicloud_vpc.foo.id}"
cidr_block = "172.16.0.0/21"
availability_zone = "cn-beijing-b"
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
}
resource "alicloud_nat_gateway" "foo" {
@ -169,11 +173,11 @@ resource "alicloud_nat_gateway" "foo" {
bandwidth_packages = [{
ip_count = 1
bandwidth = 5
zone = "cn-beijing-b"
zone = "${data.alicloud_zones.default.zones.0.id}"
}, {
ip_count = 2
bandwidth = 10
zone = "cn-beijing-b"
zone = "${data.alicloud_zones.default.zones.0.id}"
}]
depends_on = [
"alicloud_vswitch.foo"]
@ -181,6 +185,10 @@ resource "alicloud_nat_gateway" "foo" {
`
const testAccNatGatewayConfigSpec = `
data "alicloud_zones" "default" {
"available_resource_creation"= "VSwitch"
}
resource "alicloud_vpc" "foo" {
name = "tf_test_foo"
cidr_block = "172.16.0.0/12"
@ -189,7 +197,7 @@ resource "alicloud_vpc" "foo" {
resource "alicloud_vswitch" "foo" {
vpc_id = "${alicloud_vpc.foo.id}"
cidr_block = "172.16.0.0/21"
availability_zone = "cn-beijing-b"
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
}
resource "alicloud_nat_gateway" "foo" {
@ -199,11 +207,11 @@ resource "alicloud_nat_gateway" "foo" {
bandwidth_packages = [{
ip_count = 1
bandwidth = 5
zone = "cn-beijing-b"
zone = "${data.alicloud_zones.default.zones.0.id}"
}, {
ip_count = 2
bandwidth = 10
zone = "cn-beijing-b"
zone = "${data.alicloud_zones.default.zones.0.id}"
}]
depends_on = [
"alicloud_vswitch.foo"]
@ -211,6 +219,10 @@ resource "alicloud_nat_gateway" "foo" {
`
const testAccNatGatewayConfigSpecUpgrade = `
data "alicloud_zones" "default" {
"available_resource_creation"= "VSwitch"
}
resource "alicloud_vpc" "foo" {
name = "tf_test_foo"
cidr_block = "172.16.0.0/12"
@ -219,7 +231,7 @@ resource "alicloud_vpc" "foo" {
resource "alicloud_vswitch" "foo" {
vpc_id = "${alicloud_vpc.foo.id}"
cidr_block = "172.16.0.0/21"
availability_zone = "cn-beijing-b"
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
}
resource "alicloud_nat_gateway" "foo" {
@ -229,11 +241,11 @@ resource "alicloud_nat_gateway" "foo" {
bandwidth_packages = [{
ip_count = 1
bandwidth = 5
zone = "cn-beijing-b"
zone = "${data.alicloud_zones.default.zones.0.id}"
}, {
ip_count = 2
bandwidth = 10
zone = "cn-beijing-b"
zone = "${data.alicloud_zones.default.zones.0.id}"
}]
depends_on = [
"alicloud_vswitch.foo"]

View File

@ -34,6 +34,7 @@ func resourceAliyunSecurityGroupRule() *schema.Resource {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
ValidateFunc: validateSecurityRuleNicType,
},
@ -161,15 +162,28 @@ func resourceAliyunSecurityGroupRuleRead(d *schema.ResourceData, meta interface{
func resourceAliyunSecurityGroupRuleDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*AliyunClient)
args, err := buildAliyunSecurityIngressArgs(d, meta)
ruleType := d.Get("type").(string)
if GroupRuleDirection(ruleType) == GroupRuleIngress {
args, err := buildAliyunSecurityIngressArgs(d, meta)
if err != nil {
return err
}
revokeArgs := &ecs.RevokeSecurityGroupArgs{
AuthorizeSecurityGroupArgs: *args,
}
return client.RevokeSecurityGroup(revokeArgs)
}
args, err := buildAliyunSecurityEgressArgs(d, meta)
if err != nil {
return err
}
revokeArgs := &ecs.RevokeSecurityGroupArgs{
AuthorizeSecurityGroupArgs: *args,
revokeArgs := &ecs.RevokeSecurityGroupEgressArgs{
AuthorizeSecurityGroupEgressArgs: *args,
}
return client.RevokeSecurityGroup(revokeArgs)
return client.RevokeSecurityGroupEgress(revokeArgs)
}
func buildAliyunSecurityIngressArgs(d *schema.ResourceData, meta interface{}) (*ecs.AuthorizeSecurityGroupArgs, error) {

View File

@ -81,6 +81,39 @@ func TestAccAlicloudSecurityGroupRule_Egress(t *testing.T) {
}
func TestAccAlicloudSecurityGroupRule_EgressDefaultNicType(t *testing.T) {
var pt ecs.PermissionType
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
// module name
IDRefreshName: "alicloud_security_group_rule.egress",
Providers: testAccProviders,
CheckDestroy: testAccCheckSecurityGroupRuleDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccSecurityGroupRuleEgress_emptyNicType,
Check: resource.ComposeTestCheckFunc(
testAccCheckSecurityGroupRuleExists(
"alicloud_security_group_rule.egress", &pt),
resource.TestCheckResourceAttr(
"alicloud_security_group_rule.egress",
"port_range",
"80/80"),
resource.TestCheckResourceAttr(
"alicloud_security_group_rule.egress",
"nic_type",
"internet"),
),
},
},
})
}
func TestAccAlicloudSecurityGroupRule_Vpc_Ingress(t *testing.T) {
var pt ecs.PermissionType
@ -114,6 +147,43 @@ 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 testAccCheckSecurityGroupRuleExists(n string, m *ecs.PermissionType) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
@ -210,6 +280,23 @@ resource "alicloud_security_group_rule" "egress" {
`
const testAccSecurityGroupRuleEgress_emptyNicType = `
resource "alicloud_security_group" "foo" {
name = "sg_foo"
}
resource "alicloud_security_group_rule" "egress" {
type = "egress"
ip_protocol = "udp"
policy = "accept"
port_range = "80/80"
priority = 1
security_group_id = "${alicloud_security_group.foo.id}"
cidr_ip = "10.159.6.18/12"
}
`
const testAccSecurityGroupRuleVpcIngress = `
resource "alicloud_security_group" "foo" {
vpc_id = "${alicloud_vpc.vpc.id}"
@ -231,6 +318,22 @@ resource "alicloud_security_group_rule" "ingress" {
cidr_ip = "10.159.6.18/12"
}
`
const testAccSecurityGroupRule_missingSourceCidrIp = `
resource "alicloud_security_group" "foo" {
name = "sg_foo"
}
resource "alicloud_security_group_rule" "egress" {
security_group_id = "${alicloud_security_group.foo.id}"
type = "egress"
cidr_ip= "0.0.0.0/0"
policy = "accept"
ip_protocol= "udp"
port_range= "80/80"
priority= 1
}
`
const testAccSecurityGroupRuleMultiIngress = `

View File

@ -81,7 +81,6 @@ resource "alicloud_security_group" "foo" {
resource "alicloud_instance" "foo" {
# cn-beijing
availability_zone = "cn-beijing-b"
image_id = "ubuntu_140405_64_40G_cloudinit_20161115.vhd"
# series II

View File

@ -275,6 +275,10 @@ resource "alicloud_slb" "listener" {
`
const testAccSlb4Vpc = `
data "alicloud_zones" "default" {
"available_resource_creation"= "VSwitch"
}
resource "alicloud_vpc" "foo" {
name = "tf_test_foo"
cidr_block = "172.16.0.0/12"
@ -283,7 +287,7 @@ resource "alicloud_vpc" "foo" {
resource "alicloud_vswitch" "foo" {
vpc_id = "${alicloud_vpc.foo.id}"
cidr_block = "172.16.0.0/21"
availability_zone = "cn-beijing-b"
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
}
resource "alicloud_slb" "vpc" {

View File

@ -92,6 +92,10 @@ func testAccCheckVswitchDestroy(s *terraform.State) error {
}
const testAccVswitchConfig = `
data "alicloud_zones" "default" {
"available_resource_creation"= "VSwitch"
}
resource "alicloud_vpc" "foo" {
name = "tf_test_foo"
cidr_block = "172.16.0.0/12"
@ -100,6 +104,6 @@ resource "alicloud_vpc" "foo" {
resource "alicloud_vswitch" "foo" {
vpc_id = "${alicloud_vpc.foo.id}"
cidr_block = "172.16.0.0/21"
availability_zone = "cn-beijing-b"
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
}
`

View File

@ -187,14 +187,13 @@ func (client *AliyunClient) DescribeSecurity(securityGroupId string) (*ecs.Descr
}
func (client *AliyunClient) DescribeSecurityGroupRule(securityGroupId, types, ip_protocol, port_range string) (*ecs.PermissionType, error) {
sg, err := client.DescribeSecurity(securityGroupId)
if err != nil {
return nil, err
}
for _, p := range sg.Permissions.Permission {
if strings.ToLower(string(p.IpProtocol)) == ip_protocol && p.PortRange == port_range {
if strings.ToLower(string(p.IpProtocol)) == ip_protocol && p.PortRange == port_range && strings.ToLower(p.Direction) == types {
return &p, nil
}
}
@ -203,6 +202,11 @@ func (client *AliyunClient) DescribeSecurityGroupRule(securityGroupId, types, ip
}
func (client *AliyunClient) RevokeSecurityGroup(args *ecs.RevokeSecurityGroupArgs) error {
//todo: handle the specal err
//when the rule is not exist, api will return success(200)
return client.ecsconn.RevokeSecurityGroup(args)
}
func (client *AliyunClient) RevokeSecurityGroupEgress(args *ecs.RevokeSecurityGroupEgressArgs) error {
//when the rule is not exist, api will return success(200)
return client.ecsconn.RevokeSecurityGroupEgress(args)
}

View File

@ -0,0 +1,33 @@
### Configure NAT instance Example
In the Virtual Private CloudVPC 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

View File

@ -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
}

View File

@ -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}"
}

View File

@ -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}

View File

@ -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"
}

View File

@ -11,27 +11,38 @@ resource "alicloud_vswitch" "vsw" {
}
resource "alicloud_security_group" "sg" {
name = "tf-sg"
description = "sg"
vpc_id = "${alicloud_vpc.default.id}"
name = "tf-sg"
description = "sg"
vpc_id = "${alicloud_vpc.default.id}"
}
resource "alicloud_security_group_rule" "allow_ssh" {
security_group_id = "${alicloud_security_group.sg.id}"
type = "ingress"
cidr_ip= "0.0.0.0/0"
policy = "accept"
ip_protocol= "tcp"
port_range= "22/22"
priority= 1
}
resource "alicloud_instance" "website" {
# cn-beijing
availability_zone = "${var.zone}"
vswitch_id = "${alicloud_vswitch.vsw.id}"
image_id = "${var.image}"
# cn-beijing
availability_zone = "${var.zone}"
vswitch_id = "${alicloud_vswitch.vsw.id}"
image_id = "${var.image}"
# series II
instance_type = "${var.ecs_type}"
io_optimized = "optimized"
system_disk_category = "cloud_efficiency"
# series II
instance_type = "${var.ecs_type}"
io_optimized = "optimized"
system_disk_category = "cloud_efficiency"
internet_charge_type = "PayByTraffic"
internet_max_bandwidth_out = 5
allocate_public_ip = true
security_groups = ["${alicloud_security_group.sg.id}"]
instance_name = "test_foo"
internet_charge_type = "PayByTraffic"
internet_max_bandwidth_out = 5
allocate_public_ip = true
security_groups = ["${alicloud_security_group.sg.id}"]
instance_name = "tf_website"
password= "${var.password}"
user_data = "${file("userdata.sh")}"
user_data = "${file("userdata.sh")}"
}

View File

@ -1,7 +1,8 @@
output "hostname" {
value = "${alicloud_instance.website.instance_name}"
}
output "ecs_id" {
value = "${alicloud_instance.website.id}"
}
output "ecs_public_ip" {
value = "${alicloud_instance.website.public_ip}"
}

View File

@ -10,6 +10,10 @@ variable "zone" {
default = "cn-beijing-b"
}
variable "password" {
default = "Test123456"
}
variable "image" {
default = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
}

View File

@ -5,7 +5,7 @@ data "alicloud_instance_types" "1c2g" {
}
data "alicloud_zones" "default" {
"available_instance_type"= "${data.alicloud_instance_types.4c8g.instance_types.0.id}"
"available_instance_type"= "${data.alicloud_instance_types.1c2g.instance_types.0.id}"
"available_disk_category"= "${var.disk_category}"
}

View File

@ -5,7 +5,7 @@ resource "alicloud_security_group" "group" {
resource "alicloud_disk" "disk" {
availability_zone = "${var.availability_zones}"
availability_zone = "${alicloud_instance.instance.0.availability_zone}"
category = "${var.disk_category}"
size = "${var.disk_size}"
count = "${var.count}"
@ -17,7 +17,6 @@ resource "alicloud_instance" "instance" {
image_id = "${var.image_id}"
instance_type = "${var.ecs_type}"
count = "${var.count}"
availability_zone = "${var.availability_zones}"
security_groups = ["${alicloud_security_group.group.*.id}"]
internet_charge_type = "${var.internet_charge_type}"

View File

@ -23,9 +23,6 @@ variable "ecs_type" {
variable "ecs_password" {
default = "Test12345"
}
variable "availability_zones" {
default = "cn-beijing-b"
}
variable "allocate_public_ip" {
default = true
}
@ -41,7 +38,7 @@ variable "io_optimized" {
}
variable "disk_category" {
default = "cloud_ssd"
default = "cloud_efficiency"
}
variable "disk_size" {
default = "40"

View File

@ -128,7 +128,8 @@ func (client *Client) Invoke(action string, args interface{}, response interface
// Invoke sends the raw HTTP request for ECS services
//改进了一下上面那个方法可以使用各种Http方法
func (client *Client) InvokeByAnyMethod(method, action string, args interface{}, response interface{}) error {
//2017.1.30 增加了一个path参数用来拓展访问的地址
func (client *Client) InvokeByAnyMethod(method, action, path string, args interface{}, response interface{}) error {
request := Request{}
request.init(client.version, action, client.AccessKeyId)
@ -140,17 +141,18 @@ func (client *Client) InvokeByAnyMethod(method, action string, args interface{},
signature := util.CreateSignatureForRequest(method, &data, client.AccessKeySecret)
data.Add("Signature", signature)
// Generate the request URL
var (
httpReq *http.Request
err error
)
if method == http.MethodGet {
requestURL := client.endpoint + "?" + data.Encode()
requestURL := client.endpoint + path + "?" + data.Encode()
//fmt.Println(requestURL)
httpReq, err = http.NewRequest(method, requestURL, nil)
} else {
httpReq, err = http.NewRequest(method, client.endpoint, strings.NewReader(data.Encode()))
//fmt.Println(client.endpoint + path)
httpReq, err = http.NewRequest(method, client.endpoint + path, strings.NewReader(data.Encode()))
httpReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
}

View File

@ -112,6 +112,7 @@ func (client *Client) DescribeImages(args *DescribeImagesArgs) (images []ImageTy
type CreateImageArgs struct {
RegionId common.Region
SnapshotId string
InstanceId string
ImageName string
ImageVersion string
Description string

View File

@ -15,12 +15,14 @@ type InstanceStatus string
// Constants of InstanceStatus
const (
Creating = InstanceStatus("Creating")
Creating = InstanceStatus("Creating") // For backward compatability
Pending = InstanceStatus("Pending")
Running = InstanceStatus("Running")
Starting = InstanceStatus("Starting")
Stopped = InstanceStatus("Stopped")
Stopping = InstanceStatus("Stopping")
Deleted = InstanceStatus("Deleted")
)
type LockReason string
@ -279,6 +281,7 @@ type ModifyInstanceAttributeArgs struct {
Description string
Password string
HostName string
UserData string
}
type ModifyInstanceAttributeResponse struct {
@ -323,6 +326,37 @@ func (client *Client) WaitForInstance(instanceId string, status InstanceStatus,
return nil
}
// WaitForInstance waits for instance to given status
// when instance.NotFound wait until timeout
func (client *Client) WaitForInstanceAsyn(instanceId string, status InstanceStatus, timeout int) error {
if timeout <= 0 {
timeout = InstanceDefaultTimeout
}
for {
instance, err := client.DescribeInstanceAttribute(instanceId)
if err != nil {
e, _ := err.(*common.Error)
if e.ErrorResponse.Code != "InvalidInstanceId.NotFound" {
return err
}
continue
}
if instance.Status == status {
//TODO
//Sleep one more time for timing issues
time.Sleep(DefaultWaitForInterval * time.Second)
break
}
timeout = timeout - DefaultWaitForInterval
if timeout <= 0 {
return common.GetClientErrorFromString("Timeout")
}
time.Sleep(DefaultWaitForInterval * time.Second)
}
return nil
}
type DescribeInstanceVncUrlArgs struct {
RegionId common.Region
InstanceId string
@ -510,6 +544,43 @@ func (client *Client) CreateInstance(args *CreateInstanceArgs) (instanceId strin
return response.InstanceId, err
}
type RunInstanceArgs struct {
CreateInstanceArgs
MinAmount int
MaxAmount int
AutoReleaseTime string
NetworkType string
InnerIpAddress string
BusinessInfo string
}
type RunInstanceResponse struct {
common.Response
InstanceIdSets InstanceIdSets
}
type InstanceIdSets struct {
InstanceIdSet []string
}
type BusinessInfo struct {
Pack string `json:"pack,omitempty" yaml:"pack,omitempty"`
ActivityId string `json:"activityId,omitempty" yaml:"activityId,omitempty"`
}
func (client *Client) RunInstances(args *RunInstanceArgs) (instanceIdSet []string, err error) {
if args.UserData != "" {
// Encode to base64 string
args.UserData = base64.StdEncoding.EncodeToString([]byte(args.UserData))
}
response := RunInstanceResponse{}
err = client.Invoke("RunInstances", args, &response)
if err != nil {
return nil, err
}
return response.InstanceIdSets.InstanceIdSet, err
}
type SecurityGroupArgs struct {
InstanceId string
SecurityGroupId string

126
vendor/github.com/denverdino/aliyungo/slb/rules.go generated vendored Normal file
View File

@ -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
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
}

22
vendor/vendor.json vendored
View File

@ -1292,28 +1292,28 @@
"revisionTime": "2016-10-29T20:57:26Z"
},
{
"checksumSHA1": "ADySw3nBHyzEHB6afBSeVRN2A4g=",
"checksumSHA1": "e6yzSIwLwJV0tb2YQupLL0FO1BM=",
"path": "github.com/denverdino/aliyungo/common",
"revision": "d123f5d1fa71b211b70b2e9b56a62da21076884a",
"revisionTime": "2017-01-17T10:57:15Z"
"revision": "c0ff6df91f593ae8b30f749cc949b4588d8c96c9",
"revisionTime": "2017-02-23T12:23:33Z"
},
{
"checksumSHA1": "9ZY3RlumKp5DAMfL08YwMoOOT2o=",
"checksumSHA1": "YLooG/WAFF61eBUxg/R5cpfi5DE=",
"path": "github.com/denverdino/aliyungo/ecs",
"revision": "d123f5d1fa71b211b70b2e9b56a62da21076884a",
"revisionTime": "2017-01-17T10:57:15Z"
"revision": "c0ff6df91f593ae8b30f749cc949b4588d8c96c9",
"revisionTime": "2017-02-23T12:23:33Z"
},
{
"checksumSHA1": "QlA7zv05k7HWeR3tg4uHqIlFcg8=",
"checksumSHA1": "mF2UQ4+NJrPUZkm1RNa9Kxr2U0s=",
"path": "github.com/denverdino/aliyungo/slb",
"revision": "d123f5d1fa71b211b70b2e9b56a62da21076884a",
"revisionTime": "2017-01-17T10:57:15Z"
"revision": "c0ff6df91f593ae8b30f749cc949b4588d8c96c9",
"revisionTime": "2017-02-23T12:23:33Z"
},
{
"checksumSHA1": "Lp0KtT7ycgq31ox3Uzhpxyw0U+Y=",
"path": "github.com/denverdino/aliyungo/util",
"revision": "d123f5d1fa71b211b70b2e9b56a62da21076884a",
"revisionTime": "2017-01-17T10:57:15Z"
"revision": "c0ff6df91f593ae8b30f749cc949b4588d8c96c9",
"revisionTime": "2017-02-23T12:23:33Z"
},
{
"checksumSHA1": "yDQQpeUxwqB3C+4opweg6znWJQk=",

View File

@ -15,38 +15,38 @@ Provides a ECS instance resource.
```
# Create a new ECS instance for classic
resource "alicloud_security_group" "classic" {
name = "tf_test_foo"
description = "foo"
name = "tf_test_foo"
description = "foo"
}
resource "alicloud_instance" "classic" {
# cn-beijing
availability_zone = "cn-beijing-b"
security_group_id = "${alicloud_security_group.classic.id}"
# cn-beijing
availability_zone = "cn-beijing-b"
security_group_id = "${alicloud_security_group.classic.id}"
allocate_public_ip = "true"
allocate_public_ip = "true"
# series II
instance_type = "ecs.n1.medium"
io_optimized = "optimized"
system_disk_category = "cloud_efficiency"
image_id = "ubuntu_140405_64_40G_cloudinit_20161115.vhd"
instance_name = "test_foo"
# series II
instance_type = "ecs.n1.medium"
io_optimized = "optimized"
system_disk_category = "cloud_efficiency"
image_id = "ubuntu_140405_64_40G_cloudinit_20161115.vhd"
instance_name = "test_foo"
}
# Create a new ECS instance for VPC
resource "alicloud_vpc" "default" {
# Other parameters...
# Other parameters...
}
resource "alicloud_vswitch" "default" {
# Other parameters...
# Other parameters...
}
resource "alicloud_slb" "vpc" {
name = "test-slb-tf"
vpc_id = "${alicloud_vpc.default.id}"
vswitch_id = "${alicloud_vswitch.default.id}"
name = "test-slb-tf"
vpc_id = "${alicloud_vpc.default.id}"
vswitch_id = "${alicloud_vswitch.default.id}"
}
```
@ -54,22 +54,20 @@ resource "alicloud_slb" "vpc" {
The following arguments are supported:
* `availability_zone` - (Required) The Zone to start the instance in.
* `image_id` - (Required) The Image to use for the instance.
* `instance_type` - (Required) The type of instance to start.
* `security_group_ids` - (Required) A list of security group ids to associate with. If you are creating Instances in a VPC, use `vpc_security_group_ids` instead.
`security_group_ids` instead.
* `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`.
* `io_optimized` - (Required) Valid values are `none`, `optimized`, If `optimized`, the launched ECS instance will be I/O optimized.
* `security_group_ids` - (Optional) A list of security group ids to associate with.
* `availability_zone` - (Optional) The Zone to start the instance in.
* `instance_name` - (Optional) The name of the ECS. This instance_name can have a string of 2 to 128 characters, must contain only alphanumeric characters or hyphens, such as "-",".","_", and must not begin or end with a hyphen, and must not begin with http:// or https://. If not specified,
Terraform will autogenerate a default name is `ECS-Instance`.
* `allocate_public_ip` - (Optional) Associate a public ip address with an instance in a VPC or Classic. Boolean value, Default is false.
* `io_optimized` - (Optional) Valid
values are `none`, `optimized`, If `optimized`, the launched ECS instance will be I/O optimized. Default is `optimized`.
* `system_disk_category` - (Optional) Valid values are `cloud`, `cloud_efficiency`, `cloud_ssd`, For I/O optimized instance type, `cloud_ssd` and `cloud_efficiency` disks are supported. For non I/O Optimized instance type, `cloud` disk are supported.
* `system_disk_category` - (Optional) Valid values are `cloud`, `cloud_efficiency`, `cloud_ssd`, For I/O optimized instance type, `cloud_ssd` and `cloud_efficiency` disks are supported. For non I/O Optimized instance type, `cloud` disk are supported.
* `system_disk_size` - (Optional) Size of the system disk, value range: 40GB ~ 500GB. Default is 40GB.
* `description` - (Optional) Description of the instance, This description can have a string of 2 to 256 characters, It cannot begin with http:// or https://. Default value is null.
* `internet_charge_type` - (Optional) Internet charge type of the instance, Valid values are `PayByBandwidth`, `PayByTraffic`. Default is `PayByBandwidth`.
* `internet_max_bandwidth_in` - (Optional) Maximum incoming bandwidth from the public network, measured in Mbps (Mega bit per second). Value range: [1, 200]. If this value is not specified, then automatically sets it to 200 Mbps.
* `internet_max_bandwidth_out` - (Optional) Maximum outgoing bandwidth to the public network, measured in Mbps (Mega bit per second). Value range:
* `internet_max_bandwidth_out` - (Optional) Maximum outgoing bandwidth to the public network, measured in Mbps (Mega bit per second). Value range:
`internet_charge_type` is `PayByBandwidth`: this value range [0, 100], If this value is not specified, then automatically sets it to 0 Mbps; If `internet_charge_type` is `PayByTraffic`: this value range [1, 100]. this value must be set value, such as 5.
* `host_name` - (Optional) Host name of the ECS, which is a string of at least two characters. “hostname” cannot start or end with “.” or “-“. In addition, two or more consecutive “.” or “-“ symbols are not allowed. On Windows, the host name can contain a maximum of 15 characters, which can be a combination of uppercase/lowercase letters, numerals, and “-“. The host name cannot contain dots (“.”) or contain only numeric characters.
On other OSs such as Linux, the host name can contain a maximum of 30 characters, which can be segments separated by dots (“.”), where each segment can contain uppercase/lowercase letters, numerals, or “_“.
@ -77,7 +75,6 @@ On other OSs such as Linux, the host name can contain a maximum of 30 characters
* `vswitch_id` - (Optional) The virtual switch ID to launch in VPC. If you want to create instances in VPC network, this parameter must be set.
* `instance_charge_type` - (Optional) Valid values are `PrePaid`, `PostPaid`, The default is `PostPaid`.
* `period` - (Optional) The time that you have bought the resource, in month. Only valid when instance_charge_type is set as `PrePaid`. Value range [1, 12].
* `private_ip` - (Optional) Private IP address to associate with the instance in a VPC.
* `tags` - (Optional) A mapping of tags to assign to the resource.
## Attributes Reference