Merge pull request #15258 from hashicorp/jbardin/remove-providers

Remove providers from core
This commit is contained in:
James Bardin 2017-06-12 14:13:11 -04:00 committed by GitHub
commit be900e8085
6401 changed files with 25335 additions and 1943831 deletions

View File

@ -20,17 +20,6 @@ dev: fmtcheck generate
quickdev: generate quickdev: generate
@TF_DEV=1 sh -c "'$(CURDIR)/scripts/build.sh'" @TF_DEV=1 sh -c "'$(CURDIR)/scripts/build.sh'"
# Shorthand for quickly building the core of Terraform. Note that some
# changes will require a rebuild of everything, in which case the dev
# target should be used.
core-dev: generate
go install -tags 'core' github.com/hashicorp/terraform
# Shorthand for quickly testing the core of Terraform (i.e. "not providers")
core-test: generate
@echo "Testing core packages..." && \
go test -tags 'core' $(TESTARGS) $(shell go list ./... | grep -v -E 'terraform/(builtin|vendor)')
# Shorthand for building and installing just one plugin for local testing. # Shorthand for building and installing just one plugin for local testing.
# Run as (for example): make plugin-dev PLUGIN=provider-aws # Run as (for example): make plugin-dev PLUGIN=provider-aws
plugin-dev: generate plugin-dev: generate
@ -38,7 +27,7 @@ plugin-dev: generate
mv $(GOPATH)/bin/$(PLUGIN) $(GOPATH)/bin/terraform-$(PLUGIN) mv $(GOPATH)/bin/$(PLUGIN) $(GOPATH)/bin/terraform-$(PLUGIN)
# test runs the unit tests # test runs the unit tests
test: fmtcheck errcheck generate test: fmtcheck generate
go test -i $(TEST) || exit 1 go test -i $(TEST) || exit 1
echo $(TEST) | \ echo $(TEST) | \
xargs -t -n4 go test $(TESTARGS) -timeout=60s -parallel=4 xargs -t -n4 go test $(TESTARGS) -timeout=60s -parallel=4
@ -98,9 +87,6 @@ fmt:
fmtcheck: fmtcheck:
@sh -c "'$(CURDIR)/scripts/gofmtcheck.sh'" @sh -c "'$(CURDIR)/scripts/gofmtcheck.sh'"
errcheck:
@sh -c "'$(CURDIR)/scripts/errcheck.sh'"
vendor-status: vendor-status:
@govendor status @govendor status
@ -109,4 +95,4 @@ vendor-status:
# under parallel conditions. # under parallel conditions.
.NOTPARALLEL: .NOTPARALLEL:
.PHONY: bin core-dev core-test cover default dev errcheck fmt fmtcheck generate plugin-dev quickdev test-compile test testacc testrace tools vendor-status vet .PHONY: bin cover default dev fmt fmtcheck generate plugin-dev quickdev test-compile test testacc testrace tools vendor-status vet

View File

@ -8,7 +8,7 @@ import (
"github.com/hashicorp/terraform/backend" "github.com/hashicorp/terraform/backend"
"github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/schema"
terraformAWS "github.com/hashicorp/terraform/builtin/providers/aws" terraformAWS "github.com/terraform-providers/terraform-provider-aws/aws"
) )
// New creates a new backend for S3 remote state. // New creates a new backend for S3 remote state.

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/archive"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: archive.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/arukas"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: arukas.Provider,
})
}

View File

@ -1 +0,0 @@
package main

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/atlas"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: atlas.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/aws"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: aws.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/azure"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: azure.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/azurerm"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: azurerm.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/bitbucket"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: bitbucket.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/chef"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: chef.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/clc"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: clc.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/cloudflare"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: cloudflare.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/cloudstack"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: cloudstack.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/cobbler"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: cobbler.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/consul"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: consul.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/datadog"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: datadog.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/digitalocean"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: digitalocean.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/dme"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: dme.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/dns"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: dns.Provider,
})
}

View File

@ -1 +0,0 @@
package main

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/dnsimple"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: dnsimple.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/docker"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: docker.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/dyn"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: dyn.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/external"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: external.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/fastly"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: fastly.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/github"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: github.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/gitlab"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: gitlab.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/google"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: google.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/grafana"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: grafana.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/heroku"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: heroku.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/ignition"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: ignition.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/influxdb"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: influxdb.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/kubernetes"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: kubernetes.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/librato"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: librato.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/local"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: local.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/logentries"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: logentries.Provider,
})
}

View File

@ -1 +0,0 @@
package main

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/mailgun"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: mailgun.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/mysql"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: mysql.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/ns1"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: ns1.Provider,
})
}

View File

@ -1 +0,0 @@
package main

View File

@ -1,15 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/null"
"github.com/hashicorp/terraform/plugin"
"github.com/hashicorp/terraform/terraform"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: func() terraform.ResourceProvider {
return null.Provider()
},
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/openstack"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: openstack.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/opsgenie"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: opsgenie.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/ovh"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: ovh.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/packet"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: packet.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/pagerduty"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: pagerduty.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/postgresql"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: postgresql.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/powerdns"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: powerdns.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/profitbricks"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: profitbricks.Provider,
})
}

View File

@ -1,15 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/rancher"
"github.com/hashicorp/terraform/plugin"
"github.com/hashicorp/terraform/terraform"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: func() terraform.ResourceProvider {
return rancher.Provider()
},
})
}

View File

@ -1,15 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/random"
"github.com/hashicorp/terraform/plugin"
"github.com/hashicorp/terraform/terraform"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: func() terraform.ResourceProvider {
return random.Provider()
},
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/rundeck"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: rundeck.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/scaleway"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: scaleway.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/softlayer"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: softlayer.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/spotinst"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: spotinst.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/statuscake"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: statuscake.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/template"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: template.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/terraform"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: terraform.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/tls"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: tls.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/triton"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: triton.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/ultradns"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: ultradns.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/vault"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: vault.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/vcd"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: vcd.Provider,
})
}

View File

@ -1,12 +0,0 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/vsphere"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: vsphere.Provider,
})
}

1
builtin/providers/README Normal file
View File

@ -0,0 +1 @@
providers moved to github.com/terraform-providers

View File

@ -1,93 +0,0 @@
package alicloud
import (
"github.com/denverdino/aliyungo/common"
"github.com/denverdino/aliyungo/ecs"
"github.com/hashicorp/terraform/helper/schema"
)
type InstanceNetWork string
const (
ClassicNet = InstanceNetWork("classic")
VpcNet = InstanceNetWork("vpc")
)
// timeout for common product, ecs e.g.
const defaultTimeout = 120
// timeout for long time progerss product, rds e.g.
const defaultLongTimeout = 1000
func getRegion(d *schema.ResourceData, meta interface{}) common.Region {
return meta.(*AliyunClient).Region
}
func notFoundError(err error) bool {
if e, ok := err.(*common.Error); ok &&
(e.StatusCode == 404 || e.ErrorResponse.Message == "Not found" || e.Code == InstanceNotfound) {
return true
}
return false
}
// Protocol represents network protocol
type Protocol string
// Constants of protocol definition
const (
Http = Protocol("http")
Https = Protocol("https")
Tcp = Protocol("tcp")
Udp = Protocol("udp")
)
// ValidProtocols network protocol list
var ValidProtocols = []Protocol{Http, Https, Tcp, Udp}
// simple array value check method, support string type only
func isProtocolValid(value string) bool {
res := false
for _, v := range ValidProtocols {
if string(v) == value {
res = true
}
}
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 COLON_SEPARATED = ":"
const LOCAL_HOST_IP = "127.0.0.1"
// Takes the result of flatmap.Expand for an array of strings
// and returns a []string
func expandStringList(configured []interface{}) []string {
vs := make([]string, 0, len(configured))
for _, v := range configured {
vs = append(vs, v.(string))
}
return vs
}

View File

@ -1,138 +0,0 @@
package alicloud
import (
"fmt"
"github.com/denverdino/aliyungo/common"
"github.com/denverdino/aliyungo/ecs"
"github.com/denverdino/aliyungo/ess"
"github.com/denverdino/aliyungo/rds"
"github.com/denverdino/aliyungo/slb"
)
// Config of aliyun
type Config struct {
AccessKey string
SecretKey string
Region common.Region
}
// AliyunClient of aliyun
type AliyunClient struct {
Region common.Region
ecsconn *ecs.Client
essconn *ess.Client
rdsconn *rds.Client
// use new version
ecsNewconn *ecs.Client
vpcconn *ecs.Client
slbconn *slb.Client
}
// Client for AliyunClient
func (c *Config) Client() (*AliyunClient, error) {
err := c.loadAndValidate()
if err != nil {
return nil, err
}
ecsconn, err := c.ecsConn()
if err != nil {
return nil, err
}
ecsNewconn, err := c.ecsConn()
if err != nil {
return nil, err
}
ecsNewconn.SetVersion(EcsApiVersion20160314)
rdsconn, err := c.rdsConn()
if err != nil {
return nil, err
}
slbconn, err := c.slbConn()
if err != nil {
return nil, err
}
vpcconn, err := c.vpcConn()
if err != nil {
return nil, err
}
essconn, err := c.essConn()
if err != nil {
return nil, err
}
return &AliyunClient{
Region: c.Region,
ecsconn: ecsconn,
ecsNewconn: ecsNewconn,
vpcconn: vpcconn,
slbconn: slbconn,
rdsconn: rdsconn,
essconn: essconn,
}, nil
}
const BusinessInfoKey = "Terraform"
func (c *Config) loadAndValidate() error {
err := c.validateRegion()
if err != nil {
return err
}
return nil
}
func (c *Config) validateRegion() error {
for _, valid := range common.ValidRegions {
if c.Region == valid {
return nil
}
}
return fmt.Errorf("Not a valid region: %s", c.Region)
}
func (c *Config) ecsConn() (*ecs.Client, error) {
client := ecs.NewECSClient(c.AccessKey, c.SecretKey, c.Region)
client.SetBusinessInfo(BusinessInfoKey)
_, err := client.DescribeRegions()
if err != nil {
return nil, err
}
return client, nil
}
func (c *Config) rdsConn() (*rds.Client, error) {
client := rds.NewRDSClient(c.AccessKey, c.SecretKey, c.Region)
client.SetBusinessInfo(BusinessInfoKey)
return client, nil
}
func (c *Config) slbConn() (*slb.Client, error) {
client := slb.NewSLBClient(c.AccessKey, c.SecretKey, c.Region)
client.SetBusinessInfo(BusinessInfoKey)
return client, nil
}
func (c *Config) vpcConn() (*ecs.Client, error) {
client := ecs.NewVPCClient(c.AccessKey, c.SecretKey, c.Region)
client.SetBusinessInfo(BusinessInfoKey)
return client, nil
}
func (c *Config) essConn() (*ess.Client, error) {
client := ess.NewESSClient(c.AccessKey, c.SecretKey, c.Region)
client.SetBusinessInfo(BusinessInfoKey)
return client, nil
}

View File

@ -1,18 +0,0 @@
package alicloud
import (
"bytes"
"fmt"
"github.com/hashicorp/terraform/helper/hashcode"
)
// Generates a hash for the set hash function used by the ID
func dataResourceIdHash(ids []string) string {
var buf bytes.Buffer
for _, id := range ids {
buf.WriteString(fmt.Sprintf("%s-", id))
}
return fmt.Sprintf("%d", hashcode.String(buf.String()))
}

View File

@ -1,337 +0,0 @@
package alicloud
import (
"fmt"
"log"
"regexp"
"sort"
"time"
"github.com/denverdino/aliyungo/ecs"
"github.com/hashicorp/terraform/helper/schema"
)
func dataSourceAlicloudImages() *schema.Resource {
return &schema.Resource{
Read: dataSourceAlicloudImagesRead,
Schema: map[string]*schema.Schema{
"name_regex": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ValidateFunc: validateNameRegex,
},
"most_recent": {
Type: schema.TypeBool,
Optional: true,
Default: false,
ForceNew: true,
},
"owners": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ValidateFunc: validateImageOwners,
},
// Computed values.
"images": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Computed: true,
},
"image_id": {
Type: schema.TypeString,
Computed: true,
},
"architecture": {
Type: schema.TypeString,
Computed: true,
},
"creation_time": {
Type: schema.TypeString,
Computed: true,
},
"description": {
Type: schema.TypeString,
Computed: true,
},
"image_owner_alias": {
Type: schema.TypeString,
Computed: true,
},
"os_type": {
Type: schema.TypeString,
Computed: true,
},
"os_name": {
Type: schema.TypeString,
Computed: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
"platform": {
Type: schema.TypeString,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"state": {
Type: schema.TypeString,
Computed: true,
},
"size": {
Type: schema.TypeInt,
Computed: true,
},
// Complex computed values
"disk_device_mappings": {
Type: schema.TypeList,
Computed: true,
//Set: imageDiskDeviceMappingHash,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"device": {
Type: schema.TypeString,
Computed: true,
},
"size": {
Type: schema.TypeString,
Computed: true,
},
"snapshot_id": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"product_code": {
Type: schema.TypeString,
Computed: true,
},
"is_self_shared": {
Type: schema.TypeString,
Computed: true,
},
"is_subscribed": {
Type: schema.TypeBool,
Computed: true,
},
"is_copied": {
Type: schema.TypeBool,
Computed: true,
},
"is_support_io_optimized": {
Type: schema.TypeBool,
Computed: true,
},
"image_version": {
Type: schema.TypeString,
Computed: true,
},
"progress": {
Type: schema.TypeString,
Computed: true,
},
"usage": {
Type: schema.TypeString,
Computed: true,
},
"tags": tagsSchema(),
},
},
},
},
}
}
// dataSourceAlicloudImagesDescriptionRead performs the Alicloud Image lookup.
func dataSourceAlicloudImagesRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AliyunClient).ecsconn
nameRegex, nameRegexOk := d.GetOk("name_regex")
owners, ownersOk := d.GetOk("owners")
mostRecent, mostRecentOk := d.GetOk("most_recent")
if nameRegexOk == false && ownersOk == false && mostRecentOk == false {
return fmt.Errorf("One of name_regex, owners or most_recent must be assigned")
}
params := &ecs.DescribeImagesArgs{
RegionId: getRegion(d, meta),
}
if ownersOk {
params.ImageOwnerAlias = ecs.ImageOwnerAlias(owners.(string))
}
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 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.
if image.ImageName == "" {
log.Printf("[WARN] Unable to find Image name to match against "+
"for image ID %q, nothing to do.",
image.ImageId)
continue
}
if r.MatchString(image.ImageName) {
filteredImages = append(filteredImages, image)
}
}
} else {
filteredImages = allImages[:]
}
var images []ecs.ImageType
if len(filteredImages) < 1 {
return fmt.Errorf("Your query returned no results. Please change your search criteria and try again.")
}
log.Printf("[DEBUG] alicloud_image - multiple results found and `most_recent` is set to: %t", mostRecent.(bool))
if len(filteredImages) > 1 && mostRecent.(bool) {
// Query returned single result.
images = append(images, mostRecentImage(filteredImages))
} else {
images = filteredImages
}
log.Printf("[DEBUG] alicloud_image - Images found: %#v", images)
return imagesDescriptionAttributes(d, images, meta)
}
// populate the numerous fields that the image description returns.
func imagesDescriptionAttributes(d *schema.ResourceData, images []ecs.ImageType, meta interface{}) error {
var ids []string
var s []map[string]interface{}
for _, image := range images {
mapping := map[string]interface{}{
"id": image.ImageId,
"architecture": image.Architecture,
"creation_time": image.CreationTime.String(),
"description": image.Description,
"image_id": image.ImageId,
"image_owner_alias": image.ImageOwnerAlias,
"os_name": image.OSName,
"os_type": image.OSType,
"name": image.ImageName,
"platform": image.Platform,
"status": image.Status,
"state": image.Status,
"size": image.Size,
"is_self_shared": image.IsSelfShared,
"is_subscribed": image.IsSubscribed,
"is_copied": image.IsCopied,
"is_support_io_optimized": image.IsSupportIoOptimized,
"image_version": image.ImageVersion,
"progress": image.Progress,
"usage": image.Usage,
"product_code": image.ProductCode,
// Complex types get their own functions
"disk_device_mappings": imageDiskDeviceMappings(image.DiskDeviceMappings.DiskDeviceMapping),
"tags": imageTagsMappings(d, image.ImageId, meta),
}
log.Printf("[DEBUG] alicloud_image - adding image mapping: %v", mapping)
ids = append(ids, image.ImageId)
s = append(s, mapping)
}
d.SetId(dataResourceIdHash(ids))
if err := d.Set("images", s); err != nil {
return err
}
return nil
}
//Find most recent image
type imageSort []ecs.ImageType
func (a imageSort) Len() int {
return len(a)
}
func (a imageSort) Swap(i, j int) {
a[i], a[j] = a[j], a[i]
}
func (a imageSort) Less(i, j int) bool {
itime, _ := time.Parse(time.RFC3339, a[i].CreationTime.String())
jtime, _ := time.Parse(time.RFC3339, a[j].CreationTime.String())
return itime.Unix() < jtime.Unix()
}
// Returns the most recent Image out of a slice of images.
func mostRecentImage(images []ecs.ImageType) ecs.ImageType {
sortedImages := images
sort.Sort(imageSort(sortedImages))
return sortedImages[len(sortedImages)-1]
}
// Returns a set of disk device mappings.
func imageDiskDeviceMappings(m []ecs.DiskDeviceMapping) []map[string]interface{} {
var s []map[string]interface{}
for _, v := range m {
mapping := map[string]interface{}{
"device": v.Device,
"size": v.Size,
"snapshot_id": v.SnapshotId,
}
log.Printf("[DEBUG] alicloud_image - adding disk device mapping: %v", mapping)
s = append(s, mapping)
}
return s
}
//Returns a mapping of image tags
func imageTagsMappings(d *schema.ResourceData, imageId string, meta interface{}) map[string]string {
client := meta.(*AliyunClient)
conn := client.ecsconn
tags, _, err := conn.DescribeTags(&ecs.DescribeTagsArgs{
RegionId: getRegion(d, meta),
ResourceType: ecs.TagResourceImage,
ResourceId: imageId,
})
if err != nil {
log.Printf("[ERROR] DescribeTags for image got error: %#v", err)
return nil
}
log.Printf("[DEBUG] DescribeTags for image : %v", tags)
return tagsToMap(tags)
}

View File

@ -1,155 +0,0 @@
package alicloud
import (
"regexp"
"testing"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccAlicloudImagesDataSource_images(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckAlicloudImagesDataSourceImagesConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAlicloudDataSourceID("data.alicloud_images.multi_image"),
resource.TestCheckResourceAttr("data.alicloud_images.multi_image", "images.#", "2"),
resource.TestCheckResourceAttr("data.alicloud_images.multi_image", "images.0.architecture", "x86_64"),
resource.TestCheckResourceAttr("data.alicloud_images.multi_image", "images.0.disk_device_mappings.#", "0"),
resource.TestMatchResourceAttr("data.alicloud_images.multi_image", "images.0.creation_time", regexp.MustCompile("^20[0-9]{2}-")),
resource.TestMatchResourceAttr("data.alicloud_images.multi_image", "images.0.image_id", regexp.MustCompile("^centos_6\\w{1,5}[64]{1}.")),
resource.TestCheckResourceAttr("data.alicloud_images.multi_image", "images.0.image_owner_alias", "system"),
resource.TestCheckResourceAttr("data.alicloud_images.multi_image", "images.0.os_type", "linux"),
resource.TestMatchResourceAttr("data.alicloud_images.multi_image", "images.0.name", regexp.MustCompile("^centos_6[a-zA-Z0-9_]{1,5}[64]{1}.")),
resource.TestCheckResourceAttr("data.alicloud_images.multi_image", "images.0.progress", "100%"),
resource.TestCheckResourceAttr("data.alicloud_images.multi_image", "images.0.state", "Available"),
resource.TestCheckResourceAttr("data.alicloud_images.multi_image", "images.0.status", "Available"),
resource.TestCheckResourceAttr("data.alicloud_images.multi_image", "images.0.usage", "instance"),
resource.TestCheckResourceAttr("data.alicloud_images.multi_image", "images.0.tags.%", "0"),
resource.TestCheckResourceAttr("data.alicloud_images.multi_image", "images.1.architecture", "i386"),
resource.TestCheckResourceAttr("data.alicloud_images.multi_image", "images.1.disk_device_mappings.#", "0"),
resource.TestMatchResourceAttr("data.alicloud_images.multi_image", "images.1.creation_time", regexp.MustCompile("^20[0-9]{2}-")),
resource.TestMatchResourceAttr("data.alicloud_images.multi_image", "images.1.image_id", regexp.MustCompile("^centos_6[a-zA-Z0-9_]{1,5}[32]{1}.")),
resource.TestCheckResourceAttr("data.alicloud_images.multi_image", "images.1.image_owner_alias", "system"),
resource.TestCheckResourceAttr("data.alicloud_images.multi_image", "images.1.os_type", "linux"),
resource.TestMatchResourceAttr("data.alicloud_images.multi_image", "images.1.name", regexp.MustCompile("^centos_6\\w{1,5}[32]{1}.")),
resource.TestCheckResourceAttr("data.alicloud_images.multi_image", "images.1.progress", "100%"),
resource.TestCheckResourceAttr("data.alicloud_images.multi_image", "images.1.state", "Available"),
resource.TestCheckResourceAttr("data.alicloud_images.multi_image", "images.1.status", "Available"),
resource.TestCheckResourceAttr("data.alicloud_images.multi_image", "images.1.usage", "instance"),
resource.TestCheckResourceAttr("data.alicloud_images.multi_image", "images.1.tags.%", "0"),
),
},
},
})
}
func TestAccAlicloudImagesDataSource_owners(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckAlicloudImagesDataSourceOwnersConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAlicloudDataSourceID("data.alicloud_images.owners_filtered_image"),
),
},
},
})
}
func TestAccAlicloudImagesDataSource_ownersEmpty(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckAlicloudImagesDataSourceEmptyOwnersConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAlicloudDataSourceID("data.alicloud_images.empty_owners_filtered_image"),
resource.TestCheckResourceAttr("data.alicloud_images.empty_owners_filtered_image", "most_recent", "true"),
),
},
},
})
}
func TestAccAlicloudImagesDataSource_nameRegexFilter(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckAlicloudImagesDataSourceNameRegexConfig,
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("^centos_")),
),
},
},
})
}
func TestAccAlicloudImagesDataSource_imageNotInFirstPage(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckAlicloudImagesDataSourceImageNotInFirstPageConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAlicloudDataSourceID("data.alicloud_images.name_regex_filtered_image"),
resource.TestMatchResourceAttr("data.alicloud_images.name_regex_filtered_image", "images.0.image_id", regexp.MustCompile("^ubuntu_14")),
),
},
},
})
}
// Instance store test - using centos images
const testAccCheckAlicloudImagesDataSourceImagesConfig = `
data "alicloud_images" "multi_image" {
owners = "system"
name_regex = "^centos_6"
}
`
// Testing owner parameter
const testAccCheckAlicloudImagesDataSourceOwnersConfig = `
data "alicloud_images" "owners_filtered_image" {
most_recent = true
owners = "system"
}
`
const testAccCheckAlicloudImagesDataSourceEmptyOwnersConfig = `
data "alicloud_images" "empty_owners_filtered_image" {
most_recent = true
owners = ""
}
`
// Testing name_regex parameter
const testAccCheckAlicloudImagesDataSourceNameRegexConfig = `
data "alicloud_images" "name_regex_filtered_image" {
most_recent = true
owners = "system"
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"
}
`

View File

@ -1,127 +0,0 @@
package alicloud
import (
"fmt"
"github.com/denverdino/aliyungo/ecs"
"github.com/hashicorp/terraform/helper/schema"
"log"
)
func dataSourceAlicloudInstanceTypes() *schema.Resource {
return &schema.Resource{
Read: dataSourceAlicloudInstanceTypesRead,
Schema: map[string]*schema.Schema{
"instance_type_family": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"cpu_core_count": {
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
"memory_size": {
Type: schema.TypeFloat,
Optional: true,
ForceNew: true,
},
// Computed values.
"instance_types": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Computed: true,
},
"cpu_core_count": {
Type: schema.TypeInt,
Computed: true,
},
"memory_size": {
Type: schema.TypeFloat,
Computed: true,
},
"family": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
},
}
}
func dataSourceAlicloudInstanceTypesRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AliyunClient).ecsconn
cpu, _ := d.Get("cpu_core_count").(int)
mem, _ := d.Get("memory_size").(float64)
args, err := buildAliyunAlicloudInstanceTypesArgs(d, meta)
if err != nil {
return err
}
resp, err := conn.DescribeInstanceTypesNew(args)
if err != nil {
return err
}
var instanceTypes []ecs.InstanceTypeItemType
for _, types := range resp {
if cpu > 0 && types.CpuCoreCount != cpu {
continue
}
if mem > 0 && types.MemorySize != mem {
continue
}
instanceTypes = append(instanceTypes, types)
}
if len(instanceTypes) < 1 {
return fmt.Errorf("Your query returned no results. Please change your search criteria and try again.")
}
log.Printf("[DEBUG] alicloud_instance_type - Types found: %#v", instanceTypes)
return instanceTypesDescriptionAttributes(d, instanceTypes)
}
func instanceTypesDescriptionAttributes(d *schema.ResourceData, types []ecs.InstanceTypeItemType) error {
var ids []string
var s []map[string]interface{}
for _, t := range types {
mapping := map[string]interface{}{
"id": t.InstanceTypeId,
"cpu_core_count": t.CpuCoreCount,
"memory_size": t.MemorySize,
"family": t.InstanceTypeFamily,
}
log.Printf("[DEBUG] alicloud_instance_type - adding type mapping: %v", mapping)
ids = append(ids, t.InstanceTypeId)
s = append(s, mapping)
}
d.SetId(dataResourceIdHash(ids))
if err := d.Set("instance_types", s); err != nil {
return err
}
return nil
}
func buildAliyunAlicloudInstanceTypesArgs(d *schema.ResourceData, meta interface{}) (*ecs.DescribeInstanceTypesArgs, error) {
args := &ecs.DescribeInstanceTypesArgs{}
if v := d.Get("instance_type_family").(string); v != "" {
args.InstanceTypeFamily = v
}
return args, nil
}

View File

@ -1,54 +0,0 @@
package alicloud
import (
"github.com/hashicorp/terraform/helper/resource"
"testing"
)
func TestAccAlicloudInstanceTypesDataSource_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckAlicloudInstanceTypesDataSourceBasicConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAlicloudDataSourceID("data.alicloud_instance_types.4c8g"),
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"),
),
},
resource.TestStep{
Config: testAccCheckAlicloudInstanceTypesDataSourceBasicConfigUpdate,
Check: resource.ComposeTestCheckFunc(
testAccCheckAlicloudDataSourceID("data.alicloud_instance_types.4c8g"),
resource.TestCheckResourceAttr("data.alicloud_instance_types.4c8g", "instance_types.#", "1"),
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"),
),
},
},
})
}
const testAccCheckAlicloudInstanceTypesDataSourceBasicConfig = `
data "alicloud_instance_types" "4c8g" {
cpu_core_count = 4
memory_size = 8
}
`
const testAccCheckAlicloudInstanceTypesDataSourceBasicConfigUpdate = `
data "alicloud_instance_types" "4c8g" {
instance_type_family= "ecs.s3"
cpu_core_count = 4
memory_size = 8
}
`

View File

@ -1,114 +0,0 @@
package alicloud
import (
"fmt"
"github.com/denverdino/aliyungo/common"
"github.com/denverdino/aliyungo/ecs"
"github.com/hashicorp/terraform/helper/schema"
"log"
)
func dataSourceAlicloudRegions() *schema.Resource {
return &schema.Resource{
Read: dataSourceAlicloudRegionsRead,
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"current": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
//Computed value
"regions": &schema.Schema{
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Computed: true,
},
"region_id": {
Type: schema.TypeString,
Computed: true,
},
"local_name": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
},
}
}
func dataSourceAlicloudRegionsRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AliyunClient).ecsconn
currentRegion := getRegion(d, meta)
resp, err := conn.DescribeRegions()
if err != nil {
return err
}
if resp == nil || len(resp) == 0 {
return fmt.Errorf("no matching regions found")
}
name, nameOk := d.GetOk("name")
current := d.Get("current").(bool)
var filterRegions []ecs.RegionType
for _, region := range resp {
if current {
if nameOk && common.Region(name.(string)) != currentRegion {
return fmt.Errorf("name doesn't match current region: %#v, please input again.", currentRegion)
}
if region.RegionId == currentRegion {
filterRegions = append(filterRegions, region)
break
}
continue
}
if nameOk {
if common.Region(name.(string)) == region.RegionId {
filterRegions = append(filterRegions, region)
break
}
continue
}
filterRegions = append(filterRegions, region)
}
if len(filterRegions) < 1 {
return fmt.Errorf("Your query region returned no results. Please change your search criteria and try again.")
}
return regionsDescriptionAttributes(d, filterRegions)
}
func regionsDescriptionAttributes(d *schema.ResourceData, regions []ecs.RegionType) error {
var ids []string
var s []map[string]interface{}
for _, region := range regions {
mapping := map[string]interface{}{
"id": region.RegionId,
"region_id": region.RegionId,
"local_name": region.LocalName,
}
log.Printf("[DEBUG] alicloud_regions - adding region mapping: %v", mapping)
ids = append(ids, string(region.RegionId))
s = append(s, mapping)
}
d.SetId(dataResourceIdHash(ids))
if err := d.Set("regions", s); err != nil {
return err
}
return nil
}

View File

@ -1,109 +0,0 @@
package alicloud
import (
"testing"
"github.com/hashicorp/terraform/helper/resource"
)
func TestAccAlicloudRegionsDataSource_regions(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckAlicloudRegionsDataSourceRegionsConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAlicloudDataSourceID("data.alicloud_regions.region"),
resource.TestCheckResourceAttr("data.alicloud_regions.region", "name", "cn-beijing"),
resource.TestCheckResourceAttr("data.alicloud_regions.region", "current", "true"),
resource.TestCheckResourceAttr("data.alicloud_regions.region", "regions.#", "1"),
resource.TestCheckResourceAttr("data.alicloud_regions.region", "regions.0.id", "cn-beijing"),
resource.TestCheckResourceAttr("data.alicloud_regions.region", "regions.0.region_id", "cn-beijing"),
resource.TestCheckResourceAttr("data.alicloud_regions.region", "regions.0.local_name", "华北 2"),
),
},
},
})
}
func TestAccAlicloudRegionsDataSource_name(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckAlicloudRegionsDataSourceNameConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAlicloudDataSourceID("data.alicloud_regions.name_filtered_region"),
resource.TestCheckResourceAttr("data.alicloud_regions.name_filtered_region", "name", "cn-hangzhou")),
},
},
})
}
func TestAccAlicloudRegionsDataSource_current(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckAlicloudRegionsDataSourceCurrentConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAlicloudDataSourceID("data.alicloud_regions.current_filtered_region"),
resource.TestCheckResourceAttr("data.alicloud_regions.current_filtered_region", "current", "true"),
),
},
},
})
}
func TestAccAlicloudRegionsDataSource_empty(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckAlicloudRegionsDataSourceEmptyConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAlicloudDataSourceID("data.alicloud_regions.empty_params_region"),
resource.TestCheckResourceAttr("data.alicloud_regions.empty_params_region", "regions.0.id", "cn-shenzhen"),
resource.TestCheckResourceAttr("data.alicloud_regions.empty_params_region", "regions.0.region_id", "cn-shenzhen"),
resource.TestCheckResourceAttr("data.alicloud_regions.empty_params_region", "regions.0.local_name", "华南 1"),
),
},
},
})
}
// Instance store test - using centos regions
const testAccCheckAlicloudRegionsDataSourceRegionsConfig = `
data "alicloud_regions" "region" {
name = "cn-beijing"
current = true
}
`
// Testing name parameter
const testAccCheckAlicloudRegionsDataSourceNameConfig = `
data "alicloud_regions" "name_filtered_region" {
name = "cn-hangzhou"
}
`
// Testing current parameter
const testAccCheckAlicloudRegionsDataSourceCurrentConfig = `
data "alicloud_regions" "current_filtered_region" {
current = true
}
`
// Testing empty parmas
const testAccCheckAlicloudRegionsDataSourceEmptyConfig = `
data "alicloud_regions" "empty_params_region" {
}
`

View File

@ -1,137 +0,0 @@
package alicloud
import (
"fmt"
"github.com/denverdino/aliyungo/ecs"
"github.com/hashicorp/terraform/helper/schema"
"log"
"reflect"
)
func dataSourceAlicloudZones() *schema.Resource {
return &schema.Resource{
Read: dataSourceAlicloudZonesRead,
Schema: map[string]*schema.Schema{
"available_instance_type": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"available_resource_creation": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"available_disk_category": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
// Computed values.
"zones": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Computed: true,
},
"local_name": {
Type: schema.TypeString,
Computed: true,
},
"available_instance_types": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"available_resource_creation": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"available_disk_categories": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
},
},
},
}
}
func dataSourceAlicloudZonesRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AliyunClient).ecsconn
insType, _ := d.Get("available_instance_type").(string)
resType, _ := d.Get("available_resource_creation").(string)
diskType, _ := d.Get("available_disk_category").(string)
resp, err := conn.DescribeZones(getRegion(d, meta))
if err != nil {
return err
}
var zoneTypes []ecs.ZoneType
for _, types := range resp {
if insType != "" && !constraints(types.AvailableInstanceTypes.InstanceTypes, insType) {
continue
}
if resType != "" && !constraints(types.AvailableResourceCreation.ResourceTypes, resType) {
continue
}
if diskType != "" && !constraints(types.AvailableDiskCategories.DiskCategories, diskType) {
continue
}
zoneTypes = append(zoneTypes, types)
}
if len(zoneTypes) < 1 {
return fmt.Errorf("Your query returned no results. Please change your search criteria and try again.")
}
log.Printf("[DEBUG] alicloud_zones - Zones found: %#v", zoneTypes)
return zonesDescriptionAttributes(d, zoneTypes)
}
// check array constraints str
func constraints(arr interface{}, v string) bool {
arrs := reflect.ValueOf(arr)
len := arrs.Len()
for i := 0; i < len; i++ {
if arrs.Index(i).String() == v {
return true
}
}
return false
}
func zonesDescriptionAttributes(d *schema.ResourceData, types []ecs.ZoneType) error {
var ids []string
var s []map[string]interface{}
for _, t := range types {
mapping := map[string]interface{}{
"id": t.ZoneId,
"local_name": t.LocalName,
"available_instance_types": t.AvailableInstanceTypes.InstanceTypes,
"available_resource_creation": t.AvailableResourceCreation.ResourceTypes,
"available_disk_categories": t.AvailableDiskCategories.DiskCategories,
}
log.Printf("[DEBUG] alicloud_zones - adding zone mapping: %v", mapping)
ids = append(ids, t.ZoneId)
s = append(s, mapping)
}
d.SetId(dataResourceIdHash(ids))
if err := d.Set("zones", s); err != nil {
return err
}
return nil
}

View File

@ -1,132 +0,0 @@
package alicloud
import (
"fmt"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"strconv"
"testing"
)
func TestAccAlicloudZonesDataSource_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckAlicloudZonesDataSourceBasicConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAlicloudDataSourceID("data.alicloud_zones.foo"),
),
},
},
})
}
func TestAccAlicloudZonesDataSource_filter(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckAlicloudZonesDataSourceFilter,
Check: resource.ComposeTestCheckFunc(
testAccCheckAlicloudDataSourceID("data.alicloud_zones.foo"),
testCheckZoneLength("data.alicloud_zones.foo"),
),
},
resource.TestStep{
Config: testAccCheckAlicloudZonesDataSourceFilterIoOptimized,
Check: resource.ComposeTestCheckFunc(
testAccCheckAlicloudDataSourceID("data.alicloud_zones.foo"),
testCheckZoneLength("data.alicloud_zones.foo"),
),
},
},
})
}
func TestAccAlicloudZonesDataSource_unitRegion(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckAlicloudZonesDataSource_unitRegion,
Check: resource.ComposeTestCheckFunc(
testAccCheckAlicloudDataSourceID("data.alicloud_zones.foo"),
),
},
},
})
}
// the zone length changed occasionally
// check by range to avoid test case failure
func testCheckZoneLength(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
ms := s.RootModule()
rs, ok := ms.Resources[name]
if !ok {
return fmt.Errorf("Not found: %s", name)
}
is := rs.Primary
if is == nil {
return fmt.Errorf("No primary instance: %s", name)
}
i, err := strconv.Atoi(is.Attributes["zones.#"])
if err != nil {
return fmt.Errorf("convert zone length err: %#v", err)
}
if i <= 0 {
return fmt.Errorf("zone length expected greater than 0 got err: %d", i)
}
return nil
}
}
const testAccCheckAlicloudZonesDataSourceBasicConfig = `
data "alicloud_zones" "foo" {
}
`
const testAccCheckAlicloudZonesDataSourceFilter = `
data "alicloud_zones" "foo" {
available_instance_type= "ecs.c2.xlarge"
available_resource_creation= "VSwitch"
available_disk_category= "cloud_efficiency"
}
`
const testAccCheckAlicloudZonesDataSourceFilterIoOptimized = `
data "alicloud_zones" "foo" {
available_instance_type= "ecs.c2.xlarge"
available_resource_creation= "IoOptimized"
available_disk_category= "cloud"
}
`
const testAccCheckAlicloudZonesDataSource_unitRegion = `
provider "alicloud" {
alias = "northeast"
region = "ap-northeast-1"
}
data "alicloud_zones" "foo" {
provider = "alicloud.northeast"
available_resource_creation= "VSwitch"
}
`

View File

@ -1,52 +0,0 @@
package alicloud
import "github.com/denverdino/aliyungo/common"
const (
// common
Notfound = "Not found"
// ecs
InstanceNotfound = "Instance.Notfound"
// disk
DiskIncorrectStatus = "IncorrectDiskStatus"
DiskCreatingSnapshot = "DiskCreatingSnapshot"
InstanceLockedForSecurity = "InstanceLockedForSecurity"
SystemDiskNotFound = "SystemDiskNotFound"
// eip
EipIncorrectStatus = "IncorrectEipStatus"
InstanceIncorrectStatus = "IncorrectInstanceStatus"
HaVipIncorrectStatus = "IncorrectHaVipStatus"
// slb
LoadBalancerNotFound = "InvalidLoadBalancerId.NotFound"
// security_group
InvalidInstanceIdAlreadyExists = "InvalidInstanceId.AlreadyExists"
InvalidSecurityGroupIdNotFound = "InvalidSecurityGroupId.NotFound"
SgDependencyViolation = "DependencyViolation"
//Nat gateway
NatGatewayInvalidRegionId = "Invalid.RegionId"
DependencyViolationBandwidthPackages = "DependencyViolation.BandwidthPackages"
NotFindSnatEntryBySnatId = "NotFindSnatEntryBySnatId"
NotFindForwardEntryByForwardId = "NotFindForwardEntryByForwardId"
// vswitch
VswitcInvalidRegionId = "InvalidRegionId.NotFound"
// ess
InvalidScalingGroupIdNotFound = "InvalidScalingGroupId.NotFound"
IncorrectScalingConfigurationLifecycleState = "IncorrectScalingConfigurationLifecycleState"
//unknown Error
UnknownError = "UnknownError"
)
func GetNotFoundErrorFromString(str string) error {
return &common.Error{
ErrorResponse: common.ErrorResponse{
Code: InstanceNotfound,
Message: str,
},
StatusCode: -1,
}
}

View File

@ -1,37 +0,0 @@
package alicloud
type GroupRuleDirection string
const (
GroupRuleIngress = GroupRuleDirection("ingress")
GroupRuleEgress = GroupRuleDirection("egress")
)
type GroupRuleIpProtocol string
const (
GroupRuleTcp = GroupRuleIpProtocol("tcp")
GroupRuleUdp = GroupRuleIpProtocol("udp")
GroupRuleIcmp = GroupRuleIpProtocol("icmp")
GroupRuleGre = GroupRuleIpProtocol("gre")
GroupRuleAll = GroupRuleIpProtocol("all")
)
type GroupRuleNicType string
const (
GroupRuleInternet = GroupRuleNicType("internet")
GroupRuleIntranet = GroupRuleNicType("intranet")
)
type GroupRulePolicy string
const (
GroupRulePolicyAccept = GroupRulePolicy("accept")
GroupRulePolicyDrop = GroupRulePolicy("drop")
)
const (
EcsApiVersion20160314 = "2016-03-14"
EcsApiVersion20140526 = "2014-05-26"
)

View File

@ -1,164 +0,0 @@
package alicloud
import (
"fmt"
"strings"
"github.com/denverdino/aliyungo/slb"
)
type Listener struct {
slb.HTTPListenerType
InstancePort int
LoadBalancerPort int
Protocol string
//tcp & udp
PersistenceTimeout int
//https
SSLCertificateId string
//tcp
HealthCheckType slb.HealthCheckType
//api interface: http & https is HealthCheckTimeout, tcp & udp is HealthCheckConnectTimeout
HealthCheckConnectTimeout int
}
type ListenerErr struct {
ErrType string
Err error
}
func (e *ListenerErr) Error() string {
return e.ErrType + " " + e.Err.Error()
}
const (
HealthCheckErrType = "healthCheckErrType"
StickySessionErrType = "stickySessionErrType"
CookieTimeOutErrType = "cookieTimeoutErrType"
CookieErrType = "cookieErrType"
)
// Takes the result of flatmap.Expand for an array of listeners and
// returns ELB API compatible objects
func expandListeners(configured []interface{}) ([]*Listener, error) {
listeners := make([]*Listener, 0, len(configured))
// Loop over our configured listeners and create
// an array of aws-sdk-go compatabile objects
for _, lRaw := range configured {
data := lRaw.(map[string]interface{})
ip := data["instance_port"].(int)
lp := data["lb_port"].(int)
l := &Listener{
InstancePort: ip,
LoadBalancerPort: lp,
Protocol: data["lb_protocol"].(string),
}
l.Bandwidth = data["bandwidth"].(int)
if v, ok := data["scheduler"]; ok {
l.Scheduler = slb.SchedulerType(v.(string))
}
if v, ok := data["ssl_certificate_id"]; ok {
l.SSLCertificateId = v.(string)
}
if v, ok := data["sticky_session"]; ok {
l.StickySession = slb.FlagType(v.(string))
}
if v, ok := data["sticky_session_type"]; ok {
l.StickySessionType = slb.StickySessionType(v.(string))
}
if v, ok := data["cookie_timeout"]; ok {
l.CookieTimeout = v.(int)
}
if v, ok := data["cookie"]; ok {
l.Cookie = v.(string)
}
if v, ok := data["persistence_timeout"]; ok {
l.PersistenceTimeout = v.(int)
}
if v, ok := data["health_check"]; ok {
l.HealthCheck = slb.FlagType(v.(string))
}
if v, ok := data["health_check_type"]; ok {
l.HealthCheckType = slb.HealthCheckType(v.(string))
}
if v, ok := data["health_check_domain"]; ok {
l.HealthCheckDomain = v.(string)
}
if v, ok := data["health_check_uri"]; ok {
l.HealthCheckURI = v.(string)
}
if v, ok := data["health_check_connect_port"]; ok {
l.HealthCheckConnectPort = v.(int)
}
if v, ok := data["healthy_threshold"]; ok {
l.HealthyThreshold = v.(int)
}
if v, ok := data["unhealthy_threshold"]; ok {
l.UnhealthyThreshold = v.(int)
}
if v, ok := data["health_check_timeout"]; ok {
l.HealthCheckTimeout = v.(int)
}
if v, ok := data["health_check_interval"]; ok {
l.HealthCheckInterval = v.(int)
}
if v, ok := data["health_check_http_code"]; ok {
l.HealthCheckHttpCode = slb.HealthCheckHttpCodeType(v.(string))
}
var valid bool
if l.SSLCertificateId != "" {
// validate the protocol is correct
for _, p := range []string{"https", "ssl"} {
if strings.ToLower(l.Protocol) == p {
valid = true
}
}
} else {
valid = true
}
if valid {
listeners = append(listeners, l)
} else {
return nil, fmt.Errorf("[ERR] SLB Listener: ssl_certificate_id may be set only when protocol is 'https' or 'ssl'")
}
}
return listeners, nil
}
func expandBackendServers(list []interface{}) []slb.BackendServerType {
result := make([]slb.BackendServerType, 0, len(list))
for _, i := range list {
if i.(string) != "" {
result = append(result, slb.BackendServerType{ServerId: i.(string), Weight: 100})
}
}
return result
}

View File

@ -1,43 +0,0 @@
package alicloud
import (
"github.com/denverdino/aliyungo/common"
"github.com/denverdino/aliyungo/ecs"
)
type Tag struct {
Key string
Value string
}
type AddTagsArgs struct {
ResourceId string
ResourceType ecs.TagResourceType //image, instance, snapshot or disk
RegionId common.Region
Tag []Tag
}
type RemoveTagsArgs struct {
ResourceId string
ResourceType ecs.TagResourceType //image, instance, snapshot or disk
RegionId common.Region
Tag []Tag
}
func AddTags(client *ecs.Client, args *AddTagsArgs) error {
response := ecs.AddTagsResponse{}
err := client.Invoke("AddTags", args, &response)
if err != nil {
return err
}
return err
}
func RemoveTags(client *ecs.Client, args *RemoveTagsArgs) error {
response := ecs.RemoveTagsResponse{}
err := client.Invoke("RemoveTags", args, &response)
if err != nil {
return err
}
return err
}

View File

@ -1,112 +0,0 @@
package alicloud
import (
"github.com/denverdino/aliyungo/common"
"github.com/hashicorp/terraform/helper/mutexkv"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
"os"
)
// Provider returns a schema.Provider for alicloud
func Provider() terraform.ResourceProvider {
return &schema.Provider{
Schema: map[string]*schema.Schema{
"access_key": &schema.Schema{
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_ACCESS_KEY", nil),
Description: descriptions["access_key"],
},
"secret_key": &schema.Schema{
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_SECRET_KEY", nil),
Description: descriptions["secret_key"],
},
"region": &schema.Schema{
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_REGION", DEFAULT_REGION),
Description: descriptions["region"],
},
},
DataSourcesMap: map[string]*schema.Resource{
"alicloud_images": dataSourceAlicloudImages(),
"alicloud_regions": dataSourceAlicloudRegions(),
"alicloud_zones": dataSourceAlicloudZones(),
"alicloud_instance_types": dataSourceAlicloudInstanceTypes(),
},
ResourcesMap: map[string]*schema.Resource{
"alicloud_instance": resourceAliyunInstance(),
"alicloud_disk": resourceAliyunDisk(),
"alicloud_disk_attachment": resourceAliyunDiskAttachment(),
"alicloud_security_group": resourceAliyunSecurityGroup(),
"alicloud_security_group_rule": resourceAliyunSecurityGroupRule(),
"alicloud_db_instance": resourceAlicloudDBInstance(),
"alicloud_ess_scaling_group": resourceAlicloudEssScalingGroup(),
"alicloud_ess_scaling_configuration": resourceAlicloudEssScalingConfiguration(),
"alicloud_ess_scaling_rule": resourceAlicloudEssScalingRule(),
"alicloud_ess_schedule": resourceAlicloudEssSchedule(),
"alicloud_vpc": resourceAliyunVpc(),
"alicloud_nat_gateway": resourceAliyunNatGateway(),
//both subnet and vswith exists,cause compatible old version, and compatible aws habit.
"alicloud_subnet": resourceAliyunSubnet(),
"alicloud_vswitch": resourceAliyunSubnet(),
"alicloud_route_entry": resourceAliyunRouteEntry(),
"alicloud_snat_entry": resourceAliyunSnatEntry(),
"alicloud_forward_entry": resourceAliyunForwardEntry(),
"alicloud_eip": resourceAliyunEip(),
"alicloud_eip_association": resourceAliyunEipAssociation(),
"alicloud_slb": resourceAliyunSlb(),
"alicloud_slb_attachment": resourceAliyunSlbAttachment(),
},
ConfigureFunc: providerConfigure,
}
}
func providerConfigure(d *schema.ResourceData) (interface{}, error) {
accesskey, ok := d.GetOk("access_key")
if !ok {
accesskey = os.Getenv("ALICLOUD_ACCESS_KEY")
}
secretkey, ok := d.GetOk("secret_key")
if !ok {
secretkey = os.Getenv("ALICLOUD_SECRET_KEY")
}
region, ok := d.GetOk("region")
if !ok {
region = os.Getenv("ALICLOUD_REGION")
if region == "" {
region = DEFAULT_REGION
}
}
config := Config{
AccessKey: accesskey.(string),
SecretKey: secretkey.(string),
Region: common.Region(region.(string)),
}
client, err := config.Client()
if err != nil {
return nil, err
}
return client, nil
}
// This is a global MutexKV for use within this plugin.
var alicloudMutexKV = mutexkv.NewMutexKV()
var descriptions map[string]string
func init() {
descriptions = map[string]string{
"access_key": "Access key of alicloud",
"secret_key": "Secret key of alicloud",
"region": "Region of alicloud",
}
}

View File

@ -1,59 +0,0 @@
package alicloud
import (
"log"
"os"
"testing"
"fmt"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
)
var testAccProviders map[string]terraform.ResourceProvider
var testAccProvider *schema.Provider
func init() {
testAccProvider = Provider().(*schema.Provider)
testAccProviders = map[string]terraform.ResourceProvider{
"alicloud": testAccProvider,
}
}
func TestProvider(t *testing.T) {
if err := Provider().(*schema.Provider).InternalValidate(); err != nil {
t.Fatalf("err: %s", err)
}
}
func TestProvider_impl(t *testing.T) {
var _ terraform.ResourceProvider = Provider()
}
func testAccPreCheck(t *testing.T) {
if v := os.Getenv("ALICLOUD_ACCESS_KEY"); v == "" {
t.Fatal("ALICLOUD_ACCESS_KEY must be set for acceptance tests")
}
if v := os.Getenv("ALICLOUD_SECRET_KEY"); v == "" {
t.Fatal("ALICLOUD_SECRET_KEY must be set for acceptance tests")
}
if v := os.Getenv("ALICLOUD_REGION"); v == "" {
log.Println("[INFO] Test: Using cn-beijing as test region")
os.Setenv("ALICLOUD_REGION", "cn-beijing")
}
}
func testAccCheckAlicloudDataSourceID(n string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Can't find data source: %s", n)
}
if rs.Primary.ID == "" {
return fmt.Errorf("data source ID not set")
}
return nil
}
}

View File

@ -1,550 +0,0 @@
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 {
return fmt.Errorf("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
}
if resp.Databases.Database == nil {
d.SetId("")
return nil
}
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
}

View File

@ -1,765 +0,0 @@
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" {
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"
}
`

View File

@ -1,247 +0,0 @@
package alicloud
import (
"fmt"
"github.com/denverdino/aliyungo/common"
"github.com/denverdino/aliyungo/ecs"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"log"
"time"
)
func resourceAliyunDisk() *schema.Resource {
return &schema.Resource{
Create: resourceAliyunDiskCreate,
Read: resourceAliyunDiskRead,
Update: resourceAliyunDiskUpdate,
Delete: resourceAliyunDiskDelete,
Schema: map[string]*schema.Schema{
"availability_zone": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ValidateFunc: validateDiskName,
},
"description": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ValidateFunc: validateDiskDescription,
},
"category": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ValidateFunc: validateDiskCategory,
Default: "cloud",
},
"size": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
},
"snapshot_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"status": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"tags": tagsSchema(),
},
}
}
func resourceAliyunDiskCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*AliyunClient)
conn := client.ecsconn
availabilityZone, err := client.DescribeZone(d.Get("availability_zone").(string))
if err != nil {
return err
}
args := &ecs.CreateDiskArgs{
RegionId: getRegion(d, meta),
ZoneId: availabilityZone.ZoneId,
}
if v, ok := d.GetOk("category"); ok && v.(string) != "" {
category := ecs.DiskCategory(v.(string))
if err := client.DiskAvailable(availabilityZone, category); err != nil {
return err
}
args.DiskCategory = category
}
if v, ok := d.GetOk("size"); ok {
size := v.(int)
if args.DiskCategory == ecs.DiskCategoryCloud && (size < 5 || size > 2000) {
return fmt.Errorf("the size of cloud disk must between 5 to 2000")
}
if (args.DiskCategory == ecs.DiskCategoryCloudEfficiency ||
args.DiskCategory == ecs.DiskCategoryCloudSSD) && (size < 20 || size > 32768) {
return fmt.Errorf("the size of %s disk must between 20 to 32768", args.DiskCategory)
}
args.Size = size
d.Set("size", args.Size)
}
if v, ok := d.GetOk("snapshot_id"); ok && v.(string) != "" {
args.SnapshotId = v.(string)
}
if args.Size <= 0 && args.SnapshotId == "" {
return fmt.Errorf("One of size or snapshot_id is required when specifying an ECS disk.")
}
if v, ok := d.GetOk("name"); ok && v.(string) != "" {
args.DiskName = v.(string)
}
if v, ok := d.GetOk("description"); ok && v.(string) != "" {
args.Description = v.(string)
}
diskID, err := conn.CreateDisk(args)
if err != nil {
return fmt.Errorf("CreateDisk got a error: %#v", err)
}
d.SetId(diskID)
return resourceAliyunDiskUpdate(d, meta)
}
func resourceAliyunDiskRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AliyunClient).ecsconn
disks, _, err := conn.DescribeDisks(&ecs.DescribeDisksArgs{
RegionId: getRegion(d, meta),
DiskIds: []string{d.Id()},
})
if err != nil {
if notFoundError(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error DescribeDiskAttribute: %#v", err)
}
log.Printf("[DEBUG] DescribeDiskAttribute for instance: %#v", disks)
if disks == nil || len(disks) <= 0 {
return fmt.Errorf("No disks found.")
}
disk := disks[0]
d.Set("availability_zone", disk.ZoneId)
d.Set("category", disk.Category)
d.Set("size", disk.Size)
d.Set("status", disk.Status)
d.Set("name", disk.DiskName)
d.Set("description", disk.Description)
d.Set("snapshot_id", disk.SourceSnapshotId)
tags, _, err := conn.DescribeTags(&ecs.DescribeTagsArgs{
RegionId: getRegion(d, meta),
ResourceType: ecs.TagResourceDisk,
ResourceId: d.Id(),
})
if err != nil {
log.Printf("[DEBUG] DescribeTags for disk got error: %#v", err)
}
d.Set("tags", tagsToMap(tags))
return nil
}
func resourceAliyunDiskUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*AliyunClient)
conn := client.ecsconn
d.Partial(true)
if err := setTags(client, ecs.TagResourceDisk, d); err != nil {
log.Printf("[DEBUG] Set tags for instance got error: %#v", err)
return fmt.Errorf("Set tags for instance got error: %#v", err)
} else {
d.SetPartial("tags")
}
attributeUpdate := false
args := &ecs.ModifyDiskAttributeArgs{
DiskId: d.Id(),
}
if d.HasChange("name") {
d.SetPartial("name")
val := d.Get("name").(string)
args.DiskName = val
attributeUpdate = true
}
if d.HasChange("description") {
d.SetPartial("description")
val := d.Get("description").(string)
args.Description = val
attributeUpdate = true
}
if attributeUpdate {
if err := conn.ModifyDiskAttribute(args); err != nil {
return err
}
}
d.Partial(false)
return resourceAliyunDiskRead(d, meta)
}
func resourceAliyunDiskDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AliyunClient).ecsconn
return resource.Retry(5*time.Minute, func() *resource.RetryError {
err := conn.DeleteDisk(d.Id())
if err != nil {
e, _ := err.(*common.Error)
if e.ErrorResponse.Code == DiskIncorrectStatus || e.ErrorResponse.Code == DiskCreatingSnapshot {
return resource.RetryableError(fmt.Errorf("Disk in use - trying again while it is deleted."))
}
}
disks, _, descErr := conn.DescribeDisks(&ecs.DescribeDisksArgs{
RegionId: getRegion(d, meta),
DiskIds: []string{d.Id()},
})
if descErr != nil {
log.Printf("[ERROR] Delete disk is failed.")
return resource.NonRetryableError(descErr)
}
if disks == nil || len(disks) < 1 {
return nil
}
return resource.RetryableError(fmt.Errorf("Disk in use - trying again while it is deleted."))
})
}

View File

@ -1,176 +0,0 @@
package alicloud
import (
"fmt"
"strings"
"github.com/denverdino/aliyungo/common"
"github.com/denverdino/aliyungo/ecs"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"log"
"time"
)
func resourceAliyunDiskAttachment() *schema.Resource {
return &schema.Resource{
Create: resourceAliyunDiskAttachmentCreate,
Read: resourceAliyunDiskAttachmentRead,
Delete: resourceAliyunDiskAttachmentDelete,
Schema: map[string]*schema.Schema{
"instance_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"disk_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"device_name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
},
}
}
func resourceAliyunDiskAttachmentCreate(d *schema.ResourceData, meta interface{}) error {
err := diskAttachment(d, meta)
if err != nil {
return err
}
d.SetId(d.Get("disk_id").(string) + ":" + d.Get("instance_id").(string))
return resourceAliyunDiskAttachmentRead(d, meta)
}
func resourceAliyunDiskAttachmentRead(d *schema.ResourceData, meta interface{}) error {
diskId, instanceId, err := getDiskIDAndInstanceID(d, meta)
if err != nil {
return err
}
conn := meta.(*AliyunClient).ecsconn
disks, _, err := conn.DescribeDisks(&ecs.DescribeDisksArgs{
RegionId: getRegion(d, meta),
InstanceId: instanceId,
DiskIds: []string{diskId},
})
if err != nil {
if notFoundError(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error DescribeDiskAttribute: %#v", err)
}
log.Printf("[DEBUG] DescribeDiskAttribute for instance: %#v", disks)
if disks == nil || len(disks) <= 0 {
return fmt.Errorf("No Disks Found.")
}
disk := disks[0]
d.Set("instance_id", disk.InstanceId)
d.Set("disk_id", disk.DiskId)
d.Set("device_name", disk.Device)
return nil
}
func resourceAliyunDiskAttachmentDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AliyunClient).ecsconn
diskID, instanceID, err := getDiskIDAndInstanceID(d, meta)
if err != nil {
return err
}
return resource.Retry(5*time.Minute, func() *resource.RetryError {
err := conn.DetachDisk(instanceID, diskID)
if err != nil {
e, _ := err.(*common.Error)
if e.ErrorResponse.Code == DiskIncorrectStatus || e.ErrorResponse.Code == InstanceLockedForSecurity {
return resource.RetryableError(fmt.Errorf("Disk in use - trying again while it detaches"))
}
}
disks, _, descErr := conn.DescribeDisks(&ecs.DescribeDisksArgs{
RegionId: getRegion(d, meta),
DiskIds: []string{diskID},
})
if descErr != nil {
log.Printf("[ERROR] Disk %s is not detached.", diskID)
return resource.NonRetryableError(err)
}
for _, disk := range disks {
if disk.Status != ecs.DiskStatusAvailable {
return resource.RetryableError(fmt.Errorf("Disk in use - trying again while it is deleted."))
}
}
return nil
})
}
func getDiskIDAndInstanceID(d *schema.ResourceData, meta interface{}) (string, string, error) {
parts := strings.Split(d.Id(), ":")
if len(parts) != 2 {
return "", "", fmt.Errorf("invalid resource id")
}
return parts[0], parts[1], nil
}
func diskAttachment(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AliyunClient).ecsconn
diskID := d.Get("disk_id").(string)
instanceID := d.Get("instance_id").(string)
deviceName := d.Get("device_name").(string)
args := &ecs.AttachDiskArgs{
InstanceId: instanceID,
DiskId: diskID,
Device: deviceName,
}
return resource.Retry(5*time.Minute, func() *resource.RetryError {
err := conn.AttachDisk(args)
log.Printf("error : %s", err)
if err != nil {
e, _ := err.(*common.Error)
if e.ErrorResponse.Code == DiskIncorrectStatus || e.ErrorResponse.Code == InstanceIncorrectStatus {
return resource.RetryableError(fmt.Errorf("Disk or Instance status is incorrect - trying again while it attaches"))
}
return resource.NonRetryableError(err)
}
disks, _, descErr := conn.DescribeDisks(&ecs.DescribeDisksArgs{
RegionId: getRegion(d, meta),
InstanceId: instanceID,
DiskIds: []string{diskID},
})
if descErr != nil {
log.Printf("[ERROR] Disk %s is not attached.", diskID)
return resource.NonRetryableError(err)
}
if disks == nil || len(disks) <= 0 {
return resource.RetryableError(fmt.Errorf("Disk in attaching - trying again while it is attached."))
}
return nil
})
}

View File

@ -1,155 +0,0 @@
package alicloud
import (
"fmt"
"testing"
"github.com/denverdino/aliyungo/ecs"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"time"
)
func TestAccAlicloudDiskAttachment(t *testing.T) {
var i ecs.InstanceAttributesType
var v ecs.DiskItemType
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
// module name
IDRefreshName: "alicloud_disk_attachment.disk-att",
Providers: testAccProviders,
CheckDestroy: testAccCheckDiskAttachmentDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccDiskAttachmentConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckInstanceExists(
"alicloud_instance.instance", &i),
testAccCheckDiskExists(
"alicloud_disk.disk", &v),
testAccCheckDiskAttachmentExists(
"alicloud_disk_attachment.disk-att", &i, &v),
resource.TestCheckResourceAttr(
"alicloud_disk_attachment.disk-att",
"device_name",
"/dev/xvdb"),
),
},
},
})
}
func testAccCheckDiskAttachmentExists(n string, instance *ecs.InstanceAttributesType, disk *ecs.DiskItemType) 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 Disk ID is set")
}
client := testAccProvider.Meta().(*AliyunClient)
conn := client.ecsconn
request := &ecs.DescribeDisksArgs{
RegionId: client.Region,
DiskIds: []string{rs.Primary.Attributes["disk_id"]},
}
return resource.Retry(3*time.Minute, func() *resource.RetryError {
response, _, err := conn.DescribeDisks(request)
if response != nil {
for _, d := range response {
if d.Status != ecs.DiskStatusInUse {
return resource.RetryableError(fmt.Errorf("Disk is in attaching - trying again while it attaches"))
} else if d.InstanceId == instance.InstanceId {
// pass
*disk = d
return nil
}
}
}
if err != nil {
return resource.NonRetryableError(err)
}
return resource.NonRetryableError(fmt.Errorf("Error finding instance/disk"))
})
}
}
func testAccCheckDiskAttachmentDestroy(s *terraform.State) error {
for _, rs := range s.RootModule().Resources {
if rs.Type != "alicloud_disk_attachment" {
continue
}
// Try to find the Disk
client := testAccProvider.Meta().(*AliyunClient)
conn := client.ecsconn
request := &ecs.DescribeDisksArgs{
RegionId: client.Region,
DiskIds: []string{rs.Primary.ID},
}
response, _, err := conn.DescribeDisks(request)
for _, disk := range response {
if disk.Status != ecs.DiskStatusAvailable {
return fmt.Errorf("Error ECS Disk Attachment still exist")
}
}
if err != nil {
// Verify the error is what we want
return err
}
}
return nil
}
const testAccDiskAttachmentConfig = `
resource "alicloud_disk" "disk" {
availability_zone = "cn-beijing-a"
size = "50"
tags {
Name = "TerraformTest-disk"
}
}
resource "alicloud_instance" "instance" {
image_id = "ubuntu_140405_64_40G_cloudinit_20161115.vhd"
instance_type = "ecs.s1.small"
availability_zone = "cn-beijing-a"
security_groups = ["${alicloud_security_group.group.id}"]
instance_name = "hello"
internet_charge_type = "PayByBandwidth"
io_optimized = "none"
tags {
Name = "TerraformTest-instance"
}
}
resource "alicloud_disk_attachment" "disk-att" {
disk_id = "${alicloud_disk.disk.id}"
instance_id = "${alicloud_instance.instance.id}"
device_name = "/dev/xvdb"
}
resource "alicloud_security_group" "group" {
name = "terraform-test-group"
description = "New security group"
}
`

View File

@ -1,166 +0,0 @@
package alicloud
import (
"fmt"
"testing"
"github.com/denverdino/aliyungo/ecs"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"log"
)
func TestAccAlicloudDisk_basic(t *testing.T) {
var v ecs.DiskItemType
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
// module name
IDRefreshName: "alicloud_disk.foo",
Providers: testAccProviders,
CheckDestroy: testAccCheckDiskDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccDiskConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckDiskExists(
"alicloud_disk.foo", &v),
resource.TestCheckResourceAttr(
"alicloud_disk.foo",
"category",
"cloud_efficiency"),
resource.TestCheckResourceAttr(
"alicloud_disk.foo",
"size",
"30"),
),
},
},
})
}
func TestAccAlicloudDisk_withTags(t *testing.T) {
var v ecs.DiskItemType
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
//module name
IDRefreshName: "alicloud_disk.bar",
Providers: testAccProviders,
CheckDestroy: testAccCheckDiskDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccDiskConfigWithTags,
Check: resource.ComposeTestCheckFunc(
testAccCheckDiskExists("alicloud_disk.bar", &v),
resource.TestCheckResourceAttr(
"alicloud_disk.bar",
"tags.Name",
"TerraformTest"),
),
},
},
})
}
func testAccCheckDiskExists(n string, disk *ecs.DiskItemType) 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 Disk ID is set")
}
client := testAccProvider.Meta().(*AliyunClient)
conn := client.ecsconn
request := &ecs.DescribeDisksArgs{
RegionId: client.Region,
DiskIds: []string{rs.Primary.ID},
}
response, _, err := conn.DescribeDisks(request)
log.Printf("[WARN] disk ids %#v", rs.Primary.ID)
if err == nil {
if response != nil && len(response) > 0 {
*disk = response[0]
return nil
}
}
return fmt.Errorf("Error finding ECS Disk %#v", rs.Primary.ID)
}
}
func testAccCheckDiskDestroy(s *terraform.State) error {
for _, rs := range s.RootModule().Resources {
if rs.Type != "alicloud_disk" {
continue
}
// Try to find the Disk
client := testAccProvider.Meta().(*AliyunClient)
conn := client.ecsconn
request := &ecs.DescribeDisksArgs{
RegionId: client.Region,
DiskIds: []string{rs.Primary.ID},
}
response, _, err := conn.DescribeDisks(request)
if response != nil && len(response) > 0 {
return fmt.Errorf("Error ECS Disk still exist")
}
if err != nil {
// Verify the error is what we want
return err
}
}
return nil
}
const testAccDiskConfig = `
data "alicloud_zones" "default" {
"available_disk_category"= "cloud_efficiency"
}
resource "alicloud_disk" "foo" {
# cn-beijing
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
name = "New-disk"
description = "Hello ecs disk."
category = "cloud_efficiency"
size = "30"
}
`
const testAccDiskConfigWithTags = `
data "alicloud_zones" "default" {
"available_disk_category"= "cloud_efficiency"
}
resource "alicloud_disk" "bar" {
# cn-beijing
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
category = "cloud_efficiency"
size = "20"
tags {
Name = "TerraformTest"
}
}
`

View File

@ -1,157 +0,0 @@
package alicloud
import (
"strconv"
"fmt"
"github.com/denverdino/aliyungo/common"
"github.com/denverdino/aliyungo/ecs"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"time"
)
func resourceAliyunEip() *schema.Resource {
return &schema.Resource{
Create: resourceAliyunEipCreate,
Read: resourceAliyunEipRead,
Update: resourceAliyunEipUpdate,
Delete: resourceAliyunEipDelete,
Schema: map[string]*schema.Schema{
"bandwidth": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Default: 5,
},
"internet_charge_type": &schema.Schema{
Type: schema.TypeString,
Default: "PayByBandwidth",
Optional: true,
ForceNew: true,
ValidateFunc: validateInternetChargeType,
},
"ip_address": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"status": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"instance": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
},
}
}
func resourceAliyunEipCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AliyunClient).ecsconn
args, err := buildAliyunEipArgs(d, meta)
if err != nil {
return err
}
_, allocationID, err := conn.AllocateEipAddress(args)
if err != nil {
return err
}
d.SetId(allocationID)
return resourceAliyunEipRead(d, meta)
}
func resourceAliyunEipRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*AliyunClient)
eip, err := client.DescribeEipAddress(d.Id())
if err != nil {
if notFoundError(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error Describe Eip Attribute: %#v", err)
}
if eip.InstanceId != "" {
d.Set("instance", eip.InstanceId)
} else {
d.Set("instance", "")
return nil
}
bandwidth, _ := strconv.Atoi(eip.Bandwidth)
d.Set("bandwidth", bandwidth)
d.Set("internet_charge_type", eip.InternetChargeType)
d.Set("ip_address", eip.IpAddress)
d.Set("status", eip.Status)
return nil
}
func resourceAliyunEipUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AliyunClient).ecsconn
d.Partial(true)
if d.HasChange("bandwidth") {
err := conn.ModifyEipAddressAttribute(d.Id(), d.Get("bandwidth").(int))
if err != nil {
return err
}
d.SetPartial("bandwidth")
}
d.Partial(false)
return nil
}
func resourceAliyunEipDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AliyunClient).ecsconn
return resource.Retry(5*time.Minute, func() *resource.RetryError {
err := conn.ReleaseEipAddress(d.Id())
if err != nil {
e, _ := err.(*common.Error)
if e.ErrorResponse.Code == EipIncorrectStatus {
return resource.RetryableError(fmt.Errorf("EIP in use - trying again while it is deleted."))
}
}
args := &ecs.DescribeEipAddressesArgs{
RegionId: getRegion(d, meta),
AllocationId: d.Id(),
}
eips, _, descErr := conn.DescribeEipAddresses(args)
if descErr != nil {
return resource.NonRetryableError(descErr)
} else if eips == nil || len(eips) < 1 {
return nil
}
return resource.RetryableError(fmt.Errorf("EIP in use - trying again while it is deleted."))
})
}
func buildAliyunEipArgs(d *schema.ResourceData, meta interface{}) (*ecs.AllocateEipAddressArgs, error) {
args := &ecs.AllocateEipAddressArgs{
RegionId: getRegion(d, meta),
Bandwidth: d.Get("bandwidth").(int),
InternetChargeType: common.InternetChargeType(d.Get("internet_charge_type").(string)),
}
return args, nil
}

View File

@ -1,131 +0,0 @@
package alicloud
import (
"fmt"
"strings"
"github.com/denverdino/aliyungo/common"
"github.com/denverdino/aliyungo/ecs"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"time"
)
func resourceAliyunEipAssociation() *schema.Resource {
return &schema.Resource{
Create: resourceAliyunEipAssociationCreate,
Read: resourceAliyunEipAssociationRead,
Delete: resourceAliyunEipAssociationDelete,
Schema: map[string]*schema.Schema{
"allocation_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"instance_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
},
}
}
func resourceAliyunEipAssociationCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AliyunClient).ecsconn
allocationId := d.Get("allocation_id").(string)
instanceId := d.Get("instance_id").(string)
if err := conn.AssociateEipAddress(allocationId, instanceId); err != nil {
return err
}
d.SetId(allocationId + ":" + instanceId)
return resourceAliyunEipAssociationRead(d, meta)
}
func resourceAliyunEipAssociationRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*AliyunClient)
allocationId, instanceId, err := getAllocationIdAndInstanceId(d, meta)
if err != nil {
return err
}
eip, err := client.DescribeEipAddress(allocationId)
if err != nil {
if notFoundError(err) {
d.SetId("")
return nil
}
return fmt.Errorf("Error Describe Eip Attribute: %#v", err)
}
if eip.InstanceId != instanceId {
d.SetId("")
return nil
}
d.Set("instance_id", eip.InstanceId)
d.Set("allocation_id", allocationId)
return nil
}
func resourceAliyunEipAssociationDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AliyunClient).ecsconn
allocationId, instanceId, err := getAllocationIdAndInstanceId(d, meta)
if err != nil {
return err
}
return resource.Retry(5*time.Minute, func() *resource.RetryError {
err := conn.UnassociateEipAddress(allocationId, instanceId)
if err != nil {
e, _ := err.(*common.Error)
errCode := e.ErrorResponse.Code
if errCode == InstanceIncorrectStatus || errCode == HaVipIncorrectStatus {
return resource.RetryableError(fmt.Errorf("Eip in use - trying again while make it unassociated."))
}
}
args := &ecs.DescribeEipAddressesArgs{
RegionId: getRegion(d, meta),
AllocationId: allocationId,
}
eips, _, descErr := conn.DescribeEipAddresses(args)
if descErr != nil {
return resource.NonRetryableError(descErr)
} else if eips == nil || len(eips) < 1 {
return nil
}
for _, eip := range eips {
if eip.Status != ecs.EipStatusAvailable {
return resource.RetryableError(fmt.Errorf("Eip in use - trying again while make it unassociated."))
}
}
return nil
})
}
func getAllocationIdAndInstanceId(d *schema.ResourceData, meta interface{}) (string, string, error) {
parts := strings.Split(d.Id(), ":")
if len(parts) != 2 {
return "", "", fmt.Errorf("invalid resource id")
}
return parts[0], parts[1], nil
}

View File

@ -1,158 +0,0 @@
package alicloud
import (
"fmt"
"testing"
"github.com/denverdino/aliyungo/ecs"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"time"
)
func TestAccAlicloudEIPAssociation(t *testing.T) {
var asso ecs.EipAddressSetType
var inst ecs.InstanceAttributesType
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
// module name
IDRefreshName: "alicloud_eip_association.foo",
Providers: testAccProviders,
CheckDestroy: testAccCheckEIPAssociationDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccEIPAssociationConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckInstanceExists(
"alicloud_instance.instance", &inst),
testAccCheckEIPExists(
"alicloud_eip.eip", &asso),
testAccCheckEIPAssociationExists(
"alicloud_eip_association.foo", &inst, &asso),
),
},
},
})
}
func testAccCheckEIPAssociationExists(n string, instance *ecs.InstanceAttributesType, eip *ecs.EipAddressSetType) 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 EIP Association ID is set")
}
client := testAccProvider.Meta().(*AliyunClient)
return resource.Retry(3*time.Minute, func() *resource.RetryError {
d, err := client.DescribeEipAddress(rs.Primary.Attributes["allocation_id"])
if err != nil {
return resource.NonRetryableError(err)
}
if d != nil {
if d.Status != ecs.EipStatusInUse {
return resource.RetryableError(fmt.Errorf("Eip is in associating - trying again while it associates"))
} else if d.InstanceId == instance.InstanceId {
*eip = *d
return nil
}
}
return resource.NonRetryableError(fmt.Errorf("EIP Association not found"))
})
}
}
func testAccCheckEIPAssociationDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*AliyunClient)
for _, rs := range s.RootModule().Resources {
if rs.Type != "alicloud_eip_association" {
continue
}
if rs.Primary.ID == "" {
return fmt.Errorf("No EIP Association ID is set")
}
// Try to find the EIP
eips, _, err := client.ecsconn.DescribeEipAddresses(&ecs.DescribeEipAddressesArgs{
RegionId: client.Region,
AllocationId: rs.Primary.Attributes["allocation_id"],
})
for _, eip := range eips {
if eip.Status != ecs.EipStatusAvailable {
return fmt.Errorf("Error EIP Association still exist")
}
}
// Verify the error is what we want
if err != nil {
return err
}
}
return nil
}
const testAccEIPAssociationConfig = `
data "alicloud_zones" "default" {
"available_resource_creation"= "VSwitch"
}
resource "alicloud_vpc" "main" {
cidr_block = "10.1.0.0/21"
}
resource "alicloud_vswitch" "main" {
vpc_id = "${alicloud_vpc.main.id}"
cidr_block = "10.1.1.0/24"
availability_zone = "${data.alicloud_zones.default.zones.0.id}"
depends_on = [
"alicloud_vpc.main"]
}
resource "alicloud_instance" "instance" {
# cn-beijing
vswitch_id = "${alicloud_vswitch.main.id}"
image_id = "ubuntu_140405_32_40G_cloudinit_20161115.vhd"
# series II
instance_type = "ecs.n1.medium"
io_optimized = "optimized"
system_disk_category = "cloud_efficiency"
security_groups = ["${alicloud_security_group.group.id}"]
instance_name = "test_foo"
tags {
Name = "TerraformTest-instance"
}
}
resource "alicloud_eip" "eip" {
}
resource "alicloud_eip_association" "foo" {
allocation_id = "${alicloud_eip.eip.id}"
instance_id = "${alicloud_instance.instance.id}"
}
resource "alicloud_security_group" "group" {
name = "terraform-test-group"
description = "New security group"
vpc_id = "${alicloud_vpc.main.id}"
}
`

View File

@ -1,131 +0,0 @@
package alicloud
import (
"fmt"
"testing"
"github.com/denverdino/aliyungo/ecs"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"log"
)
func TestAccAlicloudEIP_basic(t *testing.T) {
var eip ecs.EipAddressSetType
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
// module name
IDRefreshName: "alicloud_eip.foo",
Providers: testAccProviders,
CheckDestroy: testAccCheckEIPDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccEIPConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckEIPExists(
"alicloud_eip.foo", &eip),
testAccCheckEIPAttributes(&eip),
),
},
resource.TestStep{
Config: testAccEIPConfigTwo,
Check: resource.ComposeTestCheckFunc(
testAccCheckEIPExists(
"alicloud_eip.foo", &eip),
testAccCheckEIPAttributes(&eip),
resource.TestCheckResourceAttr(
"alicloud_eip.foo",
"bandwidth",
"10"),
),
},
},
})
}
func testAccCheckEIPExists(n string, eip *ecs.EipAddressSetType) 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 EIP ID is set")
}
client := testAccProvider.Meta().(*AliyunClient)
d, err := client.DescribeEipAddress(rs.Primary.ID)
log.Printf("[WARN] eip id %#v", rs.Primary.ID)
if err != nil {
return err
}
if d == nil || d.IpAddress == "" {
return fmt.Errorf("EIP not found")
}
*eip = *d
return nil
}
}
func testAccCheckEIPAttributes(eip *ecs.EipAddressSetType) resource.TestCheckFunc {
return func(s *terraform.State) error {
if eip.IpAddress == "" {
return fmt.Errorf("Empty Ip address")
}
return nil
}
}
func testAccCheckEIPDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*AliyunClient)
for _, rs := range s.RootModule().Resources {
if rs.Type != "alicloud_eip" {
continue
}
// Try to find the EIP
conn := client.ecsconn
args := &ecs.DescribeEipAddressesArgs{
RegionId: client.Region,
AllocationId: rs.Primary.ID,
}
d, _, err := conn.DescribeEipAddresses(args)
if d != nil && len(d) > 0 {
return fmt.Errorf("Error EIP still exist")
}
// Verify the error is what we want
if err != nil {
return err
}
}
return nil
}
const testAccEIPConfig = `
resource "alicloud_eip" "foo" {
}
`
const testAccEIPConfigTwo = `
resource "alicloud_eip" "foo" {
bandwidth = "10"
internet_charge_type = "PayByBandwidth"
}
`

View File

@ -1,320 +0,0 @@
package alicloud
import (
"fmt"
"github.com/denverdino/aliyungo/common"
"github.com/denverdino/aliyungo/ecs"
"github.com/denverdino/aliyungo/ess"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"strings"
"time"
)
func resourceAlicloudEssScalingConfiguration() *schema.Resource {
return &schema.Resource{
Create: resourceAliyunEssScalingConfigurationCreate,
Read: resourceAliyunEssScalingConfigurationRead,
Update: resourceAliyunEssScalingConfigurationUpdate,
Delete: resourceAliyunEssScalingConfigurationDelete,
Schema: map[string]*schema.Schema{
"active": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"enable": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
},
"scaling_group_id": &schema.Schema{
Type: schema.TypeString,
ForceNew: true,
Required: true,
},
"image_id": &schema.Schema{
Type: schema.TypeString,
ForceNew: true,
Required: true,
},
"instance_type": &schema.Schema{
Type: schema.TypeString,
ForceNew: true,
Required: true,
},
"io_optimized": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateIoOptimized,
},
"security_group_id": &schema.Schema{
Type: schema.TypeString,
ForceNew: true,
Required: true,
},
"scaling_configuration_name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"internet_charge_type": &schema.Schema{
Type: schema.TypeString,
ForceNew: true,
Optional: true,
Computed: true,
ValidateFunc: validateInternetChargeType,
},
"internet_max_bandwidth_in": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
Computed: true,
},
"internet_max_bandwidth_out": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
ValidateFunc: validateInternetMaxBandWidthOut,
},
"system_disk_category": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
ValidateFunc: validateAllowedStringValue([]string{
string(ecs.DiskCategoryCloud),
string(ecs.DiskCategoryCloudSSD),
string(ecs.DiskCategoryCloudEfficiency),
string(ecs.DiskCategoryEphemeralSSD),
}),
},
"data_disk": &schema.Schema{
Optional: true,
ForceNew: true,
Type: schema.TypeList,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"size": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
},
"category": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"snapshot_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"device": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
},
},
},
"instance_ids": &schema.Schema{
Type: schema.TypeList,
Elem: &schema.Schema{Type: schema.TypeString},
Optional: true,
MaxItems: 20,
},
},
}
}
func resourceAliyunEssScalingConfigurationCreate(d *schema.ResourceData, meta interface{}) error {
args, err := buildAlicloudEssScalingConfigurationArgs(d, meta)
if err != nil {
return err
}
essconn := meta.(*AliyunClient).essconn
scaling, err := essconn.CreateScalingConfiguration(args)
if err != nil {
return err
}
d.SetId(d.Get("scaling_group_id").(string) + COLON_SEPARATED + scaling.ScalingConfigurationId)
return resourceAliyunEssScalingConfigurationUpdate(d, meta)
}
func resourceAliyunEssScalingConfigurationUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*AliyunClient)
if d.HasChange("active") {
active := d.Get("active").(bool)
if !active {
return fmt.Errorf("Please active the scaling configuration directly.")
}
ids := strings.Split(d.Id(), COLON_SEPARATED)
err := client.ActiveScalingConfigurationById(ids[0], ids[1])
if err != nil {
return fmt.Errorf("Active scaling configuration %s err: %#v", ids[1], err)
}
}
if err := enableEssScalingConfiguration(d, meta); err != nil {
return err
}
return resourceAliyunEssScalingConfigurationRead(d, meta)
}
func enableEssScalingConfiguration(d *schema.ResourceData, meta interface{}) error {
client := meta.(*AliyunClient)
ids := strings.Split(d.Id(), COLON_SEPARATED)
if d.HasChange("enable") {
d.SetPartial("enable")
enable := d.Get("enable").(bool)
if !enable {
err := client.DisableScalingConfigurationById(ids[0])
if err != nil {
return fmt.Errorf("Disable scaling group %s err: %#v", ids[0], err)
}
}
instance_ids := []string{}
if d.HasChange("instance_ids") {
d.SetPartial("instance_ids")
instances := d.Get("instance_ids").([]interface{})
instance_ids = expandStringList(instances)
}
err := client.EnableScalingConfigurationById(ids[0], ids[1], instance_ids)
if err != nil {
return fmt.Errorf("Enable scaling configuration %s err: %#v", ids[1], err)
}
}
return nil
}
func resourceAliyunEssScalingConfigurationRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*AliyunClient)
ids := strings.Split(d.Id(), COLON_SEPARATED)
c, err := client.DescribeScalingConfigurationById(ids[0], ids[1])
if err != nil {
if e, ok := err.(*common.Error); ok && e.Code == InstanceNotfound {
d.SetId("")
return nil
}
return fmt.Errorf("Error Describe ESS scaling configuration Attribute: %#v", err)
}
d.Set("scaling_group_id", c.ScalingGroupId)
d.Set("active", c.LifecycleState == ess.Active)
d.Set("image_id", c.ImageId)
d.Set("instance_type", c.InstanceType)
d.Set("io_optimized", c.IoOptimized)
d.Set("security_group_id", c.SecurityGroupId)
d.Set("scaling_configuration_name", c.ScalingConfigurationName)
d.Set("internet_charge_type", c.InternetChargeType)
d.Set("internet_max_bandwidth_in", c.InternetMaxBandwidthIn)
d.Set("internet_max_bandwidth_out", c.InternetMaxBandwidthOut)
d.Set("system_disk_category", c.SystemDiskCategory)
d.Set("data_disk", flattenDataDiskMappings(c.DataDisks.DataDisk))
return nil
}
func resourceAliyunEssScalingConfigurationDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*AliyunClient)
return resource.Retry(5*time.Minute, func() *resource.RetryError {
ids := strings.Split(d.Id(), COLON_SEPARATED)
err := client.DeleteScalingConfigurationById(ids[0], ids[1])
if err != nil {
e, _ := err.(*common.Error)
if e.ErrorResponse.Code == IncorrectScalingConfigurationLifecycleState {
return resource.NonRetryableError(
fmt.Errorf("Scaling configuration is active - please active another one and trying again."))
}
if e.ErrorResponse.Code != InvalidScalingGroupIdNotFound {
return resource.RetryableError(
fmt.Errorf("Scaling configuration in use - trying again while it is deleted."))
}
}
_, err = client.DescribeScalingConfigurationById(ids[0], ids[1])
if err != nil {
if notFoundError(err) {
return nil
}
return resource.NonRetryableError(err)
}
return resource.RetryableError(
fmt.Errorf("Scaling configuration in use - trying again while it is deleted."))
})
}
func buildAlicloudEssScalingConfigurationArgs(d *schema.ResourceData, meta interface{}) (*ess.CreateScalingConfigurationArgs, error) {
args := &ess.CreateScalingConfigurationArgs{
ScalingGroupId: d.Get("scaling_group_id").(string),
ImageId: d.Get("image_id").(string),
InstanceType: d.Get("instance_type").(string),
IoOptimized: ecs.IoOptimized(d.Get("io_optimized").(string)),
SecurityGroupId: d.Get("security_group_id").(string),
}
if v := d.Get("scaling_configuration_name").(string); v != "" {
args.ScalingConfigurationName = v
}
if v := d.Get("internet_charge_type").(string); v != "" {
args.InternetChargeType = common.InternetChargeType(v)
}
if v := d.Get("internet_max_bandwidth_in").(int); v != 0 {
args.InternetMaxBandwidthIn = v
}
if v := d.Get("internet_max_bandwidth_out").(int); v != 0 {
args.InternetMaxBandwidthOut = v
}
if v := d.Get("system_disk_category").(string); v != "" {
args.SystemDisk_Category = common.UnderlineString(v)
}
dds, ok := d.GetOk("data_disk")
if ok {
disks := dds.([]interface{})
diskTypes := []ess.DataDiskType{}
for _, e := range disks {
pack := e.(map[string]interface{})
disk := ess.DataDiskType{
Size: pack["size"].(int),
Category: pack["category"].(string),
SnapshotId: pack["snapshot_id"].(string),
Device: pack["device"].(string),
}
if v := pack["size"].(int); v != 0 {
disk.Size = v
}
if v := pack["category"].(string); v != "" {
disk.Category = v
}
if v := pack["snapshot_id"].(string); v != "" {
disk.SnapshotId = v
}
if v := pack["device"].(string); v != "" {
disk.Device = v
}
diskTypes = append(diskTypes, disk)
}
args.DataDisk = diskTypes
}
return args, nil
}

View File

@ -1,495 +0,0 @@
package alicloud
import (
"fmt"
"github.com/denverdino/aliyungo/common"
"github.com/denverdino/aliyungo/ess"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"log"
"regexp"
"strings"
"testing"
)
func TestAccAlicloudEssScalingConfiguration_basic(t *testing.T) {
var sc ess.ScalingConfigurationItemType
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
// module name
IDRefreshName: "alicloud_ess_scaling_configuration.foo",
Providers: testAccProviders,
CheckDestroy: testAccCheckEssScalingConfigurationDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccEssScalingConfigurationConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckEssScalingConfigurationExists(
"alicloud_ess_scaling_configuration.foo", &sc),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_configuration.foo",
"instance_type",
"ecs.s2.large"),
resource.TestMatchResourceAttr(
"alicloud_ess_scaling_configuration.foo",
"image_id",
regexp.MustCompile("^centos_6")),
),
},
},
})
}
func TestAccAlicloudEssScalingConfiguration_multiConfig(t *testing.T) {
var sc ess.ScalingConfigurationItemType
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
// module name
IDRefreshName: "alicloud_ess_scaling_configuration.bar",
Providers: testAccProviders,
CheckDestroy: testAccCheckEssScalingConfigurationDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccEssScalingConfiguration_multiConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckEssScalingConfigurationExists(
"alicloud_ess_scaling_configuration.bar", &sc),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_configuration.bar",
"active",
"false"),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_configuration.bar",
"instance_type",
"ecs.s2.large"),
resource.TestMatchResourceAttr(
"alicloud_ess_scaling_configuration.bar",
"image_id",
regexp.MustCompile("^centos_6")),
),
},
},
})
}
func SkipTestAccAlicloudEssScalingConfiguration_active(t *testing.T) {
var sc ess.ScalingConfigurationItemType
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
// module name
IDRefreshName: "alicloud_ess_scaling_configuration.bar",
Providers: testAccProviders,
CheckDestroy: testAccCheckEssScalingConfigurationDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccEssScalingConfiguration_active,
Check: resource.ComposeTestCheckFunc(
testAccCheckEssScalingConfigurationExists(
"alicloud_ess_scaling_configuration.bar", &sc),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_configuration.bar",
"active",
"true"),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_configuration.bar",
"instance_type",
"ecs.s2.large"),
resource.TestMatchResourceAttr(
"alicloud_ess_scaling_configuration.bar",
"image_id",
regexp.MustCompile("^centos_6")),
),
},
resource.TestStep{
Config: testAccEssScalingConfiguration_inActive,
Check: resource.ComposeTestCheckFunc(
testAccCheckEssScalingConfigurationExists(
"alicloud_ess_scaling_configuration.bar", &sc),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_configuration.bar",
"active",
"false"),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_configuration.bar",
"instance_type",
"ecs.s2.large"),
resource.TestMatchResourceAttr(
"alicloud_ess_scaling_configuration.bar",
"image_id",
regexp.MustCompile("^centos_6")),
),
},
},
})
}
func SkipTestAccAlicloudEssScalingConfiguration_enable(t *testing.T) {
var sc ess.ScalingConfigurationItemType
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
// module name
IDRefreshName: "alicloud_ess_scaling_configuration.foo",
Providers: testAccProviders,
CheckDestroy: testAccCheckEssScalingConfigurationDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccEssScalingConfiguration_enable,
Check: resource.ComposeTestCheckFunc(
testAccCheckEssScalingConfigurationExists(
"alicloud_ess_scaling_configuration.foo", &sc),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_configuration.foo",
"enable",
"true"),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_configuration.foo",
"instance_type",
"ecs.s2.large"),
resource.TestMatchResourceAttr(
"alicloud_ess_scaling_configuration.foo",
"image_id",
regexp.MustCompile("^centos_6")),
),
},
resource.TestStep{
Config: testAccEssScalingConfiguration_disable,
Check: resource.ComposeTestCheckFunc(
testAccCheckEssScalingConfigurationExists(
"alicloud_ess_scaling_configuration.foo", &sc),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_configuration.foo",
"enable",
"false"),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_configuration.foo",
"instance_type",
"ecs.s2.large"),
resource.TestMatchResourceAttr(
"alicloud_ess_scaling_configuration.foo",
"image_id",
regexp.MustCompile("^centos_6")),
),
},
},
})
}
func testAccCheckEssScalingConfigurationExists(n string, d *ess.ScalingConfigurationItemType) 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 ESS Scaling Configuration ID is set")
}
client := testAccProvider.Meta().(*AliyunClient)
ids := strings.Split(rs.Primary.ID, COLON_SEPARATED)
attr, err := client.DescribeScalingConfigurationById(ids[0], ids[1])
log.Printf("[DEBUG] check scaling configuration %s attribute %#v", rs.Primary.ID, attr)
if err != nil {
return err
}
if attr == nil {
return fmt.Errorf("Scaling Configuration not found")
}
*d = *attr
return nil
}
}
func testAccCheckEssScalingConfigurationDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*AliyunClient)
for _, rs := range s.RootModule().Resources {
if rs.Type != "alicloud_ess_scaling_configuration" {
continue
}
ids := strings.Split(rs.Primary.ID, COLON_SEPARATED)
ins, err := client.DescribeScalingConfigurationById(ids[0], ids[1])
if ins != nil {
return fmt.Errorf("Error ESS scaling configuration 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 testAccEssScalingConfigurationConfig = `
data "alicloud_images" "ecs_image" {
most_recent = true
name_regex = "^centos_6\\w{1,5}[64].*"
}
resource "alicloud_security_group" "tf_test_foo" {
description = "foo"
}
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_ess_scaling_group" "foo" {
min_size = 1
max_size = 1
scaling_group_name = "foo"
removal_policies = ["OldestInstance", "NewestInstance"]
}
resource "alicloud_ess_scaling_configuration" "foo" {
scaling_group_id = "${alicloud_ess_scaling_group.foo.id}"
image_id = "${data.alicloud_images.ecs_image.images.0.id}"
instance_type = "ecs.s2.large"
io_optimized = "optimized"
security_group_id = "${alicloud_security_group.tf_test_foo.id}"
}
`
const testAccEssScalingConfiguration_multiConfig = `
data "alicloud_images" "ecs_image" {
most_recent = true
name_regex = "^centos_6\\w{1,5}[64].*"
}
resource "alicloud_security_group" "tf_test_foo" {
description = "foo"
}
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_ess_scaling_group" "foo" {
min_size = 1
max_size = 1
scaling_group_name = "foo"
removal_policies = ["OldestInstance", "NewestInstance"]
}
resource "alicloud_ess_scaling_configuration" "foo" {
scaling_group_id = "${alicloud_ess_scaling_group.foo.id}"
image_id = "${data.alicloud_images.ecs_image.images.0.id}"
instance_type = "ecs.s2.large"
io_optimized = "optimized"
security_group_id = "${alicloud_security_group.tf_test_foo.id}"
}
resource "alicloud_ess_scaling_configuration" "bar" {
scaling_group_id = "${alicloud_ess_scaling_group.foo.id}"
image_id = "${data.alicloud_images.ecs_image.images.0.id}"
instance_type = "ecs.s2.large"
io_optimized = "optimized"
security_group_id = "${alicloud_security_group.tf_test_foo.id}"
}
`
const testAccEssScalingConfiguration_active = `
data "alicloud_images" "ecs_image" {
most_recent = true
name_regex = "^centos_6\\w{1,5}[64].*"
}
resource "alicloud_security_group" "tf_test_foo" {
description = "foo"
}
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_ess_scaling_group" "foo" {
min_size = 1
max_size = 1
scaling_group_name = "foo"
removal_policies = ["OldestInstance", "NewestInstance"]
}
resource "alicloud_ess_scaling_configuration" "foo" {
scaling_group_id = "${alicloud_ess_scaling_group.foo.id}"
active = true
image_id = "${data.alicloud_images.ecs_image.images.0.id}"
instance_type = "ecs.s2.large"
io_optimized = "optimized"
security_group_id = "${alicloud_security_group.tf_test_foo.id}"
}
`
const testAccEssScalingConfiguration_inActive = `
data "alicloud_images" "ecs_image" {
most_recent = true
name_regex = "^centos_6\\w{1,5}[64].*"
}
resource "alicloud_security_group" "tf_test_foo" {
description = "foo"
}
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_ess_scaling_group" "foo" {
min_size = 1
max_size = 1
scaling_group_name = "foo"
removal_policies = ["OldestInstance", "NewestInstance"]
}
resource "alicloud_ess_scaling_configuration" "foo" {
scaling_group_id = "${alicloud_ess_scaling_group.foo.id}"
active = false
image_id = "${data.alicloud_images.ecs_image.images.0.id}"
instance_type = "ecs.s2.large"
io_optimized = "optimized"
security_group_id = "${alicloud_security_group.tf_test_foo.id}"
}
`
const testAccEssScalingConfiguration_enable = `
data "alicloud_images" "ecs_image" {
most_recent = true
name_regex = "^centos_6\\w{1,5}[64].*"
}
resource "alicloud_security_group" "tf_test_foo" {
description = "foo"
}
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_ess_scaling_group" "foo" {
min_size = 1
max_size = 1
scaling_group_name = "foo"
removal_policies = ["OldestInstance", "NewestInstance"]
}
resource "alicloud_ess_scaling_configuration" "foo" {
scaling_group_id = "${alicloud_ess_scaling_group.foo.id}"
enable = true
image_id = "${data.alicloud_images.ecs_image.images.0.id}"
instance_type = "ecs.s2.large"
io_optimized = "optimized"
security_group_id = "${alicloud_security_group.tf_test_foo.id}"
}
`
const testAccEssScalingConfiguration_disable = `
data "alicloud_images" "ecs_image" {
most_recent = true
name_regex = "^centos_6\\w{1,5}[64].*"
}
resource "alicloud_security_group" "tf_test_foo" {
description = "foo"
}
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_ess_scaling_group" "foo" {
min_size = 1
max_size = 1
scaling_group_name = "foo"
removal_policies = ["OldestInstance", "NewestInstance"]
}
resource "alicloud_ess_scaling_configuration" "foo" {
scaling_group_id = "${alicloud_ess_scaling_group.foo.id}"
enable = false
image_id = "${data.alicloud_images.ecs_image.images.0.id}"
instance_type = "ecs.s2.large"
io_optimized = "optimized"
security_group_id = "${alicloud_security_group.tf_test_foo.id}"
}
`

View File

@ -1,209 +0,0 @@
package alicloud
import (
"fmt"
"github.com/denverdino/aliyungo/common"
"github.com/denverdino/aliyungo/ess"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"strings"
"time"
)
func resourceAlicloudEssScalingGroup() *schema.Resource {
return &schema.Resource{
Create: resourceAliyunEssScalingGroupCreate,
Read: resourceAliyunEssScalingGroupRead,
Update: resourceAliyunEssScalingGroupUpdate,
Delete: resourceAliyunEssScalingGroupDelete,
Schema: map[string]*schema.Schema{
"min_size": &schema.Schema{
Type: schema.TypeInt,
Required: true,
ValidateFunc: validateIntegerInRange(0, 100),
},
"max_size": &schema.Schema{
Type: schema.TypeInt,
Required: true,
ValidateFunc: validateIntegerInRange(0, 100),
},
"scaling_group_name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"default_cooldown": &schema.Schema{
Type: schema.TypeInt,
Default: 300,
Optional: true,
ValidateFunc: validateIntegerInRange(0, 86400),
},
"vswitch_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"removal_policies": &schema.Schema{
Type: schema.TypeList,
Elem: &schema.Schema{Type: schema.TypeString},
Optional: true,
MaxItems: 2,
},
"db_instance_ids": &schema.Schema{
Type: schema.TypeList,
Elem: &schema.Schema{Type: schema.TypeString},
Optional: true,
MaxItems: 3,
},
"loadbalancer_ids": &schema.Schema{
Type: schema.TypeList,
Elem: &schema.Schema{Type: schema.TypeString},
Optional: true,
},
},
}
}
func resourceAliyunEssScalingGroupCreate(d *schema.ResourceData, meta interface{}) error {
args, err := buildAlicloudEssScalingGroupArgs(d, meta)
if err != nil {
return err
}
essconn := meta.(*AliyunClient).essconn
scaling, err := essconn.CreateScalingGroup(args)
if err != nil {
return err
}
d.SetId(scaling.ScalingGroupId)
return resourceAliyunEssScalingGroupUpdate(d, meta)
}
func resourceAliyunEssScalingGroupRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*AliyunClient)
scaling, err := client.DescribeScalingGroupById(d.Id())
if err != nil {
if e, ok := err.(*common.Error); ok && e.Code == InstanceNotfound {
d.SetId("")
return nil
}
return fmt.Errorf("Error Describe ESS scaling group Attribute: %#v", err)
}
d.Set("min_size", scaling.MinSize)
d.Set("max_size", scaling.MaxSize)
d.Set("scaling_group_name", scaling.ScalingGroupName)
d.Set("default_cooldown", scaling.DefaultCooldown)
d.Set("removal_policies", scaling.RemovalPolicies)
d.Set("db_instance_ids", scaling.DBInstanceIds)
d.Set("loadbalancer_ids", scaling.LoadBalancerId)
return nil
}
func resourceAliyunEssScalingGroupUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AliyunClient).essconn
args := &ess.ModifyScalingGroupArgs{
ScalingGroupId: d.Id(),
}
if d.HasChange("scaling_group_name") {
args.ScalingGroupName = d.Get("scaling_group_name").(string)
}
if d.HasChange("min_size") {
args.MinSize = d.Get("min_size").(int)
}
if d.HasChange("max_size") {
args.MaxSize = d.Get("max_size").(int)
}
if d.HasChange("default_cooldown") {
args.DefaultCooldown = d.Get("default_cooldown").(int)
}
if d.HasChange("removal_policies") {
policyStrings := d.Get("removal_policies").([]interface{})
args.RemovalPolicy = expandStringList(policyStrings)
}
if _, err := conn.ModifyScalingGroup(args); err != nil {
return err
}
return resourceAliyunEssScalingGroupRead(d, meta)
}
func resourceAliyunEssScalingGroupDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*AliyunClient)
return resource.Retry(2*time.Minute, func() *resource.RetryError {
err := client.DeleteScalingGroupById(d.Id())
if err != nil {
e, _ := err.(*common.Error)
if e.ErrorResponse.Code != InvalidScalingGroupIdNotFound {
return resource.RetryableError(fmt.Errorf("Scaling group in use - trying again while it is deleted."))
}
}
_, err = client.DescribeScalingGroupById(d.Id())
if err != nil {
if notFoundError(err) {
return nil
}
return resource.NonRetryableError(err)
}
return resource.RetryableError(fmt.Errorf("Scaling group in use - trying again while it is deleted."))
})
}
func buildAlicloudEssScalingGroupArgs(d *schema.ResourceData, meta interface{}) (*ess.CreateScalingGroupArgs, error) {
client := meta.(*AliyunClient)
args := &ess.CreateScalingGroupArgs{
RegionId: getRegion(d, meta),
MinSize: d.Get("min_size").(int),
MaxSize: d.Get("max_size").(int),
DefaultCooldown: d.Get("default_cooldown").(int),
}
if v := d.Get("scaling_group_name").(string); v != "" {
args.ScalingGroupName = v
}
if v := d.Get("vswitch_id").(string); v != "" {
args.VSwitchId = v
// get vpcId
vpcId, err := client.GetVpcIdByVSwitchId(v)
if err != nil {
return nil, fmt.Errorf("VswitchId %s is not valid of current region", v)
}
// fill vpcId by vswitchId
args.VpcId = vpcId
}
dbs, ok := d.GetOk("db_instance_ids")
if ok {
dbsStrings := dbs.([]interface{})
args.DBInstanceId = expandStringList(dbsStrings)
}
lbs, ok := d.GetOk("loadbalancer_ids")
if ok {
lbsStrings := lbs.([]interface{})
args.LoadBalancerId = strings.Join(expandStringList(lbsStrings), COMMA_SEPARATED)
}
return args, nil
}

View File

@ -1,297 +0,0 @@
package alicloud
import (
"fmt"
"github.com/denverdino/aliyungo/common"
"github.com/denverdino/aliyungo/ess"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"log"
"testing"
)
func TestAccAlicloudEssScalingGroup_basic(t *testing.T) {
var sg ess.ScalingGroupItemType
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
// module name
IDRefreshName: "alicloud_ess_scaling_group.foo",
Providers: testAccProviders,
CheckDestroy: testAccCheckEssScalingGroupDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccEssScalingGroupConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckEssScalingGroupExists(
"alicloud_ess_scaling_group.foo", &sg),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_group.foo",
"min_size",
"1"),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_group.foo",
"max_size",
"1"),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_group.foo",
"scaling_group_name",
"foo"),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_group.foo",
"removal_policies.#",
"2",
),
),
},
},
})
}
func TestAccAlicloudEssScalingGroup_update(t *testing.T) {
var sg ess.ScalingGroupItemType
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
// module name
IDRefreshName: "alicloud_ess_scaling_group.foo",
Providers: testAccProviders,
CheckDestroy: testAccCheckEssScalingGroupDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccEssScalingGroup,
Check: resource.ComposeTestCheckFunc(
testAccCheckEssScalingGroupExists(
"alicloud_ess_scaling_group.foo", &sg),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_group.foo",
"min_size",
"1"),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_group.foo",
"max_size",
"1"),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_group.foo",
"scaling_group_name",
"foo"),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_group.foo",
"removal_policies.#",
"2",
),
),
},
resource.TestStep{
Config: testAccEssScalingGroup_update,
Check: resource.ComposeTestCheckFunc(
testAccCheckEssScalingGroupExists(
"alicloud_ess_scaling_group.foo", &sg),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_group.foo",
"min_size",
"2"),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_group.foo",
"max_size",
"2"),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_group.foo",
"scaling_group_name",
"update"),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_group.foo",
"removal_policies.#",
"1",
),
),
},
},
})
}
func SkipTestAccAlicloudEssScalingGroup_vpc(t *testing.T) {
var sg ess.ScalingGroupItemType
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
// module name
IDRefreshName: "alicloud_ess_scaling_group.foo",
Providers: testAccProviders,
CheckDestroy: testAccCheckEssScalingGroupDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccEssScalingGroup_vpc,
Check: resource.ComposeTestCheckFunc(
testAccCheckEssScalingGroupExists(
"alicloud_ess_scaling_group.foo", &sg),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_group.foo",
"min_size",
"1"),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_group.foo",
"max_size",
"1"),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_group.foo",
"scaling_group_name",
"foo"),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_group.foo",
"removal_policies.#",
"2",
),
),
},
},
})
}
func testAccCheckEssScalingGroupExists(n string, d *ess.ScalingGroupItemType) 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 ESS Scaling Group ID is set")
}
client := testAccProvider.Meta().(*AliyunClient)
attr, err := client.DescribeScalingGroupById(rs.Primary.ID)
log.Printf("[DEBUG] check scaling group %s attribute %#v", rs.Primary.ID, attr)
if err != nil {
return err
}
if attr == nil {
return fmt.Errorf("Scaling Group not found")
}
*d = *attr
return nil
}
}
func testAccCheckEssScalingGroupDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*AliyunClient)
for _, rs := range s.RootModule().Resources {
if rs.Type != "alicloud_ess_scaling_group" {
continue
}
ins, err := client.DescribeScalingGroupById(rs.Primary.ID)
if ins != nil {
return fmt.Errorf("Error ESS scaling group 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 testAccEssScalingGroupConfig = `
resource "alicloud_ess_scaling_group" "foo" {
min_size = 1
max_size = 1
scaling_group_name = "foo"
removal_policies = ["OldestInstance", "NewestInstance"]
}
`
const testAccEssScalingGroup = `
resource "alicloud_ess_scaling_group" "foo" {
min_size = 1
max_size = 1
scaling_group_name = "foo"
removal_policies = ["OldestInstance", "NewestInstance"]
}
`
const testAccEssScalingGroup_update = `
resource "alicloud_ess_scaling_group" "foo" {
min_size = 2
max_size = 2
scaling_group_name = "update"
removal_policies = ["OldestInstance"]
}
`
const testAccEssScalingGroup_vpc = `
data "alicloud_images" "ecs_image" {
most_recent = true
name_regex = "^centos_6\\w{1,5}[64].*"
}
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"
}
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_security_group" "tf_test_foo" {
description = "foo"
vpc_id = "${alicloud_vpc.foo.id}"
}
resource "alicloud_ess_scaling_group" "foo" {
min_size = 1
max_size = 1
scaling_group_name = "foo"
default_cooldown = 20
vswitch_id = "${alicloud_vswitch.foo.id}"
removal_policies = ["OldestInstance", "NewestInstance"]
}
resource "alicloud_ess_scaling_configuration" "foo" {
scaling_group_id = "${alicloud_ess_scaling_group.foo.id}"
enable = true
image_id = "${data.alicloud_images.ecs_image.images.0.id}"
instance_type = "ecs.n1.medium"
io_optimized = "optimized"
system_disk_category = "cloud_efficiency"
internet_charge_type = "PayByTraffic"
internet_max_bandwidth_out = 10
security_group_id = "${alicloud_security_group.tf_test_foo.id}"
}
`

View File

@ -1,168 +0,0 @@
package alicloud
import (
"fmt"
"github.com/denverdino/aliyungo/common"
"github.com/denverdino/aliyungo/ess"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"strings"
"time"
)
func resourceAlicloudEssScalingRule() *schema.Resource {
return &schema.Resource{
Create: resourceAliyunEssScalingRuleCreate,
Read: resourceAliyunEssScalingRuleRead,
Update: resourceAliyunEssScalingRuleUpdate,
Delete: resourceAliyunEssScalingRuleDelete,
Schema: map[string]*schema.Schema{
"scaling_group_id": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"adjustment_type": &schema.Schema{
Type: schema.TypeString,
Required: true,
ValidateFunc: validateAllowedStringValue([]string{string(ess.QuantityChangeInCapacity),
string(ess.PercentChangeInCapacity), string(ess.TotalCapacity)}),
},
"adjustment_value": &schema.Schema{
Type: schema.TypeInt,
Required: true,
},
"scaling_rule_name": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Optional: true,
},
"ari": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"cooldown": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
ValidateFunc: validateIntegerInRange(0, 86400),
},
},
}
}
func resourceAliyunEssScalingRuleCreate(d *schema.ResourceData, meta interface{}) error {
args, err := buildAlicloudEssScalingRuleArgs(d, meta)
if err != nil {
return err
}
essconn := meta.(*AliyunClient).essconn
rule, err := essconn.CreateScalingRule(args)
if err != nil {
return err
}
d.SetId(d.Get("scaling_group_id").(string) + COLON_SEPARATED + rule.ScalingRuleId)
return resourceAliyunEssScalingRuleUpdate(d, meta)
}
func resourceAliyunEssScalingRuleRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*AliyunClient)
ids := strings.Split(d.Id(), COLON_SEPARATED)
rule, err := client.DescribeScalingRuleById(ids[0], ids[1])
if err != nil {
if e, ok := err.(*common.Error); ok && e.Code == InstanceNotfound {
d.SetId("")
return nil
}
return fmt.Errorf("Error Describe ESS scaling rule Attribute: %#v", err)
}
d.Set("scaling_group_id", rule.ScalingGroupId)
d.Set("ari", rule.ScalingRuleAri)
d.Set("adjustment_type", rule.AdjustmentType)
d.Set("adjustment_value", rule.AdjustmentValue)
d.Set("scaling_rule_name", rule.ScalingRuleName)
d.Set("cooldown", rule.Cooldown)
return nil
}
func resourceAliyunEssScalingRuleDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*AliyunClient)
ids := strings.Split(d.Id(), COLON_SEPARATED)
return resource.Retry(2*time.Minute, func() *resource.RetryError {
err := client.DeleteScalingRuleById(ids[1])
if err != nil {
return resource.RetryableError(fmt.Errorf("Scaling rule in use - trying again while it is deleted."))
}
_, err = client.DescribeScalingRuleById(ids[0], ids[1])
if err != nil {
if notFoundError(err) {
return nil
}
return resource.NonRetryableError(err)
}
return resource.RetryableError(fmt.Errorf("Scaling rule in use - trying again while it is deleted."))
})
}
func resourceAliyunEssScalingRuleUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AliyunClient).essconn
ids := strings.Split(d.Id(), COLON_SEPARATED)
args := &ess.ModifyScalingRuleArgs{
ScalingRuleId: ids[1],
}
if d.HasChange("adjustment_type") {
args.AdjustmentType = ess.AdjustmentType(d.Get("adjustment_type").(string))
}
if d.HasChange("adjustment_value") {
args.AdjustmentValue = d.Get("adjustment_value").(int)
}
if d.HasChange("scaling_rule_name") {
args.ScalingRuleName = d.Get("scaling_rule_name").(string)
}
if d.HasChange("cooldown") {
args.Cooldown = d.Get("cooldown").(int)
}
if _, err := conn.ModifyScalingRule(args); err != nil {
return err
}
return resourceAliyunEssScalingRuleRead(d, meta)
}
func buildAlicloudEssScalingRuleArgs(d *schema.ResourceData, meta interface{}) (*ess.CreateScalingRuleArgs, error) {
args := &ess.CreateScalingRuleArgs{
RegionId: getRegion(d, meta),
ScalingGroupId: d.Get("scaling_group_id").(string),
AdjustmentType: ess.AdjustmentType(d.Get("adjustment_type").(string)),
AdjustmentValue: d.Get("adjustment_value").(int),
}
if v := d.Get("scaling_rule_name").(string); v != "" {
args.ScalingRuleName = v
}
if v := d.Get("cooldown").(int); v != 0 {
args.Cooldown = v
}
return args, nil
}

View File

@ -1,290 +0,0 @@
package alicloud
import (
"fmt"
"github.com/denverdino/aliyungo/common"
"github.com/denverdino/aliyungo/ess"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"log"
"strings"
"testing"
)
func TestAccAlicloudEssScalingRule_basic(t *testing.T) {
var sc ess.ScalingRuleItemType
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
// module name
IDRefreshName: "alicloud_ess_scaling_rule.foo",
Providers: testAccProviders,
CheckDestroy: testAccCheckEssScalingRuleDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccEssScalingRuleConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckEssScalingRuleExists(
"alicloud_ess_scaling_rule.foo", &sc),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_rule.foo",
"adjustment_type",
"TotalCapacity"),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_rule.foo",
"adjustment_value",
"1"),
),
},
},
})
}
func TestAccAlicloudEssScalingRule_update(t *testing.T) {
var sc ess.ScalingRuleItemType
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
// module name
IDRefreshName: "alicloud_ess_scaling_rule.foo",
Providers: testAccProviders,
CheckDestroy: testAccCheckEssScalingRuleDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccEssScalingRule,
Check: resource.ComposeTestCheckFunc(
testAccCheckEssScalingRuleExists(
"alicloud_ess_scaling_rule.foo", &sc),
testAccCheckEssScalingRuleExists(
"alicloud_ess_scaling_rule.foo", &sc),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_rule.foo",
"adjustment_type",
"TotalCapacity"),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_rule.foo",
"adjustment_value",
"1"),
),
},
resource.TestStep{
Config: testAccEssScalingRule_update,
Check: resource.ComposeTestCheckFunc(
testAccCheckEssScalingRuleExists(
"alicloud_ess_scaling_rule.foo", &sc),
testAccCheckEssScalingRuleExists(
"alicloud_ess_scaling_rule.foo", &sc),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_rule.foo",
"adjustment_type",
"TotalCapacity"),
resource.TestCheckResourceAttr(
"alicloud_ess_scaling_rule.foo",
"adjustment_value",
"2"),
),
},
},
})
}
func testAccCheckEssScalingRuleExists(n string, d *ess.ScalingRuleItemType) 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 ESS Scaling Rule ID is set")
}
client := testAccProvider.Meta().(*AliyunClient)
ids := strings.Split(rs.Primary.ID, COLON_SEPARATED)
attr, err := client.DescribeScalingRuleById(ids[0], ids[1])
log.Printf("[DEBUG] check scaling rule %s attribute %#v", rs.Primary.ID, attr)
if err != nil {
return err
}
if attr == nil {
return fmt.Errorf("Scaling rule not found")
}
*d = *attr
return nil
}
}
func testAccCheckEssScalingRuleDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*AliyunClient)
for _, rs := range s.RootModule().Resources {
if rs.Type != "alicloud_ess_scaling_rule" {
continue
}
ids := strings.Split(rs.Primary.ID, COLON_SEPARATED)
ins, err := client.DescribeScalingRuleById(ids[0], ids[1])
if ins != nil {
return fmt.Errorf("Error ESS scaling rule 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 testAccEssScalingRuleConfig = `
data "alicloud_images" "ecs_image" {
most_recent = true
name_regex = "^centos_6\\w{1,5}[64].*"
}
resource "alicloud_security_group" "tf_test_foo" {
description = "foo"
}
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_ess_scaling_group" "bar" {
min_size = 1
max_size = 1
scaling_group_name = "bar"
removal_policies = ["OldestInstance", "NewestInstance"]
}
resource "alicloud_ess_scaling_configuration" "foo" {
scaling_group_id = "${alicloud_ess_scaling_group.bar.id}"
image_id = "${data.alicloud_images.ecs_image.images.0.id}"
instance_type = "ecs.s2.large"
io_optimized = "optimized"
security_group_id = "${alicloud_security_group.tf_test_foo.id}"
}
resource "alicloud_ess_scaling_rule" "foo" {
scaling_group_id = "${alicloud_ess_scaling_group.bar.id}"
adjustment_type = "TotalCapacity"
adjustment_value = 1
cooldown = 120
}
`
const testAccEssScalingRule = `
data "alicloud_images" "ecs_image" {
most_recent = true
name_regex = "^centos_6\\w{1,5}[64].*"
}
resource "alicloud_security_group" "tf_test_foo" {
description = "foo"
}
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_ess_scaling_group" "bar" {
min_size = 1
max_size = 1
scaling_group_name = "bar"
removal_policies = ["OldestInstance", "NewestInstance"]
}
resource "alicloud_ess_scaling_configuration" "foo" {
scaling_group_id = "${alicloud_ess_scaling_group.bar.id}"
image_id = "${data.alicloud_images.ecs_image.images.0.id}"
instance_type = "ecs.s2.large"
io_optimized = "optimized"
security_group_id = "${alicloud_security_group.tf_test_foo.id}"
}
resource "alicloud_ess_scaling_rule" "foo" {
scaling_group_id = "${alicloud_ess_scaling_group.bar.id}"
adjustment_type = "TotalCapacity"
adjustment_value = 1
cooldown = 120
}
`
const testAccEssScalingRule_update = `
data "alicloud_images" "ecs_image" {
most_recent = true
name_regex = "^centos_6\\w{1,5}[64].*"
}
resource "alicloud_security_group" "tf_test_foo" {
description = "foo"
}
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_ess_scaling_group" "bar" {
min_size = 1
max_size = 1
scaling_group_name = "bar"
removal_policies = ["OldestInstance", "NewestInstance"]
}
resource "alicloud_ess_scaling_configuration" "foo" {
scaling_group_id = "${alicloud_ess_scaling_group.bar.id}"
image_id = "${data.alicloud_images.ecs_image.images.0.id}"
instance_type = "ecs.s2.large"
io_optimized = "optimized"
security_group_id = "${alicloud_security_group.tf_test_foo.id}"
}
resource "alicloud_ess_scaling_rule" "foo" {
scaling_group_id = "${alicloud_ess_scaling_group.bar.id}"
adjustment_type = "TotalCapacity"
adjustment_value = 2
cooldown = 60
}
`

Some files were not shown because too many files have changed in this diff Show More